websocket handler changes (#661)

add debug logging and reset connection in case of failure
This commit is contained in:
pan-wang 2018-03-13 16:05:32 -07:00 committed by GitHub
parent 02abb69cb2
commit 7a511d6a94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 61 additions and 24 deletions

View File

@ -398,6 +398,7 @@ REQUEST_NOTIFICATION_STATUS
BOOL fLocked = FALSE; BOOL fLocked = FALSE;
BOOL fClientError = FALSE; BOOL fClientError = FALSE;
BOOL fClosed = FALSE; BOOL fClosed = FALSE;
BOOL fWebSocketUpgrade = FALSE;
DBG_ASSERT(m_pW3Context != NULL); DBG_ASSERT(m_pW3Context != NULL);
__analysis_assume(m_pW3Context != NULL); __analysis_assume(m_pW3Context != NULL);
@ -467,7 +468,7 @@ REQUEST_NOTIFICATION_STATUS
goto Finished; goto Finished;
} }
hr = m_pWebSocket->ProcessRequest(this, m_pW3Context, m_hRequest); hr = m_pWebSocket->ProcessRequest(this, m_pW3Context, m_hRequest, &fWebSocketUpgrade);
if (FAILED(hr)) if (FAILED(hr))
{ {
goto Failure; goto Failure;

View File

@ -43,6 +43,7 @@ WEBSOCKET_HANDLER::WEBSOCKET_HANDLER() :
_dwOutstandingIo(0), _dwOutstandingIo(0),
_fCleanupInProgress(FALSE), _fCleanupInProgress(FALSE),
_fIndicateCompletionToIis(FALSE), _fIndicateCompletionToIis(FALSE),
_fHandleClosed(FALSE),
_fReceivedCloseMsg(FALSE) _fReceivedCloseMsg(FALSE)
{ {
DebugPrintf (ASPNETCORE_DEBUG_FLAG_INFO, "WEBSOCKET_HANDLER::WEBSOCKET_HANDLER"); DebugPrintf (ASPNETCORE_DEBUG_FLAG_INFO, "WEBSOCKET_HANDLER::WEBSOCKET_HANDLER");
@ -57,7 +58,8 @@ WEBSOCKET_HANDLER::Terminate(
) )
{ {
DebugPrintf (ASPNETCORE_DEBUG_FLAG_INFO, "WEBSOCKET_HANDLER::Terminate"); DebugPrintf (ASPNETCORE_DEBUG_FLAG_INFO, "WEBSOCKET_HANDLER::Terminate");
if (!_fHandleClosed)
{
RemoveRequest(); RemoveRequest();
_fCleanupInProgress = TRUE; _fCleanupInProgress = TRUE;
@ -76,6 +78,7 @@ WEBSOCKET_HANDLER::Terminate(
DeleteCriticalSection(&_RequestLock); DeleteCriticalSection(&_RequestLock);
delete this; delete this;
}
} }
//static //static
@ -161,10 +164,10 @@ WEBSOCKET_HANDLER::IncrementOutstandingIo(
VOID VOID
) )
{ {
InterlockedIncrement(&_dwOutstandingIo); LONG dwOutstandingIo = InterlockedIncrement(&_dwOutstandingIo);
if (sm_pTraceLog) if (sm_pTraceLog)
{ {
WriteRefTraceLog(sm_pTraceLog, _dwOutstandingIo, this); WriteRefTraceLog(sm_pTraceLog, dwOutstandingIo, this);
} }
} }
@ -208,25 +211,33 @@ WEBSOCKET_HANDLER::IndicateCompletionToIIS(
--*/ --*/
{ {
/*DebugPrintf (ASPNETCORE_DEBUG_FLAG_INFO, DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
"WEBSOCKET_HANDLER::IndicateCompletionToIIS");*/ "WEBSOCKET_HANDLER::IndicateCompletionToIIS called %d", _dwOutstandingIo);
_pHandler->SetStatus(FORWARDER_DONE); //
// do not call IndicateCompletion here
// wait for handle close callback and then call IndicateCompletion
// otherwise we may release W3Context too early and cause AV
//_pHttpContext->IndicateCompletion(RQ_NOTIFICATION_PENDING);
// close Websocket handle. This will triger a WinHttp callback // close Websocket handle. This will triger a WinHttp callback
// on handle close, then let IIS pipeline continue. // on handle close, then let IIS pipeline continue.
WinHttpCloseHandle(_hWebSocketRequest); // Make sure no pending IO as there is no IIS websocket cancelation,
// any unexpected callback will lead to AV. Revisit it once CanelOutGoingIO works
//
if (_hWebSocketRequest != NULL && _dwOutstandingIo == 0)
{
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
"WEBSOCKET_HANDLER::IndicateCompletionToIIS");
_pHandler->SetStatus(FORWARDER_DONE);
_fHandleClosed = TRUE;
WinHttpCloseHandle(_hWebSocketRequest);
_hWebSocketRequest = NULL;
}
} }
HRESULT HRESULT
WEBSOCKET_HANDLER::ProcessRequest( WEBSOCKET_HANDLER::ProcessRequest(
FORWARDING_HANDLER *pHandler, FORWARDING_HANDLER *pHandler,
IHttpContext *pHttpContext, IHttpContext *pHttpContext,
HINTERNET hRequest HINTERNET hRequest,
BOOL* pfHandleCreated
) )
/*++ /*++
@ -246,6 +257,7 @@ Routine Description:
HRESULT hr = S_OK; HRESULT hr = S_OK;
//DWORD dwBuffSize = RECEIVE_BUFFER_SIZE; //DWORD dwBuffSize = RECEIVE_BUFFER_SIZE;
*pfHandleCreated = FALSE;
_pHandler = pHandler; _pHandler = pHandler;
EnterCriticalSection(&_RequestLock); EnterCriticalSection(&_RequestLock);
@ -288,6 +300,8 @@ Routine Description:
goto Finished; goto Finished;
} }
*pfHandleCreated = TRUE;
// //
// Resize the send & receive buffers to be more conservative (and avoid DoS attacks). // Resize the send & receive buffers to be more conservative (and avoid DoS attacks).
// NOTE: The two WinHTTP options below were added for WinBlue, so we can't // NOTE: The two WinHTTP options below were added for WinBlue, so we can't
@ -453,7 +467,7 @@ Routine Description:
BOOL fClose = FALSE; BOOL fClose = FALSE;
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO, DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
"WEBSOCKET_HANDLER::DoIisWebSocketSend"); "WEBSOCKET_HANDLER::DoIisWebSocketSend %d", eBufferType);
if (eBufferType == WINHTTP_WEB_SOCKET_CLOSE_BUFFER_TYPE) if (eBufferType == WINHTTP_WEB_SOCKET_CLOSE_BUFFER_TYPE)
{ {
@ -492,7 +506,7 @@ Routine Description:
IncrementOutstandingIo(); IncrementOutstandingIo();
// //
// Backend end may start close hand shake first // Backend end may start close hand shake first
// Need to inidcate no more receive should be called on WinHttp conneciton // Need to indicate no more receive should be called on WinHttp connection
// //
_fReceivedCloseMsg = TRUE; _fReceivedCloseMsg = TRUE;
_fIndicateCompletionToIis = TRUE; _fIndicateCompletionToIis = TRUE;
@ -796,7 +810,7 @@ WEBSOCKET_HANDLER::OnWinHttpShutdownComplete(
) )
{ {
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO, DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
"WEBSOCKET_HANDLER::OnWinHttpShutdownComplete"); "WEBSOCKET_HANDLER::OnWinHttpShutdownComplete --%p", _pHandler);
DecrementOutstandingIo(); DecrementOutstandingIo();
@ -844,7 +858,7 @@ Routine Description:
CleanupReason cleanupReason = CleanupReasonUnknown; CleanupReason cleanupReason = CleanupReasonUnknown;
DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO, DebugPrintf(ASPNETCORE_DEBUG_FLAG_INFO,
"WEBSOCKET_HANDLER::OnWinHttpReceiveComplete"); "WEBSOCKET_HANDLER::OnWinHttpReceiveComplete --%p", _pHandler);
if (_fCleanupInProgress) if (_fCleanupInProgress)
{ {
@ -1051,7 +1065,7 @@ Finished:
Cleanup (cleanupReason); Cleanup (cleanupReason);
DebugPrintf (ASPNETCORE_DEBUG_FLAG_ERROR, DebugPrintf (ASPNETCORE_DEBUG_FLAG_ERROR,
"WEBSOCKET_HANDLER::OnIisSendComplete failed with HR=%08x", hr); "WEBSOCKET_HANDLER::OnIisReceiveComplete failed with HR=%08x", hr);
} }
// //
@ -1105,11 +1119,29 @@ Arguments:
// //
// TODO:: Raise FREB event with cleanup reason. // TODO:: Raise FREB event with cleanup reason.
// //
if (reason == ClientDisconnect || reason == ServerStateUnavailable)
{
//
// Calling shutdown to notify the backend about disonnect
//
WINHTTP_HELPER::sm_pfnWinHttpWebSocketShutdown(
_hWebSocketRequest,
1011, // indicate that a server is terminating the connection because it encountered
// an unexpected condition that prevent it from fulfilling the request
NULL, // Reason
0); // length og Reason
WinHttpCloseHandle(_hWebSocketRequest); }
_hWebSocketRequest = NULL;
_pHttpContext->CancelIo(); if (reason == ServerDisconnect || reason == ServerStateUnavailable)
{
_pHttpContext->CancelIo();
//
// CancelIo sometime may not be able to cannel pending websocket IO
// ResetConnection to force IISWebsocket module to release the pipeline
//
_pHttpContext->GetResponse()->ResetConnection();
}
Finished: Finished:
if (fLocked) if (fLocked)

View File

@ -40,7 +40,8 @@ public:
ProcessRequest( ProcessRequest(
FORWARDING_HANDLER *pHandler, FORWARDING_HANDLER *pHandler,
IHttpContext * pHttpContext, IHttpContext * pHttpContext,
HINTERNET hRequest HINTERNET hRequest,
BOOL* pfHandleCreated
); );
REQUEST_NOTIFICATION_STATUS REQUEST_NOTIFICATION_STATUS
@ -207,6 +208,9 @@ private:
volatile volatile
BOOL _fIndicateCompletionToIis; BOOL _fIndicateCompletionToIis;
volatile
BOOL _fHandleClosed;
volatile volatile
BOOL _fReceivedCloseMsg; BOOL _fReceivedCloseMsg;
@ -218,4 +222,4 @@ private:
static static
TRACE_LOG * sm_pTraceLog; TRACE_LOG * sm_pTraceLog;
}; };