📄 tdiup.c
字号:
// out in the world.
DEBUGMSG (ZONE_WARN, (TEXT("Got IRLAP_DISC in SharpMode\r\n")));
TdiStatus = TDI_DISCONNECT_WAIT;
break;
}
// Else fall into following
case IRLMP_IRLAP_RESET:
case IRLMP_IRLAP_CONN_FAILED:
case IRLMP_UNSPECIFIED_DISC:
TdiStatus = TDI_DISCONNECT_ABORT;
break;
default:
TdiStatus = TDI_DISCONNECT_ABORT;
break;
}
if (TdiStatus == TDI_DISCONNECT_WAIT)
{
DEBUGMSG(ZONE_WARN, (TEXT("IrlmpDisconnectInd - Starting linger timer.\r\n")));
pConn->TdiStatus = TdiStatus;
pConn->LastSendsRemaining = pConn->SendsRemaining;
pConn->LingerTime = 10000;
CTEStopTimer(&pConn->LingerTimer);
CTEInitTimer(&pConn->LingerTimer);
CTEStartTimer(&pConn->LingerTimer, 1000, LingerTimerFunc, pConn);
FREE_CONN_LOCK(pConn);
}
else
{
BOOL fIndicateRecv = FALSE;
pConn->ConnState = IRLMP_CONN_CLOSING;
if (pConn->pUsrNDISBuff)
{
pConn->pUsrNDISBuff = NULL;
pConn->UsrBuffLen = 0;
fIndicateRecv = TRUE;
}
FREE_CONN_LOCK(pConn);
IrdaAutoSuspend(FALSE); // one less active connection
if (fIndicateRecv == TRUE &&
TdiStatus != TDI_DISCONNECT_ABORT)
{
pConn->pRecvComplete(
pConn->pRecvCompleteContext,
TDI_SUCCESS,
0);
}
if (pConn->pAddrObj->pEventDisconnect(
pConn->pAddrObj->pEventDisconnectContext,
pConn->pConnectionContext, 0, NULL, 0, NULL,
TdiStatus) != STATUS_SUCCESS)
{
DEBUGMSG(ZONE_ERROR, (TEXT("TdiUp() EventDisconnect() failed\r\n")));
}
if (fIndicateRecv == TRUE &&
TdiStatus == TDI_DISCONNECT_ABORT)
{
pConn->pRecvComplete(
pConn->pRecvCompleteContext,
TDI_CONNECTION_RESET,
0);
}
}
}
else
{
FREE_CONN_LOCK(pConn);
DEBUGMSG(ZONE_WARN, (TEXT("TdiUp() IRLMP_DISC_IND ignored\r\n")));
}
REFDELCONN(pConn);
DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: -IRLMP_DISCONNECT_IND\r\n")));
return;
}
UINT ConnConfDiscReq(void *pIrlmpContext)
{
// Disconnect because either the connection context has gone away,
// or is about to go away (IRLMP_CONN_CLOSING).
IRDA_MSG IMsg;
UINT rc;
DEBUGMSG(ZONE_WARN,
(TEXT("ConnConfDiscReq - invalid connection handle or closing.\r\n")));
IMsg.Prim = IRLMP_DISCONNECT_REQ;
IMsg.IRDA_MSG_pDiscData = NULL;
IMsg.IRDA_MSG_DiscDataLen = 0;
rc = IrlmpDown(pIrlmpContext, &IMsg);
return (rc);
}
/*++
Function: IrlmpConnectConf
Description: Processes an IRLMP_CONNECT_CONF.
Comments:
--*/
VOID
IrlmpConnectConf(void *pConnContext, IRDA_MSG *pIrDAMsg)
{
int rc;
IRDA_MSG IrDAMsg;
PIRLMP_CONNECTION pConn;
DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: +IRLMP_CONNECT_CONF\r\n")));
pConn = GETCONN(pConnContext);
if (pConn == NULL)
{
// If we get a close while trying to connect, our connection
// object.
// We don't expect to get here, because we will keep an extra
// ref on the connection if a connection is pending.
// Normally we don't keep an extra ref on pending requests, but
// we need to be able to do a connect complete to AFD, other
// wise, AFD blocks....
DEBUGMSG(ZONE_WARN,
(TEXT("IrlmpConnectConf - connection gone.\r\n")));
rc = ConnConfDiscReq(pIrDAMsg->IRDA_MSG_pContext);
ASSERT(rc == 0);
goto done;
}
VALIDCONN(pConn);
GET_CONN_LOCK(pConn);
if (pConn->ConnState == IRLMP_CONN_OPENING)
{
pConn->pIrLMPContext = pIrDAMsg->IRDA_MSG_pContext;
pConn->SendMaxSDU = pIrDAMsg->IRDA_MSG_MaxSDUSize;
pConn->SendMaxPDU = pIrDAMsg->IRDA_MSG_MaxPDUSize;
if (pConn->UseExclusiveMode || pConn->UseIrLPTMode)
{
IrDAMsg.Prim = IRLMP_ACCESSMODE_REQ;
IrDAMsg.IRDA_MSG_AccessMode = IRLMP_EXCLUSIVE;
IrDAMsg.IRDA_MSG_IrLPTMode = pConn->UseIrLPTMode;
FREE_CONN_LOCK(pConn);
if ((rc = IrlmpDown(pConn->pIrLMPContext, &IrDAMsg)) != 0)
{
pConn->fConnPending = FALSE;
if (pConn->pConnectCompleteContext) {
if (rc == IRLMP_IN_MULTIPLEXED_MODE)
{
pConn->pConnectComplete(
pConn->pConnectCompleteContext,
TDI_LINK_BUSY,
0);
}
else if (rc == IRLMP_IN_EXCLUSIVE_MODE)
{
pConn->pConnectComplete(
pConn->pConnectCompleteContext,
TDI_SUCCESS,
0);
}
else
{
ASSERT(0);
}
}
// IRLMP_Connect left us an extra ref to take care of.
REFDELCONN(pConn);
}
// If the ACCESSMODE_REQ returned success -- really pending. Keep
// our extra reference.
}
else
{
pConn->ConnState = IRLMP_CONN_OPEN;
pConn->fConnPending = FALSE;
FREE_CONN_LOCK(pConn);
if (pConn->pConnectCompleteContext) {
IrdaAutoSuspend(TRUE); // new active connection
pConn->pConnectComplete(pConn->pConnectCompleteContext,
TDI_SUCCESS, 0);
}
// IRLMP_Connect left us an extra ref to take care of.
REFDELCONN(pConn);
}
}
else
{
// ConnState = IRLMP_CONN_CLOSING, IRLMP_CONN_CREATED, IRLMP_CONN_OPEN
ASSERT(pConn->ConnState == IRLMP_CONN_CLOSING);
FREE_CONN_LOCK(pConn);
DEBUGMSG(ZONE_WARN,
(TEXT("IrlmpConnectConf - connection closing.\r\n")));
rc = ConnConfDiscReq(pIrDAMsg->IRDA_MSG_pContext);
ASSERT(rc == 0);
if (pConn->pConnectCompleteContext) {
pConn->pConnectComplete(
pConn->pConnectCompleteContext,
TDI_CONNECTION_ABORTED,
0);
}
// IRLMP_Connect left us an extra ref to take care of.
REFDELCONN(pConn);
}
REFDELCONN(pConn);
done:
DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: -IRLMP_CONNECT_CONF\r\n")));
return;
}
/*++
Function: IrlmpGetValueByClassConf
Description: Process an IRLMP_GETVALUEBYCLASS_CONF.
Arguments:
--*/
__inline VOID
IrlmpGetValueByClassConf(IRDA_MSG *pIrDAMsg)
{
DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: +IRLMP_GETVALUEBYCLASS_CONF\r\n")));
EnterCriticalSection(&csIasQuery);
IASQueryStatus = pIrDAMsg->IRDA_MSG_IASStatus;
SetEvent(IASQueryConfEvent);
LeaveCriticalSection(&csIasQuery);
DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: -IRLMP_GETVALUEBYCLASS_CONF\r\n")));
return;
}
/*++
Function: IrlmpDataConf
Description: Process an IRLMP_DATA_CONF.
Comments:
--*/
VOID
IrlmpDataConf(void *pConnContext, IRDA_MSG *pIrDAMsg)
{
PIRLMP_CONNECTION pConn;
DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: +IRLMP_DATA_CONF\r\n")));
if (pIrDAMsg->IRDA_MSG_DataStatus == IRLMP_DATA_REQUEST_COMPLETED)
{
((PIRLMP_SEND_COMPLETE) pIrDAMsg->IRDA_MSG_pTdiSendComp)(
pIrDAMsg->IRDA_MSG_pTdiSendCompCnxt,
TDI_SUCCESS,
pIrDAMsg->IRDA_MSG_SendLen);
pConn = GETCONN(pConnContext);
if (pConn)
{
VALIDCONN(pConn);
GET_CONN_LOCK(pConn);
if (pConn->SendsRemaining) {
pConn->SendsRemaining--;
}
FREE_CONN_LOCK(pConn);
REFDELCONN(pConn);
}
}
else
{
((PIRLMP_SEND_COMPLETE) pIrDAMsg->IRDA_MSG_pTdiSendComp)(
pIrDAMsg->IRDA_MSG_pTdiSendCompCnxt,
TDI_GRACEFUL_DISC,
0);
}
IrdaFree(pIrDAMsg);
DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: -IRLMP_DATA_CONF\r\n")));
return;
}
/*++
Function: BufferRecv
Description:
Arguments:
Returns:
Comments:
--*/
BOOL
BufferRecv(
PIRLMP_CONNECTION pConn,
PUCHAR pData,
DWORD cbData,
BYTE bFinalSeg
)
{
PIRDATDI_RECV_BUFF pRecvBuf;
pRecvBuf = IrdaAlloc(
(offsetof(IRDATDI_RECV_BUFF, Data) + cbData),
MT_TDI_RECV_BUFF);
if (pRecvBuf == NULL)
{
ASSERT(0);
return (FALSE);
}
pConn->RecvQBytes += cbData;
pRecvBuf->DataLen = cbData;
pRecvBuf->pRead = &pRecvBuf->Data[0];
pRecvBuf->FinalSeg = bFinalSeg;
memcpy(pRecvBuf->pRead, pData, cbData);
InsertHeadList(&pConn->RecvBuffList, &pRecvBuf->Linkage);
return (TRUE);
}
/*++
Function: IrlmpDataInd
Description: Process an IRLMP_DATA_IND.
Comments:
--*/
VOID IrlmpDataInd(void *pConnContext, IRDA_MSG *pIrDAMsg)
{
IRDA_MSG IrDAMsg;
TDI_STATUS TdiStatus;
int rc;
DWORD OldPermissions;
// IRLMP_DATA_IND
EventRcvBuffer EventRecvCompleteInfo;
int BytesTaken;
PIRLMP_CONNECTION pConn;
int cbCopyToNdisBuf;
int cbCopyToRecvBuf;
PNDIS_BUFFER pNdisBuf;
BOOL fEventReceive;
BYTE FinalSeg;
DEBUGMSG(ZONE_TDI, (TEXT("TdiUp: +IRLMP_DATA_IND\r\n")));
pConn = GETCONN(pConnContext);
if (pConn == NULL)
{
DEBUGMSG(ZONE_WARN,
(TEXT("IrlmpDataInd - invalid connection handle.\r\n")));
goto done;
}
VALIDCONN(pConn);
GET_CONN_LOCK(pConn);
if (pConn->ConnState != IRLMP_CONN_OPEN)
{
DEBUGMSG(ZONE_WARN, (TEXT("TdiUp() IRLMP_DATA_IND ignored\r\n")));
// wmz open the window?
goto done;
}
pConn->TinyTPRecvCreditsLeft--;
//
// Is this an IrCOMM connection?
//
if (pConn->Use9WireMode)
{
//
// When a packet arrives that has both contrl parameters and data, the
// control data will be acted up first, then the data will be
// processed. In this case, all processing for control parameters is to
// ignore (discard). The first byte in an IrCOMM frame is the byte count
// of the control parameters.
//
BYTE cbControlPacket = *(BYTE *)pIrDAMsg->IRDA_MSG_pRead;
// Increment past the byte count.
pIrDAMsg->IRDA_MSG_pRead++;
DEBUGMSG(ZONE_TDI,
(TEXT("IrlmpDataInd: IrCOMM frame - ControlParm Len = %d/%d\r\n"),
cbControlPacket,
pIrDAMsg->IRDA_MSG_pWrite - pIrDAMsg->IRDA_MSG_pRead));
// Skip over any control parameters in the packet
pIrDAMsg->IRDA_MSG_pRead += cbControlPacket;
// Make sure that we didn't advance beyond the end of the buffer.
// If so, the peer is violating the protocol.
if (pIrDAMsg->IRDA_MSG_pRead > pIrDAMsg->IRDA_MSG_pWrite)
DEBUGMSG(ZONE_ERROR,
(TEXT("IrlmpDataInd: Invalid IrCOMM frame - ControlParm Len = %d too large\r\n"),
cbControlPacket));
// If there is no data (i.e. there was only control parameters, then
// skip the data ind path.
if (pIrDAMsg->IRDA_MSG_pRead >= pIrDAMsg->IRDA_MSG_pWrite)
{
goto IgnoreIRLMP_DATA_IND;
}
}
//
// Four main cases to deal with:
// 1) Copy all data to pending NDIS buffer. Call CompleteReceive.
// 2) No pending NDIS buffer. Other data has already been indicated
// but not accepted.
//
// The above two cases are easy, grab the locks copy the data, get out.
//
// 3) Copy some data (as much as possible) to pending NDIS buffer.
// Call CompleteReceive. Call IndicateReceive for remaining bytes and Q
// the remaining bytes.
// 4) Need to indicate all the data. Call IndicateReceive and Q bytes.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -