⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 subs.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//  Returns:    TRUE if successful, FALSE if not. GetLastError() contains the
//              error code.
//
//  Author:     danielwe   12 Oct 1999
//
//  Notes:
//
BOOL FAddSubscriberFromRequest(SSDP_REQUEST * pRequest, PSTR *ppResp, DWORD dwIndex)
{
    BOOL                fResult = FALSE;
    UPNP_EVENT_SOURCE * pes;
    UPNP_SUBSCRIBER *   pSub = NULL;

    AssertSz(pRequest->Method == GENA_SUBSCRIBE, "I thought you told me "
             "this was a subscription request!");

    // First, do some checking on the message headers to see if this is a
    // valid subscription request
    //

    if (!pRequest->Headers[GENA_CALLBACK])
    {
        pRequest->status = HTTP_STATUS_BAD_REQUEST;
        TraceTag(ttidEvents, "Didn't get a Callback header!");
        SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND);
        return FALSE;
    }

    if (!pRequest->RequestUri || !(*pRequest->RequestUri))
    {
        TraceTag(ttidEvents, "Didn't get a Reqeust-Uri!");
        pRequest->status = HTTP_STATUS_BAD_REQUEST;
        SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND);
        return FALSE;
    }

    EnterCriticalSection(&g_csListEventSource);
    pes = PesFindEventSource(pRequest->RequestUri);
    if (!pes)
    {
        pRequest->status =HTTP_STATUS_SERVER_ERROR;
        TraceTag(ttidEvents, "Subscription sent to unknown Request URI: %s ",
                 pRequest->RequestUri);

        // No event source registered matches this Request URI. We'll
        // retrun 404 Not Found.
        //
        SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND);
        goto cleanupL;
    }

    // Found the event source this SUBSCRIBE was sent to
    //
    pSub = (UPNP_SUBSCRIBER *) malloc(sizeof(UPNP_SUBSCRIBER));
    if (!pSub)
    {
        SetLastError(ERROR_OUTOFMEMORY);
        goto cleanupL;
    }

    memset(pSub,0,sizeof(UPNP_SUBSCRIBER));
    // Validate the Callback header and look for at least one URL that
    // starts with "http://"
    //
    if (!FParseCallbackUrl(pRequest->Headers[GENA_CALLBACK], &pSub->szDestUrl))
    {
        TraceTag(ttidEvents, "Callback header '%s' was invalid!",
                 pRequest->Headers[GENA_CALLBACK]);
        pRequest->status = HTTP_STATUS_PRECOND_FAILED;
        SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND);
        goto cleanupL;
    }

    DWORD dw;
    
    if(!FixURLAddressScopeId(pSub->szDestUrl, dwIndex, NULL, &(dw = 0)) && dw != 0)
        if(char* szDestUrl = (char*)malloc(dw))
            if(FixURLAddressScopeId(pSub->szDestUrl, dwIndex, szDestUrl, &dw))
            {            
                free(pSub->szDestUrl);
                pSub->szDestUrl = szDestUrl;
            }
            else
                free(szDestUrl);

    if(!g_pURL_Verifier->is_url_ok(pSub->szDestUrl))
    {
        TraceTag(ttidEvents, "Callback url '%s' is invalid.", pSub->szDestUrl);
        pRequest->status = HTTP_STATUS_PRECOND_FAILED;
        SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND);
        goto cleanupL;
    }
    
    pSub->hEventCleanup = CreateEvent(NULL, TRUE, FALSE, NULL);

    // Fill in some of the other members of the subscription struct
    //
    pSub->dwEventTimeout = DEFAULT_EVENT_TIMEOUT;
    pSub->flags = 0;
    pSub->pes = pes;
    pSub->iSeq = 0;
    pSub->szSid = SzGetNewSid();
    if (!pSub->szSid)
    {
        SetLastError(ERROR_OUTOFMEMORY);
        goto cleanupL;
    }
    
    if(pes->cProps)
    {
        pSub->rgesModified = (bool*)malloc(sizeof(bool) * pes->cProps);
        
        if (!pSub->rgesModified)
        {
            SetLastError(ERROR_OUTOFMEMORY);
            goto cleanupL;
        }
        
        pSub->cProps = pes->cProps;
    }

    pSub->dwTimerCookie = 0;
    pSub->fInTimer = FALSE;

    // Ok, now we have a valid subscription, so we need to send a response
    // to the subscriber

    SetSubscriptionTimeout(pSub, pRequest->Headers[GENA_TIMEOUT]);
    if (*ppResp = ComposeSubscribeResponse(pSub))
    {
        LPSTR      szSid;
        DWORD      iSeq;

        // Must hold the event source lock across adding the subscriber and
        // sending the notify message
        //EnterCriticalSection(&pes->cs);

        szSid = _strdup(pSub->szSid);
        iSeq = pSub->iSeq;

        // Ok we've added the subscription and notified so it's ok to allow
        // pre-empting now
#if DBG
        PrintSubscription(pSub);
#endif
        //PersistSubscriberList();

        AddToListSubscriber(pes, pSub);

        StartResubscribeTimer(pSub);

        //LeaveCriticalSection(&pes->cs);
        LeaveCriticalSection(&g_csListEventSource);

        // hack to make the SID available to the caller
        // so that an initial event notification can be sent
        pRequest->Headers[GENA_SID] = szSid;

        // tell UPNP device about this subscription
        // this callback also gives the device a chance to update the evented variables
        if (pfSubscribeCallback)
            if (!pfSubscribeCallback(TRUE, pRequest->RequestUri))
            {
                // subscription was vetoed
                pRequest->Method = GENA_UNSUBSCRIBE;
                FRemoveSubscriberFromRequest(pRequest, NULL);
                pRequest->Method = GENA_SUBSCRIBE;
                pRequest->status = HTTP_STATUS_SERVICE_UNAVAIL;
                return FALSE;
            }

        fResult = TRUE;
    }
    else
        goto cleanupL;

    TraceResult("FAddSubscriberFromRequest", fResult);
    return fResult;

cleanupL:
    FreeUpnpSubscriber(pSub);

    LeaveCriticalSection(&g_csListEventSource);

    return FALSE;
}
//+---------------------------------------------------------------------------
//
//  Function:   SendInitialEventNotification
//
//  Purpose:    Send the initial event notification to a subscriber
//              
//
DWORD SendInitialEventNotification(PSSDP_REQUEST pRequest)
{
    LPSTR       szBody = NULL;

    AssertSz(pRequest->Method == GENA_SUBSCRIBE, "I thought you told me "
             "this was a subscribe request!");
    AssertSz(pRequest->Headers[GENA_SID], "Why don't I have a SID header??!?!");

    if (!pRequest->RequestUri || !(*pRequest->RequestUri))
    {
        TraceTag(ttidEvents, "Didn't get a Reqeust-Uri!");
        FreeSsdpRequest(pRequest);
        delete pRequest;
        return 0;
    }

    EnterCriticalSection(&g_csListEventSource);

    // Find the event source based on the URI
    //
    if(UPNP_EVENT_SOURCE *pes = PesFindEventSource(pRequest->RequestUri))
    {
        //EnterCriticalSection(&pes->cs);
        PLIST_ENTRY     pListHead = &pes->listSubs;
        UPNP_SUBSCRIBER *pSub = NULL;

        // Found the event source this SUBSCRIBE was sent to. Now find the
        // subscriber.
        for (PLIST_ENTRY p = pListHead->Flink; p != pListHead; p = p->Flink)
        {
            pSub = CONTAINING_RECORD (p, UPNP_SUBSCRIBER, linkage);

            if (!_stricmp(pSub->szSid, pRequest->Headers[GENA_SID]))
            {
                // Found the subscriber they were looking for!
                break;
            }
        }

        if (p != pListHead)
        {
            Assert(pSub);
            AssertSz(pSub->iSeq == 0, "Can't send initial notify if sequence number is not 0!");

            if(EventData* pEvent = new EventData)
            {
                // make a copy of the destination URL and SID since we can't touch the subscriber
                // fields after leaving the Critical Section.
                pEvent->strUrl = pSub->szDestUrl;
                pEvent->strSid = pSub->szSid;
                pEvent->iSeq = pSub->iSeq;
                pEvent->dwTimeout = pSub->dwEventTimeout;
                pEvent->hEventSent = NULL;
                
                // create event body
                if(SUCCEEDED(HrComposeXmlBodyFromEventSource(pes, pSub, pSub->iSeq == 0, &pEvent->pszBody)))
                {
                    // mark that we are in process of sending event to the subscriber
                    assert(!(pSub->flags & F_UPNPSUB_SENDING_EVENT));
                    pSub->flags |= F_UPNPSUB_SENDING_EVENT;
                    
                    LeaveCriticalSection(&g_csListEventSource);
                    
                    SendEventMessage(pEvent);
                    
                    EnterCriticalSection(&g_csListEventSource);
                }
                else
                    delete pEvent;
            }
        }
        //LeaveCriticalSection(&pes->cs);
    }

    LeaveCriticalSection(&g_csListEventSource);

    if (szBody)
        free(szBody);
        
    FreeSsdpRequest(pRequest);
    delete pRequest;
    
    return 0;
}

//+---------------------------------------------------------------------------
//
//  Function:   FRemoveSubscriberFromRequest
//
//  Purpose:    Given an UNSUBSCRIBE request, removes the subscription from
//              the list within the event source.
//
//  Arguments:
//      
//      pRequest [in]   Request to be processed
//      ppResp   [out]  Response
//
//  Returns:    TRUE if successful, FALSE if not. GetLastError() contains the
//              error code.
//
//  Author:     danielwe   13 Oct 1999
//
//  Notes:
//
BOOL FRemoveSubscriberFromRequest(SSDP_REQUEST * pRequest, PSTR *)
{
    BOOL                fResult = FALSE;
    UPNP_EVENT_SOURCE * pes;
    PLIST_ENTRY         pListHead;
    PLIST_ENTRY         p;

    AssertSz(pRequest->Method == GENA_UNSUBSCRIBE, "I thought you told me "
             "this was an unsubscribe request!");

    // First, do some checking on the message headers to see if this is a
    // valid unsubscribe request
    //

    if (!pRequest->Headers[GENA_SID] || !(*(pRequest->Headers[GENA_SID])))
    {
        TraceTag(ttidEvents, "Didn't get a valid SID header!");
        pRequest->status = HTTP_STATUS_BAD_REQUEST;
        SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND);
        goto cleanup;
    }

    if (!pRequest->RequestUri || !(*pRequest->RequestUri))
    {
        TraceTag(ttidEvents, "Didn't get a Reqeust-Uri!");
        pRequest->status = HTTP_STATUS_BAD_REQUEST;
        SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND);
        goto cleanup;
    }

    EnterCriticalSection(&g_csListEventSource);

    // Find the event source based on the URI
    //
    pes = PesFindEventSource(pRequest->RequestUri);
    if (!pes)
    {
        TraceTag(ttidEvents, "Unsubscrbe sent to unknown Request URI: %s ",
                 pRequest->RequestUri);

        // No event source registered matches this Request URI. We'll
        // retrun 404 Not Found.
        //
        pRequest->status = HTTP_STATUS_SERVER_ERROR;
        SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND);
        goto cleanupL;
    }

    // Found the event source this SUBSCRIBE was sent to. Now find the
    // subscriber.
    //
    //EnterCriticalSection(&pes->cs);
    pListHead = &pes->listSubs;

    for (p = pListHead->Flink; p != pListHead; p = p->Flink)
    {
        UPNP_SUBSCRIBER * pSub;

        pSub = CONTAINING_RECORD (p, UPNP_SUBSCRIBER, linkage);
        if (!_stricmp(pSub->szSid, pRequest->Headers[GENA_SID]))
        {
            TraceTag(ttidEvents, "Unsubscribing SID: %s ",
                     pRequest->Headers[GENA_SID]);

            // Found the subscriber they were looking for!
            //
            CleanupSubscriberEntry(pSub);
            //pRequest->status = HTTP_STATUS_OK;
            fResult = TRUE;
            break;
        }
    }

    //LeaveCriticalSection(&pes->cs);

    if (p == pListHead)
    {
        TraceTag(ttidEvents, "Unsubscribe sent to unknown SID: %s ",
                 pRequest->Headers[GENA_SID]);

        // Didn't find the subscriber. We should return 404 Not Found.
        pRequest->status = HTTP_STATUS_SERVER_ERROR;
        SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND);
        fResult = FALSE;
    }

cleanupL:
    LeaveCriticalSection(&g_csListEventSource);
    // signal the unsubscribe to the upper layers
    if (fResult && pfSubscribeCallback)
        pfSubscribeCallback(FALSE,pRequest->RequestUri);
cleanup:
    TraceResult("FRemoveSubscriberFromRequest", fResult);
    return fResult;
}

//+---------------------------------------------------------------------------
//
//  Function:   ResubscribeTimerProc
//
//  Purpose:    Callback that is called when the re-subscription timer has
//              run out.
//
//  Arguments:
//      pvContext   [in]  Context variable. This is the pSub pointer.
//
//  Returns:    Nothing
//
//  Author:     danielwe   13 Oct 1999
//

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -