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

📄 searchc.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// 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.
//
#include <ssdppch.h>
#pragma hdrstop
#include <iphlpapi.h>

#include "ssdpfuncc.h"
#include "ssdpparser.h"
#include "ipsupport.h"
#include "upnp_config.h"

static CRITICAL_SECTION CSListSearch;

static CHAR *SearchHeader = "\"ssdp:discover\"";
static CHAR *MulticastUri = "*";
static CHAR *MX = "3";

#define MX_VALUE 3000
#define SELECT_TIMEOUT 60

DWORD WINAPI DoSsdpSearch(PSSDP_SEARCH_REQUEST SearchRequest);
DWORD WINAPI DoSsdpSearchThread(LPVOID lpvThreadParam);
//BOOL GetCacheResult(PSSDP_SEARCH_REQUEST SearchRequest);
VOID FreeSearchRequest(PSSDP_SEARCH_REQUEST SearchRequest);
VOID DoCancelCallback(PSSDP_SEARCH_REQUEST SearchRequest);
DWORD WINAPI SearchRequestTimerProc (VOID *Arg);
VOID StopSearchRequestTimer(PSSDP_SEARCH_REQUEST SearchRequest);
VOID WakeupSelect(PSSDP_SEARCH_REQUEST SearchRequest);

extern SOCKADDR_IN  MulticastAddressIPv4;
extern SOCKADDR_IN6 MulticastLinkScopeAddressIPv6;
extern SOCKADDR_IN6 MulticastSiteScopeAddressIPv6;

PSSDP_SEARCH_REQUEST CreateSearchRequest(const char *szType)
{
    PSSDP_SEARCH_REQUEST SearchRequest = NULL;
    INT Size = sizeof(SSDP_SEARCH_REQUEST);

    SearchRequest = new SSDP_SEARCH_REQUEST;

    if (SearchRequest == NULL)
    {
        TraceTag(ttidError, "Couldn't allocate  memory SearchRequest "
                 "for %s", szType);
        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
        return NULL;
    }

    SearchRequest->Type = SSDP_CLIENT_SEARCH_SIGNATURE;
    SearchRequest->Size = Size;
    SearchRequest->state = SEARCH_START;
    SearchRequest->szType = NULL;
    SearchRequest->szSearch = NULL;
    SearchRequest->Callback = NULL;
    SearchRequest->Context = NULL;
    SearchRequest->NumOfRetry = 2;
    SearchRequest->fExit = 0;
    SearchRequest->hThread = NULL;
    SearchRequest->CurrentResponse = NULL;
    SearchRequest->dwTimerCookie = 0;
    SearchRequest->DoneEvent = NULL;
    SearchRequest->HitWire = FALSE;
    SearchRequest->bCallbackInProgress = FALSE;
    SearchRequest->nRefCount = 1;
    SearchRequest->dwNumberOfResponses = 0;

    InitializeCriticalSection(&SearchRequest->cs);
    InitializeListHead(&SearchRequest->ListResponses);
    SearchRequest->CurrentResponse = SearchRequest->ListResponses.Flink;

    SearchRequest->szType = (CHAR *) malloc(strlen(szType)+1);
    if (SearchRequest->szType == NULL)
    {
        TraceTag(ttidError, "Couldn't allocate  memory for szType for %s", szType);
        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
        FreeSearchRequest(SearchRequest);
        return NULL;
    }
    strcpy(SearchRequest->szType, szType);

    SearchRequest->DoneEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (SearchRequest->DoneEvent == NULL)
    {
        FreeSearchRequest(SearchRequest);
        return NULL;
    }

    return SearchRequest;
}


// AddNetwork
void AddNetwork(ce::vector<SSDP_SEARCH_NETWORK>& Networks, PSOCKADDR_STORAGE pSockaddr, int iSockaddrLength, DWORD dwAdapterIndex)
{
    PSOCKADDR   pMulticastAddr = NULL;
    DWORD       dwScopeId = 0, dwScope = 0;

    // select proper multicast address
    if(pSockaddr->ss_family == AF_INET)
    {
        pMulticastAddr = (PSOCKADDR)&MulticastAddressIPv4;
    }
    else if(pSockaddr->ss_family == AF_INET6)
    {
        if(IN6_IS_ADDR_LINKLOCAL(&((PSOCKADDR_IN6)pSockaddr)->sin6_addr))
        {
            // scope and scope id for the link
            dwScopeId = dwAdapterIndex;
            dwScope = 1;
                
            pMulticastAddr = (PSOCKADDR)&MulticastLinkScopeAddressIPv6;
        }
        else if(IN6_IS_ADDR_SITELOCAL(&((PSOCKADDR_IN6)pSockaddr)->sin6_addr))
        {
            // check if site scope should be supported
            if(upnp_config::site_scope() < 3)
                return;
            
            // scope and scope id for the site
            dwScopeId = ((PSOCKADDR_IN6)pSockaddr)->sin6_scope_id;
            dwScope = 2;
        
            pMulticastAddr = (PSOCKADDR)&MulticastSiteScopeAddressIPv6;
        }
        else
            // scope not supported by UPnP
            return;
            
        Assert(dwScope != 0);
        Assert(dwScopeId != 0);
        
        // check if we already have address with the same scope and scope id
        for(ce::vector<SSDP_SEARCH_NETWORK>::iterator it = Networks.begin(), itEnd = Networks.end(); it != itEnd; ++it)
            if(it->dwScopeId == dwScopeId && it->dwScope == dwScope)
                return;
    }
    else
        return; // unknown address family

    SSDP_SEARCH_NETWORK network;
    
    if(SocketOpen(&network.socket, (PSOCKADDR)pSockaddr, dwAdapterIndex, NULL))
    {
        WCHAR lpwszAddress[MAX_ADDRESS_SIZE];
        DWORD dwSize;
        
        network.dwIndex = dwAdapterIndex;
        network.dwScopeId = dwScopeId;
        network.dwScope = dwScope;
        network.pMulticastAddr = pMulticastAddr;
        
        // store multicast address in string form
        WSAAddressToString((LPSOCKADDR)pMulticastAddr, sizeof(SOCKADDR_STORAGE), NULL, lpwszAddress, &(dwSize = sizeof(lpwszAddress)));
        ce::WideCharToMultiByte(CP_ACP, lpwszAddress, -1, &network.strMulticastAddr);
        
        Networks.push_back(network);
    }
}


// OpenSearchSockets
VOID OpenSearchSockets(PSSDP_SEARCH_REQUEST pSearchRequest)
{
    PIP_ADAPTER_ADDRESSES   pAdapterAddresses = NULL;  // buffer used by GetAdaptersAddresses()
    ULONG                   ulBufSize = 0;    // size of buffer returned by GetAdaptersAddresses()
    DWORD                   dwRes  = 0;   // result codes from iphelper apis
    
    // Find out size of returned buffer
    dwRes = GetAdaptersAddresses(
                upnp_config::family(),
                GAA_FLAG_SKIP_ANYCAST |GAA_FLAG_SKIP_DNS_SERVER,
                NULL,
                pAdapterAddresses,
                &ulBufSize
                );
    
    if(ulBufSize)
    {
        // Allocate sufficient Space
        pAdapterAddresses = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(malloc(ulBufSize));
        if (pAdapterAddresses !=NULL)
        {
            // Get Adapter List
            dwRes = GetAdaptersAddresses(
                    upnp_config::family(), 
                    GAA_FLAG_SKIP_ANYCAST|GAA_FLAG_SKIP_DNS_SERVER,
                    NULL,
                    pAdapterAddresses,
                    &ulBufSize
                    );
            
            if (dwRes == ERROR_SUCCESS)
            {
                // Loop through all the adapters (interfaces) returned
                for(PIP_ADAPTER_ADDRESSES pAdapterIter = pAdapterAddresses; pAdapterIter != NULL; pAdapterIter = pAdapterIter->Next)
                {
                    // don't use tunneling adapters
                    if(pAdapterIter->IfType == IF_TYPE_TUNNEL)
                        continue;
                    
                    if(!upnp_config::is_adapter_enabled(pAdapterIter->AdapterName))
                        continue;
                        
                    // Loop through all the addresses returned
                    for(PIP_ADAPTER_UNICAST_ADDRESS pUnicastAddress = pAdapterIter->FirstUnicastAddress;
                        pUnicastAddress != NULL;
                        pUnicastAddress = pUnicastAddress->Next)
                    {
                        SOCKADDR_STORAGE sockaddr;
                        
                        memcpy(&sockaddr, pUnicastAddress->Address.lpSockaddr, pUnicastAddress->Address.iSockaddrLength);

                        if(sockaddr.ss_family == AF_INET)
                            AddNetwork(pSearchRequest->Networks, &sockaddr, pUnicastAddress->Address.iSockaddrLength, pAdapterIter->IfIndex);
                        else
                            AddNetwork(pSearchRequest->Networks, &sockaddr, pUnicastAddress->Address.iSockaddrLength, pAdapterIter->Ipv6IfIndex);
                    }
                }
            }
            
            // Tidy up
            free (pAdapterAddresses);
        }
    }
}


// CloseSearchSockets
VOID CloseSearchSockets(PSSDP_SEARCH_REQUEST pSearchRequest)
{
    for(ce::vector<SSDP_SEARCH_NETWORK>::iterator it = pSearchRequest->Networks.begin(), itEnd = pSearchRequest->Networks.end(); it != itEnd; ++it)
        SocketClose(it->socket);
}


// SendSearchRequest
VOID SendSearchRequest(PSSDP_SEARCH_REQUEST pSearchRequest)
{
    for(ce::vector<SSDP_SEARCH_NETWORK>::iterator it = pSearchRequest->Networks.begin(), itEnd = pSearchRequest->Networks.end(); it != itEnd; ++it)
    {
        SSDP_REQUEST SsdpRequest;
        SSDP_HEADER SearchHeaders[] = {SSDP_HOST, SSDP_MAN, SSDP_MX, SSDP_ST};

        memset(&SsdpRequest, 0, sizeof(SsdpRequest));
        
        SsdpRequest.Method = SSDP_M_SEARCH;
        SsdpRequest.RequestUri = MulticastUri;

        SsdpRequest.Headers[SSDP_ST] = pSearchRequest->szType;
        SsdpRequest.Headers[SSDP_MAN] = SearchHeader;
        SsdpRequest.Headers[SSDP_MX] = MX;
        SsdpRequest.Headers[SSDP_HOST] = const_cast<LPSTR>(static_cast<LPCSTR>(it->strMulticastAddr));

        Assert(pSearchRequest->szSearch == NULL);

        ComposeSsdpRequest(&SsdpRequest, SearchHeaders, sizeof(SearchHeaders)/sizeof(*SearchHeaders), &pSearchRequest->szSearch);

        SocketSend(pSearchRequest->szSearch, it->socket, it->pMulticastAddr);

        if(pSearchRequest->szSearch)
            free(pSearchRequest->szSearch);

        pSearchRequest->szSearch = NULL;
    }
}


HANDLE WINAPI FindServicesCallback (const char* szType,
                                    VOID * pReserved ,
                                    BOOL fForceSearch,
                                    SERVICE_CALLBACK_FUNC fnCallback,
                                    VOID *Context)
{
    PSSDP_SEARCH_REQUEST SearchRequest = NULL;

    DWORD ThreadId;
    HANDLE hThread;

    if (szType == NULL || fnCallback == NULL || pReserved != NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return INVALID_HANDLE_VALUE;
    }

    SearchRequest = CreateSearchRequest(szType);

    if (SearchRequest == NULL)
    {
        TraceTag(ttidError, "Couldn't allocate  memory SearchRequest for %s", szType);
        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
        return INVALID_HANDLE_VALUE;
    }

    SearchRequest->Callback = fnCallback;
    SearchRequest->Context = Context;

    // To-Do: Find master
    SearchRequest->state = SEARCH_DISCOVERING;

    // GetCacheResult(SearchRequest);

    // Check ForceSearch
    if (fForceSearch == TRUE 
        //|| IsInListNotify(SearchRequest->szType) == FALSE
        )
    {
        SOCKADDR_IN sockaddrLocal;

        sockaddrLocal.sin_family = AF_INET;
        sockaddrLocal.sin_addr.s_addr = INADDR_ANY;
        sockaddrLocal.sin_port = 0;

        SearchRequest->HitWire = TRUE;

        SocketOpen(&SearchRequest->WakeupSocket, (PSOCKADDR)&sockaddrLocal, 0, NULL);
        OpenSearchSockets(SearchRequest);

        SendSearchRequest(SearchRequest);

        SearchRequest->dwTimerCookie = SearchRequest->ThreadPool.StartTimer(SearchRequestTimerProc, (VOID *) SearchRequest, MX_VALUE);

        if (SearchRequest->dwTimerCookie == 0)
        {
            TraceTag(ttidError, "Failed to start search request timer.");
            
            SocketClose(SearchRequest->WakeupSocket);
            CloseSearchSockets(SearchRequest);

            FreeSearchRequest(SearchRequest);
            SetLastError(ERROR_TIMER_START_FAILED);
            return INVALID_HANDLE_VALUE;
        }

⌨️ 快捷键说明

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