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

📄 edbgprot.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 4 页
字号:
    
    if (!IS_VALID_ID(Id))
        return FALSE;

    // Check that client is registered
    if (!pClient || (pClient->ServiceId != Id)) {
        KITLOutputDebugString ("\r\n!KITLRecv: Invalid client ID %u!!!!!\r\n",Id);
        return FALSE;
    }

    // establish connection with desktop
    if (!(pClient->State & KITL_CLIENT_REGISTERED) && !ExchangeConfig (pClient)) {
        KITL_DEBUGMSG (ZONE_WARNING, ("\r\n!KITLRecv: Client (%d) not registered!\r\n", Id));
        return FALSE;
    }

    // check if the data overlapped with buffer pool, reject if it does
    if ((pRecvBuf < pClient->pRxBufferPool + pClient->WindowSize * KITL_MTU)
        && (pRecvBuf + *pdwLen > pClient->pRxBufferPool)) {
        KITLOutputDebugString ("!KITLRecv: Receive buffer overlapped with buffer pools\r\n");
        return FALSE;
    }

    // Determine whether we can make system calls or not. There are three cases where we cannot:
    //     o  During system init, until KITLInitializeInterrupt is called
    //     o  When we are called from within a system call (this case actually should never happen,
    //        since the only service called in a syscall is debug messages, which shouldn't call recv).
    //     o  When we are called from the debugger
    if (KITLGlobalState & KITL_ST_MULTITHREADED) {
        // If we're in a sys call, can't block on anything (but won't be preempted)
        if (InSysCall()) {
            KITL_DEBUGMSG(ZONE_WARNING,("KITLRecv(%u): InSysCall()\n",Id));
            fUseSysCalls = FALSE;
            fRestoreClientState = TRUE;
            PrevSyscallState = pClient->State & KITL_USE_SYSCALLS;
            pClient->State &= ~KITL_USE_SYSCALLS;
                    
            KITLGlobalState &= ~KITL_ST_MULTITHREADED;
            fRestoreGlobalState = TRUE;

            // The protocol state machine can't handle us stepping in at some arbitrary point
            // and mucking with state, so if someone owns the CS, just bail and print to the
            // debug serial port.
            if (pClient->ClientCS.OwnerThread) {
                KITL_DEBUGMSG(ZONE_WARNING,("!KITLRecv(%u): In syscall with ClientCS owned",Id));
                fRet = FALSE;
                goto KITLRecv_exit;
            }
        }
        else if (pClient->State & KITL_USE_SYSCALLS) {
            fUseSysCalls = TRUE;
        }
        else {
            // This client cannot use system calls, and guarantees that scheduling is disabled while
            // it is called into the KITL functions. Currently, this only applies to KDBG client.
            if (Id != KITL_SVC_KDBG) {
                KITL_DEBUGMSG(ZONE_WARNING,("!KITLRecv(%u): SYSCALLS for client turned off\n",Id)); 
            }
            fUseSysCalls = FALSE;
            KITLGlobalState &= ~KITL_ST_MULTITHREADED;
            fRestoreGlobalState = TRUE;
        }
    }
    else {
        // Single threaded and non preemptible
        fUseSysCalls = FALSE;
    }

    dwStartTime = CurMSec;
    if (Timeout != INFINITE)
        Timeout *= 1000;

    if (fUseSysCalls)
        EnterCriticalSection(&pClient->ClientCS);
    
    KITL_DEBUGMSG(ZONE_RECV,("+KITLRecv(%u): Waiting for message (expect Seq %u). User bufsize: %u, SC:%u\n",
                             Id,pClient->RxSeqNum,*pdwLen,fUseSysCalls));
                             
    while (pClient->RxFrameLen[pClient->NextRxIndex] == 0) {
        if (fUseSysCalls) {
            LeaveCriticalSection (&pClient->ClientCS);
        }
        
        if (!fUseSysCalls || !(KITLGlobalState & KITL_ST_INT_ENABLED)) {
            // polling mode or debugger
            if (!KITLPollData(fUseSysCalls, NULL, NULL)) {
                fRet = FALSE;
                goto KITLRecv_exit;
            }
            
            if ((pClient->RxFrameLen[pClient->NextRxIndex] == 0)
                && (Timeout != INFINITE)
                && (!Timeout  || ((int) (CurMSec - dwStartTime) >= (int) Timeout))) {
                if (Timeout)
                    KITL_DEBUGMSG(ZONE_WARNING,("KITL(%u): Timed out polling for recv data\n",Id));

                fRet = FALSE;
                goto KITLRecv_exit;
            }
            
        } else if (SC_WaitForMultiple (1, &pClient->evRecv, 0, (Timeout == INFINITE)? INFINITE : Timeout) != WAIT_OBJECT_0) {
            KITL_DEBUGMSG(ZONE_WARNING,("KITL(%u): Timed out waiting for recv data\n",Id));
            fRet = FALSE;
            goto KITLRecv_exit;
        }
        
        if (!(pClient->State & KITL_CLIENT_REGISTERED)) {
            // client de-registered, return an error
            KITL_DEBUGMSG(ZONE_WARNING,("KITL(%u): Client de-registered while waiting to receive data\n",Id));
            fRet = FALSE;
            goto KITLRecv_exit;
        }
        if (fUseSysCalls) {
            EnterCriticalSection(&pClient->ClientCS);   
        }
    }

    // Copy received data into buffer
    dwBytesToCopy = min(pClient->RxFrameLen[pClient->NextRxIndex], *pdwLen);
    KITL_DEBUGMSG(ZONE_RECV,("-KITLRecv(%u): Read %u bytes from slot %u, copying %u\n",
                             Id,pClient->RxFrameLen[pClient->NextRxIndex],pClient->NextRxIndex,dwBytesToCopy));
    memcpy(pRecvBuf, pClient->pRxBufferPool+(pClient->NextRxIndex*KITL_MTU),dwBytesToCopy);
    *pdwLen = dwBytesToCopy;
    pClient->RxFrameLen[pClient->NextRxIndex] = 0;
    pClient->NextRxIndex = (pClient->NextRxIndex+1) % pClient->WindowSize;

    // Send ack if required
    if (!(pClient->CfgFlags & KITL_CFGFL_NOACKS))
        SendAckNack(TRUE,pClient, (UCHAR)(pClient->RxWinEnd - pClient->WindowSize));
    
    // Advance top of Rx window
    SEQ_INC(pClient->RxWinEnd);
    if (fUseSysCalls)
        LeaveCriticalSection(&pClient->ClientCS);

