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

📄 irdatdi.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    }

    IrDAMsg.Prim                   = IRLMP_CONNECT_REQ;

    memcpy(&IrDAMsg.IRDA_MSG_RemoteDevAddr, 
           &pConn->SockAddrRemote.irdaDeviceID,
           IRDA_DEV_ADDR_LEN);
    
    IrDAMsg.IRDA_MSG_RemoteLsapSel = pConn->LSAPSelRemote;
    IrDAMsg.IRDA_MSG_LocalLsapSel  = pConn->LSAPSelLocal;
    IrDAMsg.IRDA_MSG_pQos          = NULL;
    IrDAMsg.IRDA_MSG_pConnData     = NULL;
    IrDAMsg.IRDA_MSG_ConnDataLen   = 0;
    IrDAMsg.IRDA_MSG_pContext      = pConn;
    IrDAMsg.IRDA_MSG_UseTtp        = 
        ! (pConn->UseExclusiveMode || pConn->UseIrLPTMode);

    IrDAMsg.IRDA_MSG_TtpCredits    = TINY_TP_RECV_CREDITS;
    IrDAMsg.IRDA_MSG_MaxSDUSize    = TINY_TP_RECV_MAX_SDU;

    pConn->TinyTPRecvCreditsLeft = TINY_TP_RECV_CREDITS;

    // CONNECT_REQ is pending. We should get either a CONNECT_CONF or a
    // DISCONNECT_IND.
    pConn->fConnPending = TRUE;
    pConn->pConnectCompleteContext = pTDIReq->RequestContext;
    REFADDCONN(pConn);
    FREE_CONN_LOCK(pConn);

    rc = IrlmpDown(NULL, &IrDAMsg);

    GET_CONN_LOCK(pConn);

    if (rc) {
        pConn->fConnPending = FALSE;
        pConn->pConnectCompleteContext = NULL;
    }

    switch (rc) {
    case 0:
        break;

    case IRLMP_LINK_IN_USE:
        TdiStatus = TDI_ADDR_IN_USE;
        break;

    case IRLMP_IN_EXCLUSIVE_MODE:
        TdiStatus = TDI_LINK_BUSY;
        break;

    default:
        DEBUGMSG(ZONE_WARN,
            (TEXT("IRLMP_Connect - unexpected error - %#x (%d)\r\n"), rc, rc));

        TdiStatus = TDI_CONNECTION_ABORTED;
        break;
    }

    FREE_CONN_LOCK(pConn);
    REFDELCONN(pConn);
    

done_nolocks:

    //
    // If we are pending the connection, we need to keep a reference so that
    // we know it doesn't go away (someone closes before connect conf) so
    // that we can complete the connection to AFD (otherwise AFD blocks
    // waiting for the connection and we don't have our connection context
    // anymore).
    //    
    
    if (TdiStatus != TDI_PENDING)
    {
        if (pConn) REFDELCONN(pConn);
    }

    DEBUGMSG(ZONE_FUNCTION, (TEXT("-IRLMP_Connect [%#x (%d)]\r\n"), TdiStatus, TdiStatus));
    return(TdiStatus);
    

//
// Common failure exit path
//
ExitIRLMP_Connect:
    FREE_CONN_LOCK(pConn);
    REFDELCONN(pConn);
    DEBUGMSG(ZONE_FUNCTION, (TEXT("-IRLMP_Connect [%#x (%d)].\r\n"), TdiStatus, TdiStatus));
    return(TdiStatus);

ExitIRLMP_Connect_IASQuery:
    LeaveCriticalSection(&csIasQuery);
    DEBUGMSG(ZONE_FUNCTION, (TEXT("-IRLMP_Connect [%#x (%d)] (IAS Query failed).\r\n"), TdiStatus, TdiStatus));
    return(TdiStatus);
}


#define LINGER_TIMEOUT 1000

void
LingerTimerFunc(
    CTEEvent * pCTEEvent,
    void * pContext
    )
{
    PIRLMP_CONNECTION pConn;
    PIRLMP_ADDR_OBJ   pAddrObj;
    BOOL              bDisconnected;
    IRDA_MSG          IrDAMsg;
    int               rc;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("+LingerTimerFunc(0x%X) at %d\r\n"), pContext, GetTickCount()));

    pConn = GETCONN(pContext);
    if (pConn == NULL)
    {
        DEBUGMSG(ZONE_ERROR|ZONE_FUNCTION, (TEXT("-LingerTimerFunc(0x%X - invalid) \r\n"), pContext));
        return;
    }

    VALIDCONN(pConn);
    GET_CONN_LOCK(pConn);

    bDisconnected = FALSE;

    if (pConn->ConnState == IRLMP_CONN_OPEN)
    {
        if (pConn->LingerTime <= LINGER_TIMEOUT) {
            //
            // The linger time has expired.
            //
            pConn->LingerTime = 0;
            pConn->LastSendsRemaining = 0;
            bDisconnected = TRUE;
        } else {
            pConn->LingerTime -= LINGER_TIMEOUT;
        }

        if (pConn->LastSendsRemaining <= pConn->SendsRemaining) {
            //
            // Didn't send anything in the last period
            //
            bDisconnected = TRUE;
        } else {
            pConn->LastSendsRemaining = pConn->SendsRemaining;
        }
    }

    if (bDisconnected) {
        pAddrObj = pConn->pAddrObj;
        VALIDADDR(pAddrObj);
        GET_ADDR_LOCK(pAddrObj);

        pConn->ConnState = IRLMP_CONN_CLOSING;
        IrdaAutoSuspend(FALSE);    // one less active connection

        DEBUGMSG(ZONE_WARN, (TEXT("LingerTimerFunc() Disconnecting pLsapCb 0x%x\r\n"), pConn->pIrLMPContext));

        pAddrObj->pEventDisconnect(
            pAddrObj->pEventDisconnectContext,
            pConn->pConnectionContext, 0, NULL, 
            0, NULL, TDI_DISCONNECT_ABORT);

        IrDAMsg.Prim                 = IRLMP_DISCONNECT_REQ;
        IrDAMsg.IRDA_MSG_pDiscData   = NULL;
        IrDAMsg.IRDA_MSG_DiscDataLen = 0;

        FREE_ADDR_LOCK(pAddrObj);
        FREE_CONN_LOCK(pConn);

        rc = IrlmpDown(pConn->pIrLMPContext, &IrDAMsg);
        if (rc) {
            DEBUGMSG(ZONE_ERROR, (TEXT("LingerTimerFunc() IrlmpDown(IRLMP_DISCONNECT_REQ) failed %d\r\n"), rc));
            GET_CONN_LOCK(pConn);
            TdiCleanupConnection(pConn);
        } else {
            REFDELCONN(pConn);
        }
    } else {
        CTEStartTimer(&pConn->LingerTimer, min(pConn->LingerTime, LINGER_TIMEOUT), LingerTimerFunc, pConn);
        FREE_CONN_LOCK(pConn);
        REFDELCONN(pConn);
    }


    DEBUGMSG(ZONE_FUNCTION, (TEXT("-LingerTimerFunc(0x%X) \r\n"), pContext));
}


/*****************************************************************************
*
*   @func   TDI_STATUS  |   IRLMP_Disconnect        |
*           Called at socket close time. IrLMP will call EventDisconnect() to
*           to complete the disconnect. It appears that only graceful closes
*           use this mechanism. For abortive closes, Winsock calls only
*           IRLMP_CloseConnection().
*
*	@rdesc
*           TDI_SUCCESS (tdistat.h) on success, or (tdistat.h)
*   @errors
*           @ecode  TDI_INVALID_CONNECTION          |   Bad connection.
*           @ecode  TDI_INVALID_STATE               |   Bad state.
*
*   @parm   PTDI_REQUEST    |   pTDIReq             |
*           (tdi.h) pTDIReq->Handle.ConnectionContext contains the 
*           CONNECTION_CONTEXT (tdi.sock    h, PVOID) of the IRLMP_CONNECTION. 
*           IRLMP_OpenConnection() assigns this value to be a pointer to
*           the IRLMP_CONNECTION.
*   @parm   PVOID           | pTimeOut              | Ignored.
*   @parm   ushort          | Flags                 |
*           (tdi.h) One of
*           <nl>    TDI_DISCONNECT_WAIT
*           <nl>    TDI_DISCONNECT_ABORT
*           <nl>    TDI_DISCONNECT_RELEASE
*           <nl>    TDI_DISCONNECT_CONFIRM
*           <nl>    TDI_DISCONNECT_ASYNC
*   @parm   PTDI_CONNECTION_INFORMATION | pDiscInfo | Ignored.
*   @parm   PTDI_CONNECTION_INFORMATION | pRetInfo  | Ignored.
*/

