REQUEST_NOTIFICATION_STATUS CNodeHttpModule::OnAsyncCompletion(
	IHttpContext* pHttpContext, DWORD dwNotification, BOOL fPostNotification, IHttpEventProvider* pProvider, IHttpCompletionInfo* pCompletionInfo)
{
	if (NULL != pCompletionInfo && NULL != pHttpContext)
	{
		CNodeHttpStoredContext* ctx = (CNodeHttpStoredContext*)pHttpContext->GetModuleContextContainer()->GetModuleContext(this->applicationManager->GetModuleId());		

		ctx->IncreasePendingAsyncOperationCount();

		WCHAR message[256];
		wsprintfW(message, L"iisnode enters CNodeHttpModule::OnAsyncCompletion callback with request notification status of %d", ctx->GetRequestNotificationStatus());
		this->applicationManager->GetEventProvider()->Log(message, WINEVENT_LEVEL_VERBOSE, ctx->GetActivityId());

		ASYNC_CONTEXT* async = ctx->GetAsyncContext();
		if (NULL != async->completionProcessor)
		{
			async->completionProcessor(pCompletionInfo->GetCompletionStatus(), pCompletionInfo->GetCompletionBytes(), ctx->GetOverlapped());
		}

		wsprintfW(message, L"iisnode leaves CNodeHttpModule::OnAsyncCompletion callback with request notification status of %d", ctx->GetRequestNotificationStatus());
		this->applicationManager->GetEventProvider()->Log(message, WINEVENT_LEVEL_VERBOSE, ctx->GetActivityId());

		if (0 == ctx->DecreasePendingAsyncOperationCount()) // decreases ref count increased on entering OnAsyncCompletion
		{
			return ctx->GetRequestNotificationStatus();
		}
		else
		{
			return RQ_NOTIFICATION_PENDING;
		}
	}

	return RQ_NOTIFICATION_CONTINUE;
}
Esempio n. 2
0
REQUEST_NOTIFICATION_STATUS CNodeHttpModule::OnAsyncCompletion(
    IHttpContext* pHttpContext, DWORD dwNotification, BOOL fPostNotification, IHttpEventProvider* pProvider, IHttpCompletionInfo* pCompletionInfo)
{
    if (NULL != pCompletionInfo && NULL != pHttpContext)
    {
        CNodeHttpStoredContext* ctx = (CNodeHttpStoredContext*)pHttpContext->GetModuleContextContainer()->GetModuleContext(this->applicationManager->GetModuleId());

        if (ctx->GetIsUpgrade())
        {
            IHttpCompletionInfo2* pCompletionInfo2 = (IHttpCompletionInfo2*)pCompletionInfo;
            if (1 == pCompletionInfo2->GetCompletedOperation()) 
            {
                // This is completion of the read request for incoming bytes of an opaque byte stream after 101 Switching protocol response was sent

                ctx = ctx->GetUpgradeContext();
            }
        }

        ctx->IncreasePendingAsyncOperationCount();

        this->applicationManager->GetEventProvider()->Log(
            L"iisnode enters CNodeHttpModule::OnAsyncCompletion callback", 
            WINEVENT_LEVEL_VERBOSE, 
            ctx->GetActivityId());

        ASYNC_CONTEXT* async = ctx->GetAsyncContext();
        if (NULL != async->completionProcessor)
        {
            DWORD bytesCompleted = pCompletionInfo->GetCompletionBytes();
            if (async->completionProcessor == CProtocolBridge::SendResponseBodyCompleted)
            {
                bytesCompleted = async->bytesCompleteted;
                async->bytesCompleteted = 0;
            }
            async->completionProcessor(pCompletionInfo->GetCompletionStatus(), bytesCompleted, ctx->GetOverlapped());
            async->RunSynchronousContinuations();
        }

        long value = ctx->DecreasePendingAsyncOperationCount();

        REQUEST_NOTIFICATION_STATUS result = ctx->GetRequestNotificationStatus();

        if(ctx->GetIsUpgrade() && value == 0)
        {
            //
            // when the pending async count reaches 0,
            // need to return RQ_NOTIFICATION_CONTINUE 
            // to indicate websocket connection close.
            //
            result = RQ_NOTIFICATION_CONTINUE;
        }

        switch (result) 
        {
        default:
            this->applicationManager->GetEventProvider()->Log(
                L"iisnode leaves CNodeHttpModule::OnAsyncCompletion", 
                WINEVENT_LEVEL_VERBOSE, 
                ctx->GetActivityId());
            break;
        case RQ_NOTIFICATION_CONTINUE:
            this->applicationManager->GetEventProvider()->Log(
                L"iisnode leaves CNodeHttpModule::OnAsyncCompletion with RQ_NOTIFICATION_CONTINUE", 
                WINEVENT_LEVEL_VERBOSE, 
                ctx->GetActivityId());
            break;
        case RQ_NOTIFICATION_FINISH_REQUEST:
            this->applicationManager->GetEventProvider()->Log(
                L"iisnode leaves CNodeHttpModule::OnAsyncCompletion with RQ_NOTIFICATION_FINISH_REQUEST", 
                WINEVENT_LEVEL_VERBOSE, 
                ctx->GetActivityId());
            break;
        case RQ_NOTIFICATION_PENDING:
            this->applicationManager->GetEventProvider()->Log(
                L"iisnode leaves CNodeHttpModule::OnAsyncCompletion with RQ_NOTIFICATION_PENDING", 
                WINEVENT_LEVEL_VERBOSE, 
                ctx->GetActivityId());
            break;
        };

        return result;
    }

    return RQ_NOTIFICATION_CONTINUE;
}