KITLRecv_exit:
    if (fRestoreClientState)
        pClient->State |= PrevSyscallState;
    if (fRestoreGlobalState)
        KITLGlobalState |= KITL_ST_MULTITHREADED;
    if (fRet == FALSE) {
        KITL_DEBUGMSG(ZONE_WARNING,("\nKITL(%u): EdbgRecv returning FALSE!!!!!!\n",Id));
    }
    return fRet;
}


/* HandleRecvInterrupt
 *
 *   Called to process a receive interrupt.  Is also called in polling mode, to
 *   check for and handle received frames.  Buffer must be able to hold an Ethernet
 *   KITL_MTU (1500 bytes) of data.
 */
void HandleRecvInterrupt(UCHAR *pRecvBuf, BOOL fUseSysCalls, PFN_TRANSMIT pfnTransmit, LPVOID pData)
{
    WORD wLen = KITL_MTU;
    BOOL fFrameRecvd;

    // Receive data into buffer
    do {
        if (!fUseSysCalls)
            fFrameRecvd = Kitl.pfnRecv (pRecvBuf, &wLen);
        else if (IsDesktopDbgrExist ())
            fFrameRecvd = KCall((PKFN) Kitl.pfnRecv, pRecvBuf, &wLen);
        else {
            EnterCriticalSection (&KITLKCallcs);
            fFrameRecvd = Kitl.pfnRecv (pRecvBuf, &wLen);
            LeaveCriticalSection (&KITLKCallcs);
        }
        if (fFrameRecvd) {
            ProcessRecvFrame (pRecvBuf,wLen,fUseSysCalls, pfnTransmit, pData);
            wLen = KITL_MTU;
        }
    } while (fFrameRecvd);
}

