📄 overlap.cpp
字号:
{
dbgprint("OverlappedManagerThread: WaitForSingleObjectEx() failed: %d",
GetLastError());
}
else
{
lpPid = DequeueOverlappedOperation();
if (!lpPid)
continue;
ExecuteOverlappedOperation(lpPid, FALSE);
}
}
}
ExitThread(0);
return 0;
}
void StartOverlappedManager()
{
//
// Make sure things are already initalized
//
if (!gWorkerThread[0])
{
InitOverlappedManager();
if (!gWorkerThread[0])
{
dbgprint("GetOverlappedStructure: Still not properly inititalized!");
return;
}
}
}
//
// Function: GetOverlappedStructure
//
// Description:
// This returns an unused WSAOVERLAPPEDPLUS structure. We maintain a list
// of freed structures so that we don't spend too much time allocating and
// freeing memory.
//
LPWSAOVERLAPPEDPLUS GetOverlappedStructure(SOCK_INFO *SocketContext)
{
LPWSAOVERLAPPEDPLUS lpWorkerOverlappedPlus = NULL;
if (!SocketContext)
{
dbgprint("GetOverlappedStructure: SocketContext == NULL");
}
AcquireSocketLock(SocketContext);
EnterCriticalSection(&gOverlappedCS);
//
// We have to keep track of the number of outstanding overlapped requests
// an application has. Otherwise, if the app were to close a socket that
// had oustanding overlapped ops remaining, we'd start leaking structures
// in OverlappedPool. The idea here is to force the CallerSocket to remain
// open until the lower provider has processed all the overlapped requests.
// If we closed both the lower socket and the caller socket, we would no
// longer be able to correlate completed requests to any apps sockets.
//
(SocketContext->dwOutstandingAsync)++;
if (FreePool)
{
lpWorkerOverlappedPlus = FreePool;
FreePool = FreePool->next;
lpWorkerOverlappedPlus->next = NULL;
}
else // Empty pool
{
if (AllocateFreePool() != WSAENOBUFS)
{
lpWorkerOverlappedPlus = FreePool;
FreePool = FreePool->next;
lpWorkerOverlappedPlus->next = NULL;
}
}
if (lpWorkerOverlappedPlus)
memset(lpWorkerOverlappedPlus, 0, sizeof(WSAOVERLAPPEDPLUS));
LeaveCriticalSection(&gOverlappedCS);
ReleaseSocketLock(SocketContext);
return lpWorkerOverlappedPlus;
}
//
// Function: PutbackOverlappedStructure
//
// Description:
// Once we're done using a WSAOVERLAPPEDPLUS structure we return it to
// a list of free structures for re-use later.
//
void PutbackOverlappedStructure(WSAOVERLAPPEDPLUS *olp)
{
EnterCriticalSection(&gOverlappedCS);
memset(olp, 0, sizeof(WSAOVERLAPPEDPLUS));
//HeapFree(hLspHeap, 0, olp);
olp->lpCallerThreadId = (LPWSATHREADID)(ULONG_PTR)0xbadbeef;
olp->next = FreePool;
FreePool = olp;
LeaveCriticalSection(&gOverlappedCS);
}
//
// Function: SetOverlappedInProgress
//
// Description:
// Simply set the interal fields of an OVERLAPPED structure to the
// "in progress" state.
//
void SetOverlappedInProgress(OVERLAPPED *ol)
{
ol->Internal = WSS_OPERATION_IN_PROGRESS;
ol->InternalHigh = 0;
}
//
// Function: IntermediateCompletionRoutine
//
// Description:
// Once an overlapped operation completes we call this routine to keep
// count of the bytes sent/received as well as to complete the operation
// to the application.
//
void CALLBACK IntermediateCompletionRoutine(DWORD dwError,
DWORD cbTransferred,
LPWSAOVERLAPPED lpOverlapped,
DWORD dwFlags)
{
LPWSAOVERLAPPEDPLUS olp = (LPWSAOVERLAPPEDPLUS) lpOverlapped;
SOCK_INFO *SocketContext,
*AcceptSocketContext;
int Error,
ret;
if (lpOverlapped == NULL)
{
dbgprint("IntermediateCompletionRoutine: lpOverlapped == NULL!");
return;
}
//
// We actually already have the socket context for this operation (its in
// the WSAOVERLAPPEDPLUS structure but do this anyway to make sure the
// socket hasn't been closed as well as to increment the ref count while
// we're accessing the SOCK_INFO structure.
//
SocketContext = FindAndLockSocketContext(olp->CallerSocket, &Error);
if (SocketContext == NULL)
{
dbgprint("IntermediateCompletionRoutine: WPUQuerySocketHandleContext failed: %d", Error);
PutbackOverlappedStructure(olp);
return;
}
if (dwError == WSA_IO_PENDING)
{
//
// Get the results of the operation
//
dwError = NO_ERROR;
ret = olp->Provider->NextProcTable.lpWSPGetOverlappedResult(olp->ProviderSocket,
lpOverlapped,
&cbTransferred,
FALSE,
&dwFlags,
(int *)&dwError);
if (ret == FALSE)
{
dbgprint("IntermediateCompletionRoutine: WSPGetOverlappedResult failed: %d", dwError);
}
dbgprint("Bytes transferred on socket %d: %d [op=%d; err=%d]",
olp->CallerSocket, cbTransferred, olp->Operation, dwError);
}
olp->lpCallerOverlapped->Offset = dwError;
olp->lpCallerOverlapped->OffsetHigh = dwFlags;
olp->lpCallerOverlapped->InternalHigh = cbTransferred;
if (dwError == 0)
{
AcquireSocketLock(SocketContext);
switch (olp->Operation)
{
case LSP_OP_RECV:
SocketContext->BytesRecv += cbTransferred;
FreeBuffer(olp->RecvArgs.lpBuffers);
break;
case LSP_OP_RECVFROM:
SocketContext->BytesRecv += cbTransferred;
FreeBuffer(olp->RecvFromArgs.lpBuffers);
break;
case LSP_OP_SEND:
SocketContext->BytesSent += cbTransferred;
FreeBuffer(olp->SendArgs.lpBuffers);
break;
case LSP_OP_SENDTO:
SocketContext->BytesSent += cbTransferred;
FreeBuffer(olp->SendToArgs.lpBuffers);
break;
case LSP_OP_TRANSMITFILE:
SocketContext->BytesSent += cbTransferred;
break;
case LSP_OP_ACCEPTEX:
AcceptSocketContext = FindAndLockSocketContext(
olp->AcceptExArgs.sAcceptSocket,
&Error
);
if (AcceptSocketContext == NULL)
{
dbgprint("IntermediateCompletionRoutine: WPUQuerySocketHandleContext failed (accept socket)");
}
AcceptSocketContext->BytesRecv += cbTransferred;
UnlockSocketContext(AcceptSocketContext, &Error);
break;
default:
break;
}
ReleaseSocketLock(SocketContext);
}
UnlockSocketContext(SocketContext, &Error);
//
// If the app supplied a completion routine, queue it up for completion
//
if (olp->lpCallerCompletionRoutine)
{
olp->lpCallerOverlapped->Internal = (ULONG_PTR)olp->lpCallerCompletionRoutine;
if (MainUpCallTable.lpWPUQueueApc(olp->lpCallerThreadId,
CallUserApcProc,
(DWORD_PTR) olp->lpCallerOverlapped,
&Error) == SOCKET_ERROR)
{
dbgprint("IntermediateCompletionRoutine: WPUQueueApc() failed: %d", Error);
}
}
else
{
// Otherwise we signal that the op has completed
//
if (WPUCompleteOverlappedRequest(olp->CallerSocket,
olp->lpCallerOverlapped,
dwError,
cbTransferred,
&Error) == SOCKET_ERROR)
{
dbgprint("WPUCompleteOverlappedRequest failed: %d", Error);
}
dbgprint("Completing request on socket: %d", olp->CallerSocket);
}
//
// Cleanup the accounting on the socket
//
//(SocketContext->dwOutstandingAsync)--;
CheckForContextCleanup(olp);
PutbackOverlappedStructure(olp);
return;
}
//
// Function: CallerUserApcProc
//
// Description:
// This function completes an overlapped request that supplied an APC.
//
VOID CALLBACK CallUserApcProc(ULONG_PTR Context)
{
LPOVERLAPPED lpOverlapped;
LPWSAOVERLAPPED_COMPLETION_ROUTINE UserCompletionRoutine;
lpOverlapped = (LPOVERLAPPED) Context;
UserCompletionRoutine = (LPWSAOVERLAPPED_COMPLETION_ROUTINE)lpOverlapped->Internal;
lpOverlapped->Internal = lpOverlapped->Offset; // To make sure it
// in no longer is
// WSS_OPERATION_IN_PROGRESS
UserCompletionRoutine (
(DWORD)lpOverlapped->Offset,
(DWORD)lpOverlapped->InternalHigh,
lpOverlapped,
(DWORD)lpOverlapped->OffsetHigh
);
return;
}
void CheckForContextCleanup(WSAOVERLAPPEDPLUS *ol)
{
SOCK_INFO *SocketContext=NULL;
int Error;
SocketContext = FindAndLockSocketContext(ol->CallerSocket, &Error);
if (SocketContext == NULL)
{
return;
}
AcquireSocketLock(ol->SockInfo);
(ol->SockInfo->dwOutstandingAsync)--;
if ((ol->SockInfo->bClosing) &&
(ol->SockInfo->dwOutstandingAsync == 0) &&
(ol->SockInfo->RefCount == 1))
{
//
// If the calling app closed the socket while there were still outstanding
// async operations then all the outstanding operations have completed so
// we can close the apps socket handle.
//
if (MainUpCallTable.lpWPUCloseSocketHandle(ol->CallerSocket, &ol->Error) == SOCKET_ERROR)
{
dbgprint("CheckForContextClenaup: WPUCloseSocketHandle() failed: %d", ol->Error);
}
ol->SockInfo->LayeredSocket = INVALID_SOCKET;
RemoveSocketInfo(ol->SockInfo->Provider, ol->SockInfo);
dbgprint("Closing socket %d Bytes Sent [%lu] Bytes Recv [%lu]",
ol->CallerSocket, ol->SockInfo->BytesSent, ol->SockInfo->BytesRecv);
ReleaseSocketLock(ol->SockInfo);
ol->SockInfo = NULL;
DeleteCriticalSection(&SocketContext->SockCritSec);
dbgprint("Freeing a SOCK_INFO (SocketContext) structure");
HeapFree(hLspHeap, 0, SocketContext);
return;
}
ReleaseSocketLock(SocketContext);
UnlockSocketContext(SocketContext, &Error);
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -