📄 searchc.cpp
字号:
//
// 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 + -