// Frame received from the wire, with all protocol headers attached
static BOOL ProcessRecvFrame(UCHAR *pFrame, WORD wMsgLen, BOOL fUseSysCalls, PFN_TRANSMIT pfnTransmit, LPVOID pData)
{
    KITL_HDR *pMsg;
    KITL_CLIENT *pClient = NULL;
    BOOL fRet = TRUE;
    UCHAR RxBufOffset;
    WORD  wDataLen;
    UCHAR ClientIdx;
    // let the transport layer decode the frame
    if (!(pMsg = (KITL_HDR *) Kitl.pfnDecode (pFrame, &wMsgLen))) {
        KITL_DEBUGMSG(ZONE_RECV, ("ProcessRecvFrame: Received Unhandled frame\n"));
        return FALSE;
    }

    // is it a valid KITL message?
    if (pMsg->Id != KITL_ID) {
        KITL_DEBUGMSG(ZONE_WARNING,("KITL: Got unrecognized Id: %X\r\n",pMsg->Id));
        return FALSE;
    }
    
    // Validate length
    if (wMsgLen < sizeof(KITL_HDR)) {
        KITL_DEBUGMSG(ZONE_WARNING,("KITL: Invalid length %u\n",wMsgLen));
        return FALSE;
    }
    if (KITLDebugZone & ZONE_FRAMEDUMP)
        KITLDecodeFrame("<<KITLRecv", pMsg, wMsgLen);
    
    // Check for administrative messages
    if (pMsg->Service == KITL_SVC_ADMIN)
        return ProcessAdminMsg(pMsg, wMsgLen, fUseSysCalls, pfnTransmit, pData);

    // Service Id is index into KITLClients array
    ClientIdx = pMsg->Service;
    if (ClientIdx >= MAX_KITL_CLIENTS) {
        KITL_DEBUGMSG(ZONE_WARNING,("!ProcessKITLMsg: Invalid ServiceId: %u\n",pMsg->Service));
        return FALSE;
    }

    pClient = KITLClients[ClientIdx];
    
    // Until we complete registering, only handle administrative messages
    if (!pClient || !(pClient->State & KITL_CLIENT_REGISTERED)) {
        KITL_DEBUGMSG(ZONE_WARNING,("!ProcessKITLMsg: Client %u not registered\n",ClientIdx));
        return FALSE;
    }
    if (pMsg->Service != pClient->ServiceId) {
        KITL_DEBUGMSG(ZONE_WARNING,("!ProcessKITLMsg: Mismatch in service Id for Client %u (Got %u, expect %u)\n",
                                    ClientIdx,pMsg->Service,pClient->ServiceId));
        return FALSE;
    }

    if (pClient->State & KITL_USE_SYSCALLS) {
        if (fUseSysCalls)  
            EnterCriticalSection(&pClient->ClientCS);
        else if (pClient->ClientCS.OwnerThread) {
            // We can't get the client CS, and it is owned - just toss frame
            KITL_DEBUGMSG(ZONE_WARNING,("!KITL(%u) tossing msg %u (Can't get CS)\n",ClientIdx, pMsg->SeqNum));
            return FALSE;
        }
    }

    // we've being in sync with the desktop
    pClient->State |= KITL_SYNCED;
    
    // Put flags and seq # to LEDs
    KITL_DEBUGLED(LED_PEM_SEQ, ((DWORD) pMsg->Flags << 24) | pMsg->SeqNum);
    
    // OK, valid message, see if it's an ACK
    if (pMsg->Flags & KITL_FL_ACK) {
        KITL_DEBUGMSG(ZONE_RECV,("KITL(%u): Received ack for msg %u, Tx window: %u,%u\n",
                                 ClientIdx,pMsg->SeqNum, pClient->AckExpected,pClient->TxSeqNum));
        // ACKs acknowledge all data up to the ACK sequence #
        while (SEQ_BETWEEN(pClient->AckExpected, pMsg->SeqNum, pClient->TxSeqNum)) {        
            if ((pClient->State & KITL_USE_SYSCALLS) &&
                ((pClient->CfgFlags & KITL_CFGFL_STOP_AND_WAIT) ||
                 (SEQ_DELTA(pClient->AckExpected, pClient->TxSeqNum) >= pClient->WindowSize-1) ||
                 !(KITLGlobalState & KITL_ST_INT_ENABLED))) {
                if (fUseSysCalls)
                    SetClientEvent(pClient,pClient->evTxFull);
                else {
                    // Can't process message at this time...
                    KITL_DEBUGMSG(ZONE_WARNING,("!KITL(%u): Tossing ACK %u (Can't set event)\n",
                                                ClientIdx, pMsg->SeqNum));
                    return FALSE;
                }
            }
            // Stop retransmission timer. 
            TimerStop(pClient, (UCHAR)(pClient->AckExpected % pClient->WindowSize),fUseSysCalls);
            SEQ_INC(pClient->AckExpected);
        }
        goto ProcessKITLMsg_exit;
    }

    // Handle NACKs - retransmit requested frame if it is in our Tx window
    if (pMsg->Flags & KITL_FL_NACK) {
        KITL_DEBUGMSG(ZONE_WARNING,("KITL(%u): Received NACK for msg %u, Tx window: %u,%u\n",
                                    ClientIdx,pMsg->SeqNum, pClient->AckExpected,pClient->TxSeqNum)); 
        if (SEQ_BETWEEN(pClient->AckExpected, pMsg->SeqNum, pClient->TxSeqNum)) {
            UCHAR Index = pMsg->SeqNum % pClient->WindowSize;
            if (pClient->TxFrameLen[Index]) {
                // Restart retransmission timer (note we can't start timers if syscalls
                // are disabled, but this shouldn't be a problem; we'll just potentially
                // retransmit an extra frame if the timer fires before we get the ACK)
                if (fUseSysCalls)
                    TimerStop(pClient,Index,fUseSysCalls);
                RetransmitFrame(pClient, Index, fUseSysCalls);
                if (fUseSysCalls)
                    TimerStart(pClient,Index,KITL_RETRANSMIT_INTERVAL_MS,fUseSysCalls);
            }
            else
                KITL_DEBUGMSG(ZONE_WARNING,("!KITL(%u): NACK in window, but TxFrameLen empty!\n",ClientIdx));
        }
        else
            KITL_DEBUGMSG(ZONE_WARNING,("!KITL(%u): Received NACK outside of TX window: Seq: %u, Window: %u,%u\n",
                                        ClientIdx,pMsg->SeqNum,pClient->AckExpected,pClient->TxSeqNum));
        goto ProcessKITLMsg_exit;
    }
    
    // Data frame.  Place in appropriate slot in Rx buffer pool. Note that we defer acking
    // received frames until they are read from the buffer, in KITLRecv.
    RxBufOffset = pMsg->SeqNum % pClient->WindowSize;

    if (! SEQ_BETWEEN(pClient->RxSeqNum, pMsg->SeqNum, pClient->RxWinEnd)) {
        UCHAR uLastACK = (UCHAR) (pClient->RxWinEnd - pClient->WindowSize - 1);

        KITL_DEBUGMSG (ZONE_WARNING, ("KITL(%u): Received msg outside window: Seq:%u, Win:%u,%u\n",
                              ClientIdx,pMsg->SeqNum,pClient->RxSeqNum,pClient->RxWinEnd));

        // Special case to handle lost ACKs - if an ack is dropped, our Rx window will have
        // advanced beyond the seq # of the retransmitted frame.  Since ACKs ack all messages
        // up to the ack #, we only need to check the last frame. 
        if (pMsg->SeqNum == uLastACK) {
            KITL_DEBUGMSG(ZONE_WARNING,("KITL(%u): Lost ACK (seq: %u, win: %u,%u)\n",ClientIdx,
                                        pMsg->SeqNum,uLastACK,pClient->RxWinEnd));
            SendAckNack (TRUE, pClient, uLastACK);
        }
    } else if (pClient->RxFrameLen[RxBufOffset] != 0) {
        // If all our buffers are full, toss frame (will be acked when data is read in KITLRecv)
        KITL_DEBUGMSG(ZONE_WARNING,("KITL(%u): Received duplicate (Seq:%u), slot %u already full. Win: %u,%u\n",
                                    ClientIdx,pMsg->SeqNum,RxBufOffset,pClient->RxSeqNum,pClient->RxWinEnd));
    } else {
        DWORD OldProcPerms;

        // If we're in non-preemptible mode, can't set the receive event, so just toss message
        // and wait for retry.
        if (!fUseSysCalls && (pClient->State & KITL_USE_SYSCALLS)) {
            KITL_DEBUGMSG(ZONE_WARNING,("KITL(%u): Tossing frame %u (Can't signal Rx event)\n",
                                        ClientIdx,pMsg->SeqNum));
            return FALSE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -