Codice: Seleziona tutto
//o----------------------------------------------------------------------------------
//| Function - DWORD WINAPI WorkerThread (LPVOID ThreadContext)
//| Date -
//| Author - Nuitari
//| Modified -
//o----------------------------------------------------------------------------------
//| Purpose - Thread per i socket connessi
//o----------------------------------------------------------------------------------
DWORD WINAPI cNetwork::WorkerThread (LPVOID ThreadContext)
{
SEH_BEGIN("DWORD WINAPI WorkerThread (LPVOID ThreadContext)")
cNetwork *ContextServer = (cNetwork *)ThreadContext;
BOOL bSuccess;
DWORD dwIoSize = 0, dwRecvNumBytes = 0, dwFlags = 0, dwSendNumBytes = 0;
cSocket *lpSocket = NULL;
LPOVERLAPPED lpOverlapped = NULL;
PIO_CONTEXT lpIoContext = NULL;
INT rc = 0;
BOOL bCtxtSect = FALSE, bOutBuffSect = FALSE, bCrSectClient = FALSE;
__try
{
InterlockedExchangeAdd(&ContextServer->lWorkThreads,1);
while (TRUE)
{
if (bOutBuffSect)
{
LeaveCriticalSection(&lpSocket->CrSect_OutBuffer);
bOutBuffSect = FALSE;
}
if (bCrSectClient)
{
LeaveCriticalSection(&ContextServer->CrSect_Client);
bCrSectClient = FALSE;
}
bSuccess = GetQueuedCompletionStatus(ContextServer->hWorkIOCP, &dwIoSize, (LPDWORD)&lpSocket, &lpOverlapped, INFINITE);
InterlockedExchangeAdd(&ContextServer->lBusyWorkThreads,1);
if (ContextServer->lBusyWorkThreads == ContextServer->lWorkThreads && ContextServer->lWorkThreads < ContextServer->lMaxWorkThreads)
{
//Gui->MessageLog(L"NETWORK: Spawning New Thread");
DebugLog("NETWORK: Spawning New Thread");
HANDLE hThread;
DWORD dwThreadId;
hThread = CreateThread(NULL, 0, WorkerThread, ContextServer, 0, &dwThreadId);
if (hThread == NULL)
{
//Gui->MessageLog(L"NETWORK: ERROR Spawning New Thread");
DebugLog("NETWORK: ERROR Spawning New Thread");
}
}
if (ContextServer->bEndServer)
break;
if (!bSuccess || (bSuccess && (0 == dwIoSize)))
{
__try
{
__try
{
if (lpSocket)
{
rc = GetLastError();
lpSocket->bClose = TRUE;
lpIoContext = CONTAINING_RECORD(lpOverlapped, IO_CONTEXT, Overlapped);
if (lpIoContext)
{
if (lpIoContext->IOOperation == ClientIoWrite)
{
//lpSocket->ClearOut();
lpSocket->isSending = FALSE;
}
lpSocket->CtxtDeAllocate(lpIoContext);
}
InterlockedExchangeAdd(&lpSocket->IoPending,-1);
} else {
//Gui->MessageLog(L"NETWORK: Invalid Socket in Worker Thread");
DebugLog("NETWORK: Invalid Socket in Worker Thread");
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
//Gui->MessageLog(L"NETWORK: DISCONNECT EXCEPTION");
DebugLog("NETWORK: DISCONNECT EXCEPTION");
}
}
__finally
{
if (bCrSectClient)
{
LeaveCriticalSection(&ContextServer->CrSect_Client);
bCrSectClient = FALSE;
}
}
InterlockedExchangeAdd(&ContextServer->lBusyWorkThreads,-1);
continue;
}
lpIoContext = CONTAINING_RECORD(lpOverlapped, IO_CONTEXT, Overlapped);
switch(lpIoContext->IOOperation)
{
case ClientIoRead:
InterlockedExchangeAdd(&lpSocket->IoPending,-1);
lpIoContext->nRecvBytes += dwIoSize;
lpSocket->AddIn(lpIoContext);
lpSocket->isWaitRecv = FALSE;
GetLocalTime(&lpSocket->LastRecv);
break;
case ClientIoWrite:
// a write operation has completed, determine if all the data intended to be
// sent actually was sent.
InterlockedExchangeAdd(&lpSocket->IoPending, -1);
lpIoContext->nSentBytes += dwIoSize;
dwFlags = 0;
if (lpIoContext->nSentBytes < lpIoContext->nTotalBytes)
{
// the previous write operation didn't send all the data,
// post another send to complete the operation
//DebugLog("NETWORK: Resending incomplete data");
//Gui->MessageLog(L"NETWORK: Resending incomplete data..");
lpIoContext->wsabuf.buf = lpIoContext->Buffer + lpIoContext->nSentBytes;
lpIoContext->wsabuf.len = lpIoContext->nTotalBytes - lpIoContext->nSentBytes;
//lpIoContext->nTotalBytes = lpIoContext->wsabuf.len;
InterlockedExchangeAdd(&lpSocket->IoPending, 1);
rc = WSASend (
lpSocket->sd,
&lpIoContext->wsabuf, 1, &dwSendNumBytes,
dwFlags,
&lpIoContext->Overlapped, NULL);
if (SOCKET_ERROR == rc && (ERROR_IO_PENDING != WSAGetLastError()))
{
rc = WSAGetLastError();
DebugLog("NETWROK: RESEND ERROR");
//ContextServer->Disconnect(lpSocket);
lpSocket->pClient->Disconnect();
}
}
else
{
// previous write operation completed for this socket, delete context
EnterCriticalSection(&lpSocket->CrSect_OutBuffer);
bOutBuffSect = TRUE;
lpSocket->CtxtDeAllocate(lpIoContext);
if (lpSocket->OutBuffer.empty())
{
lpSocket->isSending = FALSE;
} else {
InterlockedExchangeAdd(&lpSocket->IoPending, 1);
lpIoContext = *lpSocket->OutBuffer.begin();
lpSocket->OutBuffer.erase(lpSocket->OutBuffer.begin());
rc = WSASend(
lpIoContext->pSocket->sd,
&lpIoContext->wsabuf, 1, &dwSendNumBytes,
dwFlags,
&lpIoContext->Overlapped, NULL);
}
if (SOCKET_ERROR == rc)
{
rc = WSAGetLastError();
if (rc != ERROR_IO_PENDING)
{
DebugLog("NETWORK: SEND ERROR");
//ContextServer->Disconnect(lpSocket);
}
}
LeaveCriticalSection(&lpSocket->CrSect_OutBuffer);
bOutBuffSect = FALSE;
}
break;
}
InterlockedExchangeAdd(&ContextServer->lBusyWorkThreads,-1);
}
}
__finally
{
if (bOutBuffSect)
LeaveCriticalSection(&lpSocket->CrSect_OutBuffer);
InterlockedExchangeAdd(&ContextServer->lWorkThreads,-1);
}
return FALSE;
SEH_END_FUNC
}