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

📄 irdatdi.c

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

    // Init lock.
    CTEInitLock(&pNewAddrObj->Lock);

    // Initialize connection list head.
    InitializeListHead(&pNewAddrObj->ConnList);
    
    // These values are set by IRLMP_SetEvent().
    pNewAddrObj->pEventConnect                 = NULL;
    pNewAddrObj->pEventConnectContext          = NULL;
    pNewAddrObj->pEventDisconnect              = NULL;
    pNewAddrObj->pEventDisconnectContext       = NULL;
    pNewAddrObj->pEventError                   = NULL;
    pNewAddrObj->pEventDisconnectContext       = NULL;
    pNewAddrObj->pEventReceive                 = NULL;
    pNewAddrObj->pEventReceiveContext          = NULL;
    pNewAddrObj->pEventReceiveDatagram         = NULL;
    pNewAddrObj->pEventReceiveDatagramContext  = NULL;
    pNewAddrObj->pEventReceiveExpedited        = NULL;
    pNewAddrObj->pEventReceiveExpeditedContext = NULL;
    
    // If there is no service name, save LSAP-SELXxx.
    if (pIrdaAddr->irdaServiceName[0] == 0)
    {
        // Not a server by default. If the app then does a listen on the
        // socket we get a WSH_NOTIFY_LISTEN and change the addr obj to
        // a server.
        pNewAddrObj->IsServer = FALSE;
        SetLsapSelAddr(LsapSel, &pIrdaAddr->irdaServiceName[0]);
    }
    else
    {
        // This will allow us to return an error to the user if a
        // connect attempt is made after binding to a service name.
        pNewAddrObj->IsServer = TRUE;
    }

    // Save the address and protocol.
    // Assume SOCKADDR_IRDA is TA_ADDRESS.AddressType, TA_ADDRESS.Address.
    memcpy(&pNewAddrObj->SockAddrLocal, 
           pIrdaAddr,
           sizeof(SOCKADDR_IRDA));

    pNewAddrObj->Protocol         = Protocol;
    pNewAddrObj->LSAPSelLocal     = LsapSel;
    pNewAddrObj->UseExclusiveMode = FALSE;
    pNewAddrObj->UseIrLPTMode     = FALSE;
    pNewAddrObj->Use9WireMode     = FALSE;
    pNewAddrObj->UseSharpMode     = FALSE;

    // Keep our ref, since we are passing it off to AFD. We will 
    // remove this ref in IRLMP_CloseAddress.

ExitIRLMP_OpenAddress:

    LeaveCriticalSection(&csIrObjList);
    DEBUGMSG(ZONE_FUNCTION,
        (TEXT("-IRLMP_OpenAddress [Status: %d; hAddr: %#x; ")
         TEXT("pAddr: 0x%x, id: %d]\r\n"),
         TdiStatus, pTDIReq->Handle.AddressHandle, 
         pNewAddrObj, (NULL == pNewAddrObj) ? 0 : pNewAddrObj->dwId));
	return (TdiStatus);
}

/*****************************************************************************
*
*   @func   TDI_STATUS  |   IRLMP_CloseAddress  |
*           Called at socket close time after IRLMP_Disconnect()
*           and IRLMP_CloseConnection(). Frees the IRDA_ADDR_OBJ.
*
*	@rdesc
*           TDI_SUCCESS (tdistat.h) on success, or (tdistat.h)
*   @errors
*           @ecode  TDI_ADDR_INVALID            |  Bad address object.
*
*   @parm   PTDI_REQUEST        |   pTDIReq     |
*           (tdi.h) pTDIReq->Handle.AddressHandle is a handle to the
*           IRLMP_ADDR_OBJ. IRLMP_OpenAddress() assigns this value to be
*           a pointer to the IRLMP_ADDR_OBJ.
*/