TDI_STATUS 
IRLMP_Disconnect(PTDI_REQUEST                pTDIReq,
                 PVOID                       pTimeOut,
                 ushort                      Flags,
                 PTDI_CONNECTION_INFORMATION pDiscInfo,
                 PTDI_CONNECTION_INFORMATION pRetInfo)
{
    TDI_STATUS        TdiStatus = TDI_SUCCESS;
    PIRLMP_CONNECTION pConn;
    PIRLMP_ADDR_OBJ   pAddrObj;
    IRDA_MSG          IrDAMsg;
    int               rc;

	DEBUGMSG(ZONE_FUNCTION, 
        (TEXT("+IRLMP_Disconnect(0x%X,0x%X,0x%X,0x%X,0x%X)\r\n"), 
         pTDIReq, pTimeOut, (unsigned) Flags, pDiscInfo, pRetInfo));

    pConn = GETCONN(pTDIReq->Handle.ConnectionContext);
    if (pConn == NULL)
    {
        goto done;
    }

    rc = 0;
    VALIDCONN(pConn);
    GET_CONN_LOCK(pConn);

    switch (pConn->ConnState) {
    case IRLMP_CONN_OPEN:
        if (Flags != TDI_DISCONNECT_ABORT) {
            pConn->LastSendsRemaining = pConn->SendsRemaining;
            pConn->LingerTime = 0xffffffff;
            if (pTimeOut && (*(DWORD *)pTimeOut)) {
                pConn->LingerTime = *(DWORD *)pTimeOut;
            }
            CTEStopTimer(&pConn->LingerTimer);
            CTEInitTimer(&pConn->LingerTimer);
            CTEStartTimer(&pConn->LingerTimer, min(pConn->LingerTime, LINGER_TIMEOUT), LingerTimerFunc, pConn);
            FREE_CONN_LOCK(pConn);
        } else {
            pAddrObj = pConn->pAddrObj;
            VALIDADDR(pAddrObj);
            GET_ADDR_LOCK(pAddrObj);

            pConn->ConnState = IRLMP_CONN_CLOSING;
            IrdaAutoSuspend(FALSE);    // one less active connection

            DEBUGMSG(ZONE_WARN, (TEXT("IRLMP_Disconnect() pLsapCb 0x%x\r\n"), pConn->pIrLMPContext));

            TdiStatus = pAddrObj->pEventDisconnect(
                pAddrObj->pEventDisconnectContext,
                pConn->pConnectionContext, 0, NULL, 
                0, NULL, TDI_DISCONNECT_WAIT);

            if (TdiStatus != TDI_SUCCESS)
            {
                DEBUGMSG(ZONE_ERROR, (TEXT("IRLMP_Disconnect() EventDisconnect() failed\r\n")));
            }

            IrDAMsg.Prim                 = IRLMP_DISCONNECT_REQ;
            IrDAMsg.IRDA_MSG_pDiscData   = NULL;
            IrDAMsg.IRDA_MSG_DiscDataLen = 0;

            FREE_ADDR_LOCK(pAddrObj);
            FREE_CONN_LOCK(pConn);

            rc = IrlmpDown(pConn->pIrLMPContext, &IrDAMsg);
            if (rc) {
                DEBUGMSG(ZONE_ERROR, (TEXT("IRLMP_Disconnect() IrlmpDown() failed %d\r\n"), rc));
            }

        }
        break;

    case IRLMP_CONN_OPENING:
        DEBUGMSG(ZONE_ERROR, (TEXT("IRLMP_Disconnect() called in OPENING state!\n")));
        TdiStatus = TDI_INVALID_STATE;
        FREE_CONN_LOCK(pConn);
        break;

    default:
        FREE_CONN_LOCK(pConn);
        TdiStatus = TDI_INVALID_STATE;
        break;
    }

done:

    if (pConn)
    {
        if (rc) {
            GET_CONN_LOCK(pConn);
            TdiCleanupConnection(pConn);
        } else {
            REFDELCONN(pConn);
        }
    }

    DEBUGMSG(ZONE_FUNCTION,
        (TEXT("-IRLMP_Disconnect [%#x (%d)]\r\n"), TdiStatus, TdiStatus));
    return (TdiStatus);
}

