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

📄 evtsrc.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
//+---------------------------------------------------------------------------
//
//  Microsoft Windows
//
//  File:       E V T S R C . C P P
//
//  Contents:
//
//  Notes:
//
//  Author:     danielwe   8 Oct 1999
//
//----------------------------------------------------------------------------

#include <ssdppch.h>
#pragma hdrstop
#include <ssdpnetwork.h>
#include <safeint.hxx>

extern LONG cInitialized;

LIST_ENTRY          g_listEventSource;
CRITICAL_SECTION    g_csListEventSource;
static HANDLE       g_hThrdEventSource;
static DWORD        g_fShutdownEventThread;
HANDLE              g_hEvtEventSource;
static long         g_lOutstandingEvents;

DWORD SendEventMessage(EventData* pEvent)
{
    assert(pEvent);

    InterlockedIncrement(&g_lOutstandingEvents);
    
    HRESULT hr = HrSubmitEventToSubscriber(0, pEvent->dwTimeout, pEvent->strSid, pEvent->iSeq, pEvent->pszBody, pEvent->strUrl);
    
    //
    // Find the subscriber by Sid and update its state
    //    
    EnterCriticalSection(&g_csListEventSource);
    
    UPNP_EVENT_SOURCE   *pes;
    UPNP_SUBSCRIBER     *pSub;
    PLIST_ENTRY         p, p2;
    PLIST_ENTRY         pListHead = &g_listEventSource;
    
    for (p = pListHead->Flink; p != pListHead; p = p->Flink)
    {
        pes = CONTAINING_RECORD (p, UPNP_EVENT_SOURCE, linkage);
        
        for (p2 = pes->listSubs.Flink; p2 != &pes->listSubs; p2 = p2->Flink)
        {
            pSub = CONTAINING_RECORD(p2, UPNP_SUBSCRIBER, linkage);
            
            if(pEvent->strSid == pSub->szSid)
            {
                // Clear the F_UPNPSUB_SENDING_EVENT flag
                pSub->flags &= ~F_UPNPSUB_SENDING_EVENT;
                
                // increment the subscriber's sequence number - handle overflow
                if(++pSub->iSeq == 0)
                    pSub->iSeq = 1;
                
                // If the event message has timed out mark the subscriber as non-responsive and decrease the timeout
                if(hr == HRESULT_FROM_WIN32(ERROR_INTERNET_TIMEOUT))
                {
                    pSub->flags |= F_UPNPSUB_NOTRESPONDING;
                    
                    // cut the time by half but don't go below MINIMAL_EVENT_TIMEOUT
                    if(pSub->dwEventTimeout >= 2 * MINIMAL_EVENT_TIMEOUT)
                        pSub->dwEventTimeout /= 2;
                        
                    TraceTag(ttidEvents, "Subscriber %s is not responding. Event timeout set to %d.", pSub->szSid, pSub->dwEventTimeout);
                }
                else
                {
                    // Clear the F_UPNPSUB_NOTRESPONDING flag
                    pSub->flags &= ~F_UPNPSUB_NOTRESPONDING;
                    
                    // restore DEFAULT_EVENT_TIMEOUT
                    pSub->dwEventTimeout = DEFAULT_EVENT_TIMEOUT;
                }
                
                goto Cleanup;
            }
        }
    }
    
Cleanup:
    LeaveCriticalSection(&g_csListEventSource);

    SetEvent(pEvent->hEventSent);
    delete pEvent;
    InterlockedDecrement(&g_lOutstandingEvents);

    return 0;
}


