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