/*****************************************************************************
*
*   @func   TDI_STATUS  |   IRLMP_Listen    | THIS IS NEVER CALLED.
*/

TDI_STATUS 
IRLMP_Listen(PTDI_REQUEST                pTDIReq,
             ushort                      Flags,
             PTDI_CONNECTION_INFORMATION pAcceptableInfo,
             PTDI_CONNECTION_INFORMATION pConnectedInfo)
{
	DEBUGMSG(ZONE_FUNCTION, 
        (TEXT("IRLMP_Listen(0x%X,0x%X,0x%X,0x%X)\r\n"), 
        pTDIReq, (unsigned) Flags, pAcceptableInfo, pConnectedInfo));

    ASSERT(0);

    return(TDI_SUCCESS);
}

/*****************************************************************************
*
*   @func   TDI_STATUS  |   IRLMP_Accept    | THIS IS NEVER CALLED.
*/

TDI_STATUS 
IRLMP_Accept(PTDI_REQUEST                pTDIReq,
             PTDI_CONNECTION_INFORMATION pAcceptInfo,
             PTDI_CONNECTION_INFORMATION pConnectedInfo)
{
	DEBUGMSG(ZONE_FUNCTION, 
        (TEXT("IRLMP_Accept(0x%X,0x%X,0x%X)\r\n"), 
        pTDIReq, pAcceptInfo, pConnectedInfo));

    ASSERT(0);

    return(TDI_SUCCESS);
}

/*****************************************************************************
*
*   @func   TDI_STATUS  |   IRLMP_Receive   | 
*           Called to recv data driectly into a user buffer or to signal
*           a flow off condition.
*
*	@rdesc
*           TDI_SUCCESS (tdistat.h) on success, or (tdistat.h)
*   @errors
*           @ecode  TDI_PENDING             |
*           @ecode  TDI_NO_RESOURCES        |
*           @ecode  TDI_INVALID_STATE       |
*           @ecode  TDI_INVALID_CONNECTION  |
*
*   @parm   PTDI_REQUEST    |   pTDIReq     |
*           (tdi.h) pTDIReq->Handle.ConnectionContext contains the 
*           CONNECTION_CONTEXT (tdi.h, PVOID) of the IRLMP_CONNECTION. 
*           IRLMP_OpenConnection() assigns this value to be a pointer to
*           the IRLMP_CONNECTION.
*           <nl>pTDIReq->RequestNotifyObject is a pointer (void (*)(PVOID 
*           Context, TDI_STATUS TdiStatus, DWORD BytesRecvd)) to a Winsock 
*           routine to call if this function returns TDI_PENDING.
*           <nl>pTDIReq->RequestNotifyContext is a Winsock context to return in
*           the callback.
*   @parm   ushort          |   Flags       |
*           (tdi.h) One of
*           <nl>TDI_RECEIVE_TRUNCATED
*           <nl>TDI_RECEIVE_FRAGMENT
*           <nl>TDI_RECEIVE_BROADCAST
*           <nl>TDI_RECEIVE_MULTICAST
*           <nl>TDI_RECEIVE_PARTIAL
*           <nl>TDI_RECEIVE_NORMAL
*           <nl>TDI_RECEIVE_EXPEDITED
*           <nl>TDI_RECEIVE_PEEK
*           <nl>TDI_RECEIVE_NO_RESPONSE_EXP
*           <nl>TDI_RECEIVE_COPY_LOOKAHEAD
*           <nl>TDI_RECEIVE_ENTIRE_MESSAGE
*           <nl>TDI_RECEIVE_AT_DISPATCH_LEVEL
*   @parm   unit *          |   RecvLen     |
*           Data size of the NDIS buffer (chain?).
*   @parm   PNDIS_BUFFER    | pNDISBuf      |
*           (ndis.h) Pointer to output NDIS_BUFFER.
*
*   @xref   <f EventReceive>
*/

#ifdef DEBUG

⌨️ 快捷键说明

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