예제 #1
0
REQUEST_NOTIFICATION_STATUS CNodeHttpModule::OnSendResponse(IN IHttpContext* pHttpContext, IN ISendResponseProvider* pProvider)
{
    if (NULL != pHttpContext && NULL != pProvider)
    {
        CNodeHttpStoredContext* ctx = (CNodeHttpStoredContext*)pHttpContext->GetModuleContextContainer()->GetModuleContext(this->applicationManager->GetModuleId());
        DWORD flags = pProvider->GetFlags();
        if (NULL != ctx && ctx->GetIsUpgrade() && !ctx->GetOpaqueFlagSet())
        {
            // Set opaque mode in HTTP.SYS to enable exchanging raw bytes.
            
            pProvider->SetFlags(flags | HTTP_SEND_RESPONSE_FLAG_OPAQUE);
            ctx->SetOpaqueFlag();
        }
    }

    return RQ_NOTIFICATION_CONTINUE;
}
예제 #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;
}