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

📄 network.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        SocketClose(pSSDPNetwork->socket);

    free(pSSDPNetwork);

    FreeNetworkLock();
}


VOID CleanupListNetwork()
{
    TraceTag(ttidSsdpNetwork, "----- Cleanup SSDP Network List -----");
    StopListenOnAllNetworks();
    DeleteCriticalSection(&CSListNetwork);
}


extern DWORD ProcessReceiveBuffer(VOID* pvContext);

static DWORD WINAPI SSDPReadThread(void*)
{
    int ReturnValue;
    CHAR *pszData;
    SOCKADDR_STORAGE RemoteSocket;
    fd_set recvset;
    UINT i;
    static ssdp_queue queue;

    // thread exits when one of the sockets is closed
    while (1)
    {
        PLIST_ENTRY p;
        PLIST_ENTRY pListHead = &listNetwork;
        
        FD_ZERO(&recvset);
        
        // go through the network list and construct a socket list to recv on
        GetNetworkLock();
        
        for (p = pListHead->Flink, i = 0; p != pListHead; p = p->Flink, ++i)
        {
            SSDPNetwork *pssdpNetwork;

            pssdpNetwork = CONTAINING_RECORD (p, SSDPNetwork, linkage);
            FD_SET(pssdpNetwork->socket, &recvset);
        }
        
        FreeNetworkLock();
        
        if(i)
            TraceTag(ttidSsdpNetwork, "Listening on %d network(s).", i); 
        else
            TraceTag(ttidError, "No networks to listen on!"); 
        
        ReturnValue = select(0, &recvset, NULL, NULL, NULL);
        
        if (!ReturnValue || ReturnValue == SOCKET_ERROR)
        {
            TraceTag(ttidSsdpNetwork, "----- select failed with error code "
                     "%d -----", GetLastError());
            break;
        }
        
        if (InterlockedExchange(&g_bExitSSDPReadThread, g_bExitSSDPReadThread))
            break;
        
        for (i = 0; i < recvset.fd_count; i++)
        {
            if (SocketReceive(recvset.fd_array[i], &pszData, &RemoteSocket) == TRUE)
            {
                if (RECEIVE_DATA* pData = (RECEIVE_DATA *)malloc(sizeof(RECEIVE_DATA)))
                {
                    CopyMemory(&pData->RemoteSocket, &RemoteSocket, sizeof(RemoteSocket));
                    
                    pData->socket = recvset.fd_array[i];
                    pData->szBuffer = pszData;
                    pData->dwIndex = 0;
                    
                    GetNetworkLock();
                    
                    // find index of the interface that received the request
                    for (p = pListHead->Flink; p != pListHead; p = p->Flink)
                    {
                        SSDPNetwork *pssdpNetwork;

                        pssdpNetwork = CONTAINING_RECORD (p, SSDPNetwork, linkage);
                        
                        if(pssdpNetwork->socket == recvset.fd_array[i])
                        {
                            pData->dwIndex = pssdpNetwork->dwIndex;
                            break;
                        }
                    }
                    
                    FreeNetworkLock();
                    
                    // always adds to the queue but if queue was full it will remove old item to make space
                    if(ssdp_queue::was_not_full == queue.push(pData))
                        g_pThreadPool->ScheduleEvent(ProcessReceiveBuffer, &queue);
                }
                else
                {
                    TraceError("Couldn't allocate sufficient memory!", E_OUTOFMEMORY);
                    if(pszData)
                        free(pszData);
                }
            }
        }
    }
    
    return 0;
}

static HANDLE g_hSsdpReadThread;
static HANDLE g_hSsdpNetMonThread;
static HANDLE g_hNetMonShutdownEvent;

INT ListenOnAllNetworks(HWND)
{
    //INT ReturnValue;
    DWORD dwSsdpThreadId;

    TraceTag(ttidSsdpNetwork, "ListenOnAllNetworks ...");
    GetNetworks();
    
    InterlockedExchange(&g_bExitSSDPReadThread, FALSE);
    
    g_hSsdpReadThread = CreateThread(
                    NULL, 
                    0, //cbStack
                    (LPTHREAD_START_ROUTINE)SSDPReadThread,
                    NULL,
                    0,
                    &dwSsdpThreadId);
                    
    if (!g_hSsdpReadThread)
    {
        TraceTag(ttidError, "Failed to create SSDPReadThread.  Error code (%d).", GetLastError());
    }

    return g_hSsdpReadThread != NULL;
}

void StopListenOnAllNetworks()
{
    PLIST_ENTRY p;
    PLIST_ENTRY pListHead = &listNetwork;
    
    TraceTag(ttidSsdpNetwork, "StopListenOnAllNetworks ...");
    
    InterlockedExchange(&g_bExitSSDPReadThread, TRUE);
    
    GetNetworkLock();

    for (p = pListHead->Flink; p && p != pListHead;)
    {
        SSDPNetwork *pssdpNetwork;

        pssdpNetwork = CONTAINING_RECORD (p, SSDPNetwork, linkage);

        p = p->Flink;

        FreeSSDPNetwork(pssdpNetwork);
    }

    FreeNetworkLock();
    
    if (g_hSsdpReadThread != NULL)
    {
        WaitForSingleObject(g_hSsdpReadThread,INFINITE);
        CloseHandle(g_hSsdpReadThread);
        g_hSsdpReadThread = NULL;
    }
}