TDI_STATUS
IRLMP_CloseAddress(PTDI_REQUEST pTDIReq)
{
    TDI_STATUS        TdiStatus = TDI_SUCCESS;
    PIRLMP_ADDR_OBJ   pAddrObj = NULL;
    PIRLMP_CONNECTION pConn    = NULL;

	DEBUGMSG(ZONE_FUNCTION,
        (TEXT("+IRLMP_CloseAddress(0x%X)\r\n"), pTDIReq));

    pAddrObj = GETADDR(pTDIReq->Handle.AddressHandle);

    if (pAddrObj == NULL)
    {
        DEBUGMSG(ZONE_WARN, (TEXT("+IRLMP_CloseAddress(0x%X) hAddr = 0x%X not found!\r\n"),
                    pTDIReq, pTDIReq->Handle.AddressHandle));

        TdiStatus = TDI_ADDR_INVALID;
        goto done;
    }

    VALIDADDR(pAddrObj);

    DUMP_OBJECTS(ZONE_TDI || ZONE_ALLOC);

    // SH - It is possible that we have connection objects which are not
    //      disassociated. Cleanup appropriately.
    DEBUGMSG(ZONE_ERROR && (IsListEmpty(&pAddrObj->ConnList) == FALSE), 
        (TEXT("IRLMP_CloseAddress WARNING: Connections not disassociated.\r\n")));

    EnterCriticalSection(&csIrObjList);

    while (IsListEmpty(&pAddrObj->ConnList) == FALSE)
    {
        pConn = (PIRLMP_CONNECTION)pAddrObj->ConnList.Flink;

        // Assume that we don't have any real clean up to do. Just disassociate.
        ASSERT(pConn->ConnState != IRLMP_CONN_OPEN);
        ASSERT(pConn->pUsrNDISBuff == NULL);
        ASSERT(IsListEmpty(&pConn->RecvBuffList) == TRUE);

        TdiStatus = TdiDisassociateAddress(pConn);
        ASSERT(TdiStatus == TDI_SUCCESS);
    }
    
    LeaveCriticalSection(&csIrObjList);

    if (pAddrObj->IsServer == TRUE)
    {
        IRDA_MSG IMsg;
        int      rc;

        IMsg.Prim                  = IRLMP_DEREGISTERLSAP_REQ;
        IMsg.IRDA_MSG_LocalLsapSel = pAddrObj->LSAPSelLocal;
        rc = IrlmpDown(NULL, &IMsg);
        ASSERT(rc == 0);

        IMsg.Prim                  = IRLMP_DELATTRIBUTE_REQ;
        IMsg.IRDA_MSG_AttribHandle = pAddrObj->IasAttribHandle;
        rc = IrlmpDown(NULL, &IMsg);
        ASSERT(rc == 0);
    }

    // One for reference in this function and one since AFD is giving up
    // it's reference.
    REFDELADDR(pAddrObj);
    REFDELADDR(pAddrObj);

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


#ifdef DEBUG
    static DWORD dwConnId = 1;
#endif 

/*****************************************************************************
*
*   @func   TDI_STATUS  |   IRLMP_OpenConnection    |
*           Called after connect() and backlog times after listen(). Allocates 
*           a new IRLMP_CONNECTION.
*
*	@rdesc
*           TDI_SUCCESS (tdistat.h) on success, or (tdistat.h)
*   @errors
*           @ecode  TDI_NO_RESOURCES    |   No memory.
*
*   @parm   PTDI_REQUEST        |   pTDIReq     |
*           (tdi.h) pTDIReq->Handle.ConnectionContext returns the address of
*           the new IRLMP_CONNECTION.
*   @parm   PVOID               |   pContext    |
*           IrLMP saves this in the IRLMP_CONNECTION.
*/

TDI_STATUS          
IRLMP_OpenConnection(PTDI_REQUEST pTDIReq,
                     PVOID        pContext)
{
    PIRLMP_CONNECTION pNewConn;
    TDI_STATUS        TdiStatus = TDI_SUCCESS;

	DEBUGMSG(ZONE_FUNCTION,
        (TEXT("+IRLMP_OpenConnection(0x%X,0x%X)\r\n"),
         pTDIReq, pContext));

    pNewConn = IrdaAlloc(sizeof(IRLMP_CONNECTION), MT_TDI_CONNECTION);

	if (pNewConn == NULL)
    {
        TdiStatus = TDI_NO_RESOURCES;
        goto done;
    }

    pNewConn->cRefs = 1;
#ifdef DEBUG
    pNewConn->Sig  = TDICONNSIG;
    pNewConn->dwId = dwConnId++;
#endif // DEBUG

    DEBUGMSG(ZONE_ALLOC, (TEXT("IrDA: Allocate Connection - %#x (%d)\r\n"), pNewConn, pNewConn->dwId));
    pNewConn->ConnState               = IRLMP_CONN_CREATED;
    pNewConn->fConnPending            = FALSE;
    pNewConn->pConnectionContext      = pContext;
    pNewConn->TdiStatus               = TDI_SUCCESS;
    InitializeListHead(&pNewConn->RecvBuffList);
    CTEInitLock(&pNewConn->Lock);

    // Put connection on unassociated connection list.
    EnterCriticalSection(&csIrObjList);
    InsertHeadList(&IrConnObjList, (PLIST_ENTRY)pNewConn);
    // For now the handle is just the pointer.
    pTDIReq->Handle.ConnectionContext =(HANDLE)pNewConn;
    LeaveCriticalSection(&csIrObjList);

    // Keep our ref since we are passing it off to AFD. We will remove this
    // ref in IRLMP_CloseConnection.

done:
    DEBUGMSG(ZONE_FUNCTION,
        (TEXT("-IRLMP_OpenConnection [Status: %#x; hConn = %#x;")
         TEXT(" pConn = %#x, id = %d]\r\n"),
         TdiStatus, pTDIReq->Handle.ConnectionContext, 
         pNewConn, (NULL == pNewConn) ? 0 : pNewConn->dwId));

    return (TdiStatus);
}

void TdiCleanupConnection(PIRLMP_CONNECTION pConn);


/*****************************************************************************
*
*   @func   TDI_STATUS  |   IRLMP_CloseConnection   |
*           Called at socket close time. If the connection is in a conencted
*           state, this call implies an abortive close - close the IRLMP
*           connection and free the IRDA_CONNECTION. If the connection is
*           not in the connected state, the IRLMP_DIsconnect() handler has
*           been called and only the IRLMP_CONNECTION will be freed.
*
*	@rdesc
*           TDI_SUCCESS (tdistat.h) on success, or (tdistat.h)
*   @errors
*           @ecode  TDI_INVALID_CONNECTION          |   Bad 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.
*/

TDI_STATUS 
IRLMP_CloseConnection(PTDI_REQUEST pTDIReq)
{
    TDI_STATUS         TdiStatus = TDI_SUCCESS;
    PIRLMP_CONNECTION  pConn;
    IRDA_MSG           IrDAMsg;
    int                rc;

    pConn = GETCONN(pTDIReq->Handle.ConnectionContext);
    if (pConn == NULL)
    {
        DEBUGMSG(ZONE_WARN, (TEXT("IRLMP_CloseConnection(%#x) hConn = %#x, pConn = NULL!!!\r\n"), 
             pTDIReq, pTDIReq->Handle.ConnectionContext));
        DUMP_OBJECTS(ZONE_TDI || ZONE_ALLOC);
        return TdiStatus;
    }

    VALIDCONN(pConn);

    GET_CONN_LOCK(pConn);

	DEBUGMSG(ZONE_FUNCTION,
        (TEXT("+IRLMP_CloseConnection(%#x) hConn = %#x, pConn = %#x, id = %d\r\n"), 
         pTDIReq, pTDIReq->Handle.ConnectionContext, pConn, pConn->dwId));

    // Disconnect if required.
    if (pConn->ConnState == IRLMP_CONN_OPEN)
    {
        IrDAMsg.Prim                 = IRLMP_DISCONNECT_REQ;
        IrDAMsg.IRDA_MSG_pDiscData   = NULL;
        IrDAMsg.IRDA_MSG_DiscDataLen = 0;

        // Set state to closing.
        pConn->ConnState = IRLMP_CONN_CLOSING;
        IrdaAutoSuspend(FALSE);    // one less active connection
		
        rc = IrlmpDown(pConn->pIrLMPContext, &IrDAMsg);
        ASSERT(rc == 0);
    } else {
        DEBUGMSG(ZONE_WARN, (TEXT("IRLMP_CloseConnection() state = %d\r\n"), pConn->ConnState));
		// Set state to closing.
		pConn->ConnState = IRLMP_CONN_CLOSING;
	}


    TdiCleanupConnection(pConn);
    
	DEBUGMSG(ZONE_FUNCTION, (TEXT("-IRLMP_CloseConnection(%#x)\r\n"), pTDIReq));
    
    DUMP_OBJECTS(ZONE_TDI || ZONE_ALLOC);
	
    return(TdiStatus);
}

//
// Common worker used by both IRLMP_CloseConnection and IRLMP_Disconnect
//
void
TdiCleanupConnection(
    PIRLMP_CONNECTION pConn
    )
{
    TDI_STATUS         TdiStatus = TDI_SUCCESS;
    PIRDATDI_RECV_BUFF pRecvBuff;
    BOOL               fIndicateRecv = FALSE;

    //
    // Disassociate since our AFD does not call TdiDisassociateEntry.
    //

    // If the connect fails before AssociateAddress is called, it won't have
    // a pointer to an address object to disassociate.
    if (pConn->pAddrObj)
    {
        TdiStatus = TdiDisassociateAddress(pConn);
        ASSERT(TdiStatus == TDI_SUCCESS);
    }

    // Free memory.
    while (!IsListEmpty(&pConn->RecvBuffList))
    {
        pRecvBuff = (PIRDATDI_RECV_BUFF) 
                    RemoveTailList(&pConn->RecvBuffList);

        IrdaFree(pRecvBuff);
    }

    if (pConn->pUsrNDISBuff)
    {
        pConn->pUsrNDISBuff = NULL;
        pConn->UsrBuffLen   = 0;
        fIndicateRecv       = TRUE;
    }

    FREE_CONN_LOCK(pConn);

    if (fIndicateRecv == TRUE)
    {
        pConn->pRecvComplete(
            pConn->pRecvCompleteContext,
            TDI_SUCCESS,
            0);
    }

    // One for reference in this function and one since AFD is giving up
    // it's reference.
    REFDELCONN(pConn);
    REFDELCONN(pConn);    
}   // TdiCleanupConnection

/*****************************************************************************
*
*   @func   TDI_STATUS  |   IRLMP_AssociateAddress  |
*           Called after connect() and backlog times after listen(). 
*           Assigns pAddrObj in a newly created IRLMP_CONNECTION to point
*           to an IRLMP_ADDR_OBJ and adds the IRLMP_CONNECTION to pConnList
*           anchored on IRLMP_ADDR_OBJ. SockAddrLocal is copied from the
*           the IRLMP_ADDR_OBJ to the IRLMP_CONNECTION to handle the the
*           IsConn option of IRLMP_QueryInformation().
*
*	@rdesc
*           TDI_SUCCESS (tdistat.h) on success, or (tdistat.h)
*   @errors
*           @ecode TDI_ALREADY_ASSOCIATED   |   pAddrObj != NULL.
*
*   @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.
*   @parm   HANDLE          |   AddrHandle  |
*           Handle to the IRLMP_ADDR_OBJ. IRLMP_OpenAddress() assigns this
*           value to be a pointer to the IRLMP_ADDR_OBJ.
*
*   @xref   <f IRLMP_OpenAddress>   <f IRLMP_OpenConnection>
*           <f IRLMP_QueryInformation>
*/

TDI_STATUS
IRLMP_AssociateAddress(PTDI_REQUEST pTDIReq,
                       HANDLE       AddrHandle)
{
    TDI_STATUS        TdiStatus = TDI_SUCCESS;
    PIRLMP_CONNECTION pConn;
    PIRLMP_ADDR_OBJ   pAddrObj;

	DEBUGMSG(ZONE_FUNCTION,
        (TEXT("+IRLMP_AssociateAddress(0x%X,0x%X)\r\n"), 
         pTDIReq, (unsigned) AddrHandle));

    pConn    = GETCONN(pTDIReq->Handle.ConnectionContext);
    pAddrObj = GETADDR(AddrHandle);

⌨️ 快捷键说明

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