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;
}
Exemple #2
0
REQUEST_NOTIFICATION_STATUS CNodeHttpModule::OnExecuteRequestHandler(
    IN IHttpContext* pHttpContext, 
    IN IHttpEventProvider* pProvider)
{
    HRESULT hr;
    CNodeHttpStoredContext* ctx = NULL;

    CheckError(this->applicationManager->Initialize(pHttpContext));

    this->applicationManager->GetEventProvider()->Log(L"iisnode received a new http request", WINEVENT_LEVEL_INFO);

    CheckError(this->applicationManager->Dispatch(pHttpContext, pProvider, &ctx));
    this->applicationManager->GetEventProvider()->Log(L"iisnode dispatched new http request", WINEVENT_LEVEL_INFO, ctx->GetActivityId());
    ASYNC_CONTEXT* async = ctx->GetAsyncContext();
    async->RunSynchronousContinuations();

    REQUEST_NOTIFICATION_STATUS result;
    if (0 == ctx->DecreasePendingAsyncOperationCount()) // decreases ref count set to 1 in the ctor of CNodeHttpStoredContext
    {
        result = ctx->GetRequestNotificationStatus();
    }
    else
    {
        result = RQ_NOTIFICATION_PENDING;
    }

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

    return result;

Error:

    CNodeEventProvider* log = this->applicationManager->GetEventProvider();

    if (log)
    {
        if (ctx)
        {
            log->Log(L"iisnode failed to process a new http request", WINEVENT_LEVEL_INFO, ctx->GetActivityId());
        }
        else
        {
            log->Log(L"iisnode failed to process a new http request", WINEVENT_LEVEL_INFO);
        }
    }

    if (ERROR_NOT_ENOUGH_QUOTA == hr)
    {
        CProtocolBridge::SendEmptyResponse(pHttpContext, 503, CNodeConstants::IISNODE_ERROR_NOT_ENOUGH_QUOTA, _T("Service Unavailable"), hr);
    }
    else if (ERROR_FILE_NOT_FOUND == hr)
    {
        CProtocolBridge::SendEmptyResponse(pHttpContext, 404, 0, _T("Not Found"), hr);
    }
    else if (ERROR_NOT_SUPPORTED == hr)
    {
        if (log)
        {
            log->Log(L"iisnode rejected websocket connection request", WINEVENT_LEVEL_INFO);
        }
        CProtocolBridge::SendEmptyResponse(pHttpContext, 501, 0, _T("Not Implemented"), hr);
    }
    else if (!CProtocolBridge::SendIisnodeError(pHttpContext, hr))
    {
        CProtocolBridge::SendEmptyResponse( pHttpContext, 
                                            500, 
                                            CNodeConstants::IISNODE_ERROR_ON_EXECUTE_REQ_HANDLER, 
                                            _T("Internal Server Error"), 
                                            hr );
    }

    return RQ_NOTIFICATION_FINISH_REQUEST;
}
Exemple #3
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;
}