extern VOID SendAllAnnouncements();

static DWORD WINAPI SSDPNetMonThread(void *pData)
{
    HANDLE          hEvents[3] = {0};
    unsigned        nEvents = 0;
    SOCKET          s[2];
    WSAOVERLAPPED   ov[2] = {0};
    int             af[] = {AF_INET, AF_INET6};
    DWORD           dwTimeout;
    unsigned        i;
    
    // set up notification events for each address family
    for(i = 0; i < sizeof(af)/sizeof(*af); ++i)
    {
        Assert(i < sizeof(s)/sizeof(*s));
        Assert(i < sizeof(ov)/sizeof(*ov));
            
        // create socket for this address family
        s[nEvents] = socket(af[i], SOCK_STREAM, 0);
        
        if(s[nEvents] != INVALID_SOCKET)
        {
            // create event to be used for notifications for this address family
            ov[nEvents].hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
            
            // register notification
            if(ERROR_SUCCESS != WSAIoctl(s[nEvents], SIO_ADDRESS_LIST_CHANGE, NULL, 0, NULL, 0, NULL, &ov[nEvents], NULL) &&
               ERROR_IO_PENDING != GetLastError())
            {
                closesocket(s[nEvents]);
                CloseHandle(ov[nEvents].hEvent);
            }
            else
            {
                hEvents[nEvents] = ov[nEvents].hEvent;
                nEvents++;
            }
        }
    }
    
    // add shutdown event
    hEvents[nEvents++] = reinterpret_cast<HANDLE>(pData);
    
    dwTimeout = INFINITE;
    
    // wait for address change notifications
    while(true)
    {
        DWORD dw = WaitForMultipleObjects(nEvents, hEvents, FALSE, dwTimeout);
        
        if(dw == WAIT_FAILED)
        {
            Assert(false);
            break;
        }
        
        if(dw == WAIT_OBJECT_0 + nEvents - 1)
        {
            // shutdown event signaled
            break;
        }
        
        if(dw != WAIT_TIMEOUT)
        {
            Assert(dw - WAIT_OBJECT_0 < nEvents - 1);
            Assert(dw - WAIT_OBJECT_0 < sizeof(s)/sizeof(*s));
            Assert(dw - WAIT_OBJECT_0 < sizeof(ov)/sizeof(*ov));
            
            // reenable notification
            if(ERROR_SUCCESS != WSAIoctl(s[dw - WAIT_OBJECT_0], SIO_ADDRESS_LIST_CHANGE, NULL, 0, NULL, 0, NULL, &ov[dw - WAIT_OBJECT_0], NULL) &&
               ERROR_IO_PENDING != GetLastError())
            {
                TraceTag(ttidError, "Error 0x%x trying to reenable address change notification", GetLastError());
            }
            
            // give time for the network to settle
            // wait for 7 seconds and see if there is another address change
            dwTimeout = 7000;
            continue;
        }
        
        Assert(dw == WAIT_TIMEOUT);
        
        // no more address change notifications within 7 seconds
        // update UPnP networks

        TraceTag(ttidSsdpNetwork, "Processing address change notifiction");
            
        // Remove all the networks ...
        StopListenOnAllNetworks();
        
        // ... and bringing them up again
        ListenOnAllNetworks(NULL);
        
        SendAllAnnouncements();
        
        dwTimeout = INFINITE;
    }
    
    for(i = 0; i < nEvents - 1; ++i)
    {
        closesocket(s[i]);
        CloseHandle(hEvents[i]);
    }
    
    return 1;
}


INT StartNetworkMonitorThread()
{
    DWORD dwSsdpThreadId;

    Assert(!g_hSsdpNetMonThread);
    Assert(!g_hNetMonShutdownEvent);

    TraceTag(ttidSsdpNetwork, "Starting Network Monitor Thread ...");

    g_hNetMonShutdownEvent = CreateEventW(NULL, FALSE, FALSE, NULL);

    if (!g_hNetMonShutdownEvent)
        return FALSE;
    
    g_hSsdpNetMonThread = CreateThread(
                    NULL, 
                    0, //cbStack
                    (LPTHREAD_START_ROUTINE)SSDPNetMonThread,
                    g_hNetMonShutdownEvent,
                    0,
                    &dwSsdpThreadId);
    
    if (!g_hSsdpNetMonThread)
    {
        TraceTag(ttidError, "Failed to create SSDPNetMonThread.  Error code (%d).", GetLastError());
        CloseHandle(g_hNetMonShutdownEvent);
        g_hNetMonShutdownEvent = NULL;
    }

    return g_hSsdpNetMonThread != NULL;
}


INT StopNetworkMonitorThread()
{
    DWORD dwWait;
    
    if (!g_hSsdpNetMonThread)
        return TRUE;
    
    Assert(g_hNetMonShutdownEvent);
    TraceTag(ttidSsdpNetwork, "Stopping Network Monitor Thread ...");
    
    SetEvent(g_hNetMonShutdownEvent);
    
    dwWait = WaitForSingleObject(g_hSsdpNetMonThread, INFINITE);
    
    CloseHandle(g_hSsdpNetMonThread);
    CloseHandle(g_hNetMonShutdownEvent);
    
    g_hNetMonShutdownEvent = NULL;
    g_hSsdpNetMonThread = NULL;
    
    return dwWait == WAIT_OBJECT_0;
}

⌨️ 快捷键说明

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