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