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

📄 overlap.cpp

📁 这个是网络编程
💻 CPP
📖 第 1 页 / 共 3 页
字号:
            {
                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 + -