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

📄 irdatdi.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 5 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*****************************************************************************
*
* 
*
*       @doc
*       @module irdatdi.c | IrDA stack interface to TDI
*
*               11/11/1997
*               - Modified for new irdastk. New locking stategy. 
*                         Everything else is same.
*
*               3/16/1998
*               - Modified to used handles instead of pointers with
*                         AFD (AFD can call in to close connections at any
*                         time. We need to make sure that we ref count and
*                         not to delete any connection objects in use.)
*
*       see AFD\peginit.c
*
*       Locking Strategy:
*           Lock TDI connection objects while using.
*           Lock TDI address objects while using.
*           (Lock connection objects before address objects).
*           Don't call into IrLMP with locks held.
*           IrLmp locks the LMP link control blocks.
*
*           There is a specific lock for discoveries.
*           There is a specific lock for IAS queries.
*           There is a specific lock for manipulating object lists.
*
*/

#include "irdatdi.h"

#ifdef DEBUG

TCHAR *szIrlmpConnState[] = {
    TEXT("CONN_CREATED"),
    TEXT("CONN_CLOSING"),
    TEXT("CONN_OPENING"),
    TEXT("CONN_OPEN")
};

#define DUMP_RECVLIST(debugzone, pConn) if (debugzone) DumpRecvList(pConn)

void
DumpRecvList(PIRLMP_CONNECTION pConn)
{
    PIRDATDI_RECV_BUFF pRecv;
    PLIST_ENTRY        pRecvEntry;

    if (IsListEmpty(&pConn->RecvBuffList) == TRUE)
    {
        DEBUGMSG(1, (TEXT("*** IrTdi: No recv buffers are queued.\r\n")));
        return;
    }

    DEBUGMSG(1, (TEXT("*** IrTdi: Queued recv buffers:\r\n")));
    
    for (pRecvEntry = pConn->RecvBuffList.Flink;
         pRecvEntry != &pConn->RecvBuffList;
         pRecvEntry = pRecvEntry->Flink)
    {
        pRecv = (PIRDATDI_RECV_BUFF)pRecvEntry;

        DEBUGMSG(1,
            (TEXT("    %d B [%#x] %s\r\n"),
             pRecv->DataLen,
             pRecv->pRead,
             pRecv->FinalSeg == TRUE ? TEXT("F") : TEXT("")));
    }

    return;
}

#define DUMP_OBJECTS(debugzone) if (debugzone) DumpObjects()

void
DumpObjects()
{
    PIRLMP_ADDR_OBJ   pAddr;
    PIRLMP_CONNECTION pConn;
    PLIST_ENTRY       pAddrEntry, pConnEntry;

    EnterCriticalSection(&csIrObjList);

    DEBUGMSG(1,
        (TEXT("*** Dump Address and Connection Objects: %s\r\n"),
         (!IsListEmpty(&IrAddrObjList) && !IsListEmpty(&IrConnObjList)) ? 
          TEXT("NO ADDR or CONN objects.") : TEXT("")));
    
    for (pAddrEntry = IrAddrObjList.Flink;
         pAddrEntry != &IrAddrObjList;
         pAddrEntry = pAddrEntry->Flink)
    {    
        pAddr = (PIRLMP_ADDR_OBJ)pAddrEntry;

        VALIDADDR(pAddr);
        if (pAddr) {
            GET_ADDR_LOCK(pAddr);

            DEBUGMSG(1,
                (TEXT("  AddrObj:%#x (%d) RefCnt: %d Loc:\"%hs\",%d Next:%#x\r\n"),
                 pAddr, pAddr->dwId, pAddr->cRefs,
                 pAddr->SockAddrLocal.irdaServiceName,
                 pAddr->LSAPSelLocal,
                 pAddrEntry->Flink != &IrAddrObjList ? pAddrEntry->Flink : NULL));

            for (pConnEntry = pAddr->ConnList.Flink;
                 pConnEntry != &pAddr->ConnList;
                 pConnEntry = pConnEntry->Flink)
            {
                pConn = (PIRLMP_CONNECTION)pConnEntry;
                VALIDCONN(pConn);

                DEBUGMSG(1,
                    (TEXT("    ConnObj:%#x (%d) Ref: %d Loc:\"%hs\",%d Rem:\"%hs\",%d ")
                     TEXT("State:%s (%d) AddrObj:%#x Next:%#x\r\n"),
                     pConn, pConn->dwId, pConn->cRefs,
                     pConn->SockAddrLocal.irdaServiceName,
                     pConn->LSAPSelLocal,
                     pConn->SockAddrRemote.irdaServiceName,
                     pConn->LSAPSelRemote,
                     szIrlmpConnState[pConn->ConnState], pConn->ConnState,
                     pConn->pAddrObj,
                     pConnEntry->Flink != &pAddr->ConnList ? pConnEntry->Flink : NULL));
            }

            FREE_ADDR_LOCK(pAddr);
        } else {
            ASSERT(0);  // list is corrupt
            break;
        }
    }
    
    if (!IsListEmpty(&IrConnObjList))
    {
        DEBUGMSG(1,
            (TEXT("  Unassociated Connection Objects:\r\n")));
        
        for (pConnEntry = IrConnObjList.Flink;
             pConnEntry != &IrConnObjList;
             pConnEntry = pConnEntry->Flink)
        {
            pConn = (PIRLMP_CONNECTION)pConnEntry;
            VALIDCONN(pConn);
            DEBUGMSG(1,
                (TEXT("    ConnObj:%#x (%d) Ref: %d Loc:\"%hs\",%d Rem:\"%hs\",%d ")
                 TEXT("State:%s (%d) AddrObj:%#x pNext:%#x\r\n"),
                 pConn, pConn->dwId, pConn->cRefs,
                 pConn->SockAddrLocal.irdaServiceName,
                 pConn->LSAPSelLocal,
                 pConn->SockAddrRemote.irdaServiceName,
                 pConn->LSAPSelRemote,
                 szIrlmpConnState[pConn->ConnState], pConn->ConnState,
                 pConn->pAddrObj,
                 pConnEntry->Flink != &IrConnObjList ? pConnEntry->Flink : NULL));
        }
    }

    LeaveCriticalSection(&csIrObjList);
    return;
}

