📄 irdatdi.c
字号:
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 + -