//
// Worker thread responsible for sending events to all subscribers
//
DWORD
WINAPI
EventSourceWorkerThread(PVOID )
{
    ce::auto_handle hEventSent(CreateEvent(NULL, FALSE, FALSE, NULL));
    
    PLIST_ENTRY p, p2;
    PLIST_ENTRY pListHead = &g_listEventSource;
    
    while (!g_fShutdownEventThread)
    {
        UPNP_EVENT_SOURCE *pes;
        UPNP_SUBSCRIBER *pSub;
        bool bPendingEvents = false;
        
        EnterCriticalSection(&g_csListEventSource);
        //
        // Walk the list of event sources searching for the first source with pending events
        // If we find one, move it to the end of the list
        // (For this to work consistently, new event sources must be added to the head of the list)
        for (p = pListHead->Flink; p != pListHead; p = p->Flink)
        {
            pes = CONTAINING_RECORD (p, UPNP_EVENT_SOURCE, linkage);
            
            // Check if there events pending for any subscribers;
            // Flag all subscribers with event pending
            // If a new subscriber is added to this event source while we are sending an event
            // it will not have the flag set, which is correct.
            for (p2 = pes->listSubs.Flink; p2 != &pes->listSubs; p2 = p2->Flink)
            {
                pSub = CONTAINING_RECORD(p2, UPNP_SUBSCRIBER, linkage);
                
                if(pSub->iSeq == 0)
                {
                    TraceTag(ttidEvents, "EventSourceWorkerThread: Skipping subscriber with iSeq == 0");
                    continue;
                }
                
                if(pSub->flags & F_UPNPSUB_SENDING_EVENT)
                {
                    TraceTag(ttidEvents, "EventSourceWorkerThread: Skipping subscriber with unsent message");
                    continue;
                }
                
                for(unsigned i = 0; i < pSub->cProps; ++i)
                    if(pSub->rgesModified[i])
                    {
                        pSub->flags |= F_UPNPSUB_PENDINGEVENT;
                        bPendingEvents = true;
                        break;
                    }
            }
                            
            if(bPendingEvents)
            {
                // round robin scheduling of event source: put this event source at the end of the list
                // This also makes it possible to locate the event source in the next while loop
                RemoveEntryList(p);
                InsertTailList(pListHead, p);
                break;
            }
        }

        if (bPendingEvents)
        {
            TraceTag(ttidEvents, "Processing Event for %s:\n-------------------", pes->szRequestUri);
            // we have an event to send to one or more subscribers
            // We give up the critical section while iterating through the subscriber list so
            // make sure the event source at the tail of the list is the same one we are
            // processing. If it's not then the event source must have been deleted!
            while (!IsListEmpty(pListHead) 
                  && CONTAINING_RECORD(pListHead->Blink, UPNP_EVENT_SOURCE, linkage) == pes)
            {
                // go through each subscriber, and pick out the first one with PENDINGEVENT
                // flag set. 
                for (p2 = pes->listSubs.Flink; p2 != &pes->listSubs; p2 = p2->Flink)
                {
                     pSub = CONTAINING_RECORD(p2, UPNP_SUBSCRIBER, linkage);
                     if (pSub->flags & F_UPNPSUB_PENDINGEVENT)
                     {
                         break;
                     }
                }

                if (p2 != &pes->listSubs)
                {
                    // we broke out of the above for loop => we found a subscriber to send to
                    // clear the PENDINGEVENT flag, so we skip past this subscriber next time.
                    pSub->flags &= ~F_UPNPSUB_PENDINGEVENT;

                    if(EventData* pEvent = new EventData)
                    {
                        assert(pSub->dwEventTimeout == DEFAULT_EVENT_TIMEOUT || (pSub->flags & F_UPNPSUB_NOTRESPONDING));
                        
                        // 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 = hEventSent;
                        
                        // create event body
                        if(SUCCEEDED(HrComposeXmlBodyFromEventSource(pes, pSub, false, &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;
                            
                            ResetEvent(hEventSent);
                            
                            // SendEventMessage is reponsible for deleting pEvent
                            if(g_pThreadPool->StartTimer((LPTHREAD_START_ROUTINE)SendEventMessage, pEvent, 0))
                            {
                                // now leave the critical section. 
                                // All event source and subscriber pointers are off limits after this.
                                //
                                LeaveCriticalSection(&g_csListEventSource);
                                
                                TraceTag(ttidEvents, "EventSourceWorkerThread: --- There is %d outstanding event messages ---", g_lOutstandingEvents);
                                
                                // Wait a bit so that all the event messeges don't go out at the same time 
                                WaitForSingleObject(hEventSent, 10 * g_lOutstandingEvents);
                                
                                EnterCriticalSection(&g_csListEventSource);
                            }
                            else
                            {
                                // Since we couldn't schedule the SendEventMessage we must delete pEvent ...
                                delete pEvent;
                                
                                // ... and clear the F_UPNPSUB_SENDING_EVENT flag
                                pSub->flags &= ~F_UPNPSUB_SENDING_EVENT;
                            }
                        }
                        else
                            delete pEvent;
                    }
                }
                else
                {
                    // there are no more subscribers to send this event
                    break;
                }
            }
            
            TraceTag(ttidEvents, "EventSourceWorkerThread: ---Done sending event ----");
        }
        
        LeaveCriticalSection(&g_csListEventSource);
        
        if (!bPendingEvents)
        {
            // no more events to be sent to anyone. Go to sleep ....
            TraceTag(ttidEvents, "EventSourceWorkerThread: Sleeping...");
            WaitForSingleObject(g_hEvtEventSource,INFINITE);
        }
    }

    return 0;
}

//+---------------------------------------------------------------------------
//
//  Function:   InitializeListEventSource
//
//  Purpose:    Initializes the event source list structures
//
//  Arguments:
//      (none)
//
//  Returns:    Nothing
//
//  Author:     danielwe   13 Oct 1999
//
//  Notes:
//
BOOL InitializeListEventSource()
{
    DWORD dwThreadId;
    InitializeCriticalSection(&g_csListEventSource);
    EnterCriticalSection(&g_csListEventSource);
    InitializeListHead(&g_listEventSource);
    g_fShutdownEventThread = FALSE;
    g_hEvtEventSource = CreateEvent(NULL,FALSE, FALSE, NULL);
    if (g_hEvtEventSource)
        g_hThrdEventSource = CreateThread(NULL, 0, EventSourceWorkerThread, NULL, 0, &dwThreadId);
    LeaveCriticalSection(&g_csListEventSource);
    return g_hEvtEventSource && g_hThrdEventSource;
}

//+---------------------------------------------------------------------------
//
//  Function:   RegisterUpnpEventSource
//
//  Purpose:    Public API to register a URI as a UPnP event source
//
//  Arguments:
//      szRequestUri [in]   URI to register as an event source
//      cProps       [in]   Number of properties this event source supplies
//      rgProps      [in]   List of properties
//
//  Returns:    TRUE if successful, FALSE if not. GetLastError() contains the
//              error code.
//
//  Author:     danielwe   13 Oct 1999
//
//  Notes:
//
BOOL WINAPI RegisterUpnpEventSource(
    /* [string][in] */ LPCSTR szRequestUri,
    /* [in] */ DWORD cProps,
    /* [in] */ UPNP_PROPERTY __RPC_FAR *rgProps)
{
    UPNP_EVENT_SOURCE *     pes = NULL;
    DWORD                   iProp;
    DWORD                   dwError = NOERROR;

    if (InterlockedExchange(&cInitialized, cInitialized) == 0)
    {
        dwError = ERROR_NOT_READY;
    }
    // Validate params
    //
    else if (!szRequestUri )
    {
        TraceTag(ttidError, "_RegisterUpnpEventSourceRpc: error %ld.",
                   HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
        dwError = ERROR_INVALID_PARAMETER;
    }

    // Validate property info
    //
    else for (iProp = 0; iProp < cProps; iProp++)
    {
        if (!FValidateUpnpProperty(&rgProps[iProp]))
        {
            TraceTag(ttidError, "_RegisterUpnpEventSourceRpc: error %ld.",
                       HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
            dwError = ERROR_INVALID_PARAMETER;
            break;
        }
    }
    if (dwError)
    {
        SetLastError(dwError);
        return FALSE;
    }

    EnterCriticalSection(&g_csListEventSource);

    // Look to see if they've already registered this event source
    //
    if (PesFindEventSource(szRequestUri))
    {
        TraceTag(ttidError, "_RegisterUpnpEventSourceRpc: error %ld.",
                   HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS));
        dwError = ERROR_ALREADY_EXISTS;
    }
    else if (!(pes = (UPNP_EVENT_SOURCE *) malloc(sizeof(UPNP_EVENT_SOURCE))))
    {
        TraceTag(ttidError, "_RegisterUpnpEventSourceRpc: error %ld.",
                   HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY));
        dwError = ERROR_OUTOFMEMORY;
    }
    else 
    {
        pes->cProps = 0;
        pes->rgesProps = NULL;
        pes->fCleanup = FALSE;
        pes->szRequestUri = _strdup(szRequestUri);
        if (cProps && cProps < ULONG_MAX / sizeof(UPNP_PROPERTY)) // protect against integer overflow
        {
            if(pes->rgesProps = (UPNP_PROPERTY*) malloc(sizeof(UPNP_PROPERTY) * cProps))
            {
                // Copy in property information
                //
                for (iProp = 0; iProp < cProps; iProp++)
                {
                    if(CopyUpnpProperty(&pes->rgesProps[pes->cProps], &rgProps[iProp]))
                        pes->cProps++;
                }
            }
        }
        //InitializeCriticalSection(&(pes->cs));
        InitializeListHead(&(pes->listSubs));

        // read the LIST_ENTRY
        InsertHeadList(&g_listEventSource, &(pes->linkage));

        PrintListEventSource(&g_listEventSource);
    }
    LeaveCriticalSection(&g_csListEventSource);

    TraceError("_RegisterUpnpEventSourceRpc", HRESULT_FROM_WIN32(dwError));
    if (dwError)
    {
        SetLastError(dwError);
        return FALSE;
    }
    return TRUE;
        
}

//+---------------------------------------------------------------------------
//
//  Function:   DeregisterUpnpEventSource
//
//  Purpose:    Public API to remove an event source
//
//  Arguments:
//      szRequestUri [in]   URI to identify event source to remove
//
//  Returns:    TRUE if successful, FALSE if not. GetLastError() contains the
//              error code.
//
//  Author:     danielwe   13 Oct 1999
//
//  Notes:
//
BOOL WINAPI DeregisterUpnpEventSource(
    /* [string][in] */ LPCSTR szRequestUri)
{
    DWORD               dwError = NOERROR;
    UPNP_EVENT_SOURCE * pes;

    if (InterlockedExchange(&cInitialized, cInitialized) == 0)
    {
        SetLastError(ERROR_NOT_READY);
        return FALSE;
    }
    EnterCriticalSection(&g_csListEventSource);

    pes = PesFindEventSource(szRequestUri);
    if (pes)
    {
        TraceTag(ttidEvents, "DeregisterUpnpEventSource: removing event "
                 "source %s.", szRequestUri);
        CleanupEventSourceEntry(pes);
        FreeEventSource(pes);
    }
    else
    {
        TraceTag(ttidError, "DeregisterUpnpEventSource: unknown URI %s.",
                 szRequestUri);
        dwError = ERROR_INTERNET_ITEM_NOT_FOUND;
    }

    LeaveCriticalSection(&g_csListEventSource);

    TraceError("_RegisterUpnpEventSourceRpc", HRESULT_FROM_WIN32(dwError));
    if (dwError)
    {
        SetLastError(dwError);
        return FALSE;
    }
    return TRUE;
}

⌨️ 快捷键说明

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