#else
#define DUMP_OBJECTS(debugzone)             ((void)0)
#define DUMP_RECVLIST(debugzone, pConn)     ((void)0)
#endif

//
// For sockets which are not bound to a service name - we will assign a 
// hard coded LSAP-SEL. We will store this in the irdaServiceName of the
// sockaddr.
//

VOID
SetLsapSelAddr(
    int LsapSel,
    CHAR *ServiceName)
{
    int     Digit, i;
    int     StrLen = 0;
    CHAR    Str[4];

    while (LsapSel > 0 && StrLen < 3)
    {
        Digit = LsapSel % 10;
        LsapSel = LsapSel / 10;
        Str[StrLen] = Digit + '0';
        StrLen++;
    }

    RtlCopyMemory(ServiceName, LSAPSEL_TXT, LSAPSEL_TXTLEN);

    for (i = 0; i < StrLen; i++)
    {
       ServiceName[i + LSAPSEL_TXTLEN] = Str[StrLen - 1 - i];
    }

    ServiceName[StrLen + LSAPSEL_TXTLEN] = 0;
}

#define IRDA_MIN_LSAP_SEL 1
#define IRDA_MAX_LSAP_SEL 127

int
ParseLsapSel(CHAR *pszDigits)
{
    int LsapSel = 0;
    int i;

    for (i = 0; i < 3; i++)
    {
        if (pszDigits[i] == 0)
            break;

        // Only real digits are valid.
        if ((pszDigits[i] < '0') || (pszDigits[i] > '9'))
            return (-1);

        // Calculate LSAP-SEL.
        LsapSel = (LsapSel * 10) + (pszDigits[i] - '0');
    }

    // Greater than 4 characters, < 1, > 127 are all invalid LSAP-SELs.
    if ((pszDigits[i] != 0) || 
        (LsapSel < IRDA_MIN_LSAP_SEL) || 
        (LsapSel > IRDA_MAX_LSAP_SEL))
    {
        return (-1);
    }

    return (LsapSel);
}

__inline BOOL 
IsLsapSelUsed(int LsapSel)
{
    PLIST_ENTRY pAddrEntry;

    // Assumes AddrObjList lock is held.

    // sh - We have hardcoded our IAS Lsap Sel as 3. Therefore, don't let 'em
    //      use it.
    if (LsapSel == 3 /*IAS_LOCAL_LSAP_SEL*/)
    {
        return (TRUE);
    }

    for (pAddrEntry = IrAddrObjList.Flink; 
         pAddrEntry != &IrAddrObjList; 
         pAddrEntry = pAddrEntry->Flink)
    {
        if (((PIRLMP_ADDR_OBJ)pAddrEntry)->LSAPSelLocal == LsapSel)
        {
            return (TRUE);
        }
    }
    return (FALSE);
}

int
GetUnusedLsapSel()
{
    int LsapSel;
    
    // Assumes AddrObjList lock is held.
    
    for (LsapSel = IRDA_MIN_LSAP_SEL; LsapSel <= IRDA_MAX_LSAP_SEL; LsapSel++)
    {
        if (IsLsapSelUsed(LsapSel) == FALSE)
        {
            return (LsapSel);
        }
    }
    return -1;
}    

/*****************************************************************************
*
*   @func   TDI_STATUS  |   IRLMP_OpenAddress   |
*           Called after bind(). Allocates a new IRLMP_ADDR_OBJ.
*
*	@rdesc
*           TDI_SUCCESS (tdistat.h) on success, or (tdistat.h)
*   @errors
*           @ecode  TDI_ADDR_IN_USE     |   Address is in use.
*           @ecode  TDI_BAD_ADDR        |   Address is bad.
*           @ecode  TDI_NO_FREE_ADDR    |   Address space is full.
*           @ecode  TDI_NO_RESOURCES    |   No memory.
*
*   @parm   PTDI_REQUEST        |   pTDIReq     |
*           (tdi.h) The address of the new IRLMP_ADDR_OBJ is returned in
*           pTDIReq->Handle.AddressHandle.
*   @parm   PTRANSPORT_ADDRESS  |   pAddr       |
*           Pointer to input TRANSPORT_ADDRESS (tdi.h) struct. IrLMP assumes
*           one TA_ADDRESS entry with the Address field containing the 
*           remaining bytes of a SOCKADDR_IRDA struct minus the first two
*           bytes.
*   @parm   uint                |   Protocol    |
*           (TBD, see tcp.h, udp.h> IrLMP will save this value in the new
*           IRLMP_ADDR_OBJ.
*   @parm   PVOID               |   pOptions    |
*           Pointer to options. IrLMP will ignore this value.
*/

TDI_STATUS
IRLMP_OpenAddress(PTDI_REQUEST       pTDIReq,
                  PTRANSPORT_ADDRESS pAddr,
                  uint               Protocol,
                  PVOID              pOptions)
{
    TDI_STATUS      TdiStatus = TDI_SUCCESS;
    PIRLMP_ADDR_OBJ	pNewAddrObj, pAddrObj;
    int             LsapSel;
    PSOCKADDR_IRDA  pIrdaAddr;
    PLIST_ENTRY     pAddrEntry;

    DEBUGMSG(ZONE_FUNCTION,
        (TEXT("+IRLMP_OpenAddress(0x%X,0x%X,0x%X,0x%X)\r\n"), 
         pTDIReq, pAddr, Protocol, pOptions));

    pNewAddrObj = NULL;
    EnterCriticalSection(&csIrObjList);

    // Service name supplied. Ensure that an address object with same
    // name does not exist.
    pIrdaAddr = (PSOCKADDR_IRDA)&pAddr->Address[0].AddressType;

    if (pIrdaAddr->irdaServiceName[0] != 0)
    {
        // Truncate at 24 chars. Doc'd as a NULL terminated string in a 25
        // char buffer. Truncate without error.
        pIrdaAddr->irdaServiceName[24] = 0;

        for (pAddrEntry = IrAddrObjList.Flink;
             pAddrEntry != &IrAddrObjList;
             pAddrEntry = pAddrEntry->Flink)
        {
            pAddrObj = (PIRLMP_ADDR_OBJ)pAddrEntry;
            if (strcmp(pIrdaAddr->irdaServiceName,
                       pAddrObj->SockAddrLocal.irdaServiceName) == 0)
            {
                DEBUGMSG(ZONE_WARN,
                    (TEXT("IRLMP_OpenAddress, dup irdaServiceName\r\n")));
                
                TdiStatus = TDI_ADDR_IN_USE;
                goto ExitIRLMP_OpenAddress;
            }
        }
    }

	if (!memcmp (pIrdaAddr->irdaServiceName, LSAPSEL_TXT, LSAPSEL_TXTLEN)) 
    {
		DEBUGMSG(ZONE_WARN, 
            (TEXT("IRLMP_OpenAddress: Hard coded LSAP '%hs' requested.\r\n"),
             pIrdaAddr->irdaServiceName));

        LsapSel = ParseLsapSel(
            &pIrdaAddr->irdaServiceName[LSAPSEL_TXTLEN]);

        if (LsapSel == -1)
        {
            TdiStatus = TDI_ADDR_INVALID;
            goto ExitIRLMP_OpenAddress;
        }

        DEBUGMSG(ZONE_WARN, 
            (TEXT("IRLMP_OpenAddress: Have hardcoded LSAP %d(0x%X)\r\n"),
             LsapSel, LsapSel));

        // Ensure that our LSAP does not collide.
        if (IsLsapSelUsed(LsapSel) == TRUE)
        {
            DEBUGMSG(ZONE_WARN,
                (TEXT("IRLMP_OpenAddress: Can't give hardcoded LSAP %d -- in use!\r\n"),
                 LsapSel));
            TdiStatus = TDI_ADDR_IN_USE;
            goto ExitIRLMP_OpenAddress;
        }
	}
    else
    {
        // Get an unused LSAP-SEL for this socket address object.
        LsapSel = GetUnusedLsapSel();

        if (LsapSel == -1)
        {
            TdiStatus = TDI_NO_FREE_ADDR;
            goto ExitIRLMP_OpenAddress;
        }
    }

	pNewAddrObj = ALLOCADDR(&pTDIReq->Handle.AddressHandle);

    if (pNewAddrObj == NULL)
    {
        DEBUGMSG(ZONE_ERROR,
            (TEXT("IRLMP_OpenAddress() CTEAllocMem() failed\r\n")));

        TdiStatus = TDI_NO_RESOURCES;

⌨️ 快捷键说明

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