📄 tdi.cxx
字号:
pC->eStage = CLOSED;
else
pC->eStage = OPENED;
PBT_CONNECT_COMPLETE pConnectCompleteEvent = pC->pConnectCompleteEvent;
void *pConnectCompleteContext = pC->pConnectCompleteContext;
pC->pConnectCompleteContext = NULL;
pC->pConnectCompleteEvent = NULL;
SVSUTIL_ASSERT (pConnectCompleteEvent);
gpTDIR->AddRef ();
gpTDIR->Unlock ();
pConnectCompleteEvent (pConnectCompleteContext, iError, 0);
gpTDIR->Lock ();
gpTDIR->DelRef ();
}
static int SignalConnectionLoss (RFCOMM_CONNECTION_OBJECT *pC, TDI_STATUS fHow, BOOL fImmediateCleanup) {
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"SignalConnectionLoss : closing connection 0x%08x to %04x%08x 0x%02x\n", pC, GET_NAP(pC->BTAddr.btAddr), GET_SAP(pC->BTAddr.btAddr), pC->BTAddr.port));
CONNECT_STAGE eStage = pC->eStage;
pC->eStage = CLOSED;
while (pC->pPacketList) {
RFCOMM_PACKET_OBJECT *pNext = pC->pPacketList->pNext;
delete pC->pPacketList;
pC->pPacketList = pNext;
}
int iRes = TDI_SUCCESS;
if (pC->pConnectCompleteEvent && (! pC->fNoDisconnect)) {
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"SignalConnectionLoss : signalling connection abort to complete event\n"));
SignalConnectionCompleteUp (pC, TDI_CONNECTION_ABORTED);
pC = GetConnectionObject ((HANDLE)pC);
}
if ((! fImmediateCleanup) && (eStage == OPENED) && pC && pC->pRecvList && pC->pRecvList->pBuffer) {
// there's still data to recv(), and we want to leave it around.
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"SignalConnectionLoss : waiting to flush the recv list...\n"));
pC->fCloseHaveRecv = TRUE;
} else if (pC && ((eStage == OPENED) || fImmediateCleanup || (pC->fCloseHaveRecv && (! (pC->pRecvList && pC->pRecvList->pBuffer))))) {
pC->fCloseHaveRecv = FALSE;
while (pC && pC->pRecvList) {
RFCOMM_RECEIVE_OBJECT *pThis = pC->pRecvList;
pC->pRecvList = pC->pRecvList->pNext;
if (pThis->pBuffer && pThis->pBuffer->pFree)
pThis->pBuffer->pFree (pThis->pBuffer);
NDIS_BUFFER *pNdisBuffer = pThis->pNdisBuffer;
PBT_RECV_COMPLETE pCallback = pThis->pRecvEvent;
void *pContext = pThis->pRecvContext;
int iReceived = pThis->iNdisUsed;
delete pThis;
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"SignalConnectionLoss : cleaning up ndis buffer 0x%08x context 0x%08x, received %d\n", pNdisBuffer, pContext, iReceived));
if (pNdisBuffer) {
gpTDIR->AddRef ();
gpTDIR->Unlock ();
pCallback (pContext, fHow, iReceived);
gpTDIR->Lock ();
gpTDIR->DelRef ();
}
pC = GetConnectionObject ((HANDLE)pC);
}
while (pC && pC->pSendList) {
RFCOMM_SEND_OBJECT *pNext = pC->pSendList->pNext;
PBT_SEND_COMPLETE pCallback = pC->pSendList->pSendCallback;
void *pCallbackContext = pC->pSendList->pSendContext;
int cBytesSent = pC->pSendList->cBytesUsed;
delete pC->pSendList;
pC->pSendList = pNext;
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"SignalConnectionLoss : cleaning up send list context 0x%08x, sent %d\n", pCallbackContext, cBytesSent));
gpTDIR->AddRef ();
gpTDIR->Unlock ();
pCallback (pCallbackContext, TDI_CONNECTION_ABORTED, cBytesSent);
gpTDIR->Lock ();
gpTDIR->DelRef ();
pC = GetConnectionObject ((HANDLE)pC);
}
if (pC && pC->pAddr && pC->pAddr->pEventDisconnect) {
PDisconnectEvent pEventDisconnect = pC->pAddr->pEventDisconnect;
void *pEventContext = pC->pAddr->pEventDisconnectContext;
void *pConnectionContext = pC->pConnectionContext;
IFDBG(DebugOut (DEBUG_TDI_PACKETS, L"SignalConnectionLoss : forwarding up disconnection event conn 0x%08x\n", pC));
gpTDIR->AddRef ();
gpTDIR->Unlock ();
iRes = pEventDisconnect (pEventContext, pConnectionContext, 0, NULL, 0, NULL,
TDI_DISCONNECT_WAIT);
gpTDIR->Lock ();
gpTDIR->DelRef ();
} else {
IFDBG(DebugOut (DEBUG_WARN, L"[TDI] SignalConnectionLoss : nothing reported for conn 0x%08x\n", pC));
}
} else {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] SignalConnectionLoss : already closed\n"));
SVSUTIL_ASSERT ((! pC) || ((! pC->pSendList) && (! pC->pRecvList)));
}
return iRes;
}
int SendMSC (RFCOMM_CONNECTION_OBJECT *pConn, unsigned char v24out, unsigned char brout) {
HANDLE h = gpTDIR->hRFCOMM;
RFCOMM_MSC_In pCallback = gpTDIR->rfcomm_if.rfcomm_MSC_In;
HANDLE hConnection = pConn->hConnect;
unsigned char v24 = TDIR_V24_CONST | (pConn->fc_local ? TDIR_V24_FC : 0) | v24out;
gpTDIR->AddRef ();
gpTDIR->Unlock ();
int iRes = ERROR_INTERNAL_ERROR;
__try {
iRes = pCallback (h, NULL, hConnection, v24, brout);
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDIR] SendMSC Exception in rfcomm_MSC_In\n"));
}
gpTDIR->Lock ();
gpTDIR->DelRef ();
return iRes;
}
int SendRLS (RFCOMM_CONNECTION_OBJECT *pConn, unsigned char rls) {
HANDLE h = gpTDIR->hRFCOMM;
RFCOMM_RLS_In pCallback = gpTDIR->rfcomm_if.rfcomm_RLS_In;
HANDLE hConnection = pConn->hConnect;
gpTDIR->AddRef ();
gpTDIR->Unlock ();
int iRes = ERROR_INTERNAL_ERROR;
__try {
iRes = pCallback (h, NULL, hConnection, rls);
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDIR] SendMSC Exception in rfcomm_MSC_In\n"));
}
gpTDIR->Lock ();
gpTDIR->DelRef ();
return iRes;
}
static DWORD WINAPI StackDisconnect (LPVOID lpUnused) {
tdiR_CloseDriverInstance ();
return 0;
}
static DWORD WINAPI StackXXX (LPVOID lpWhat) {
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"+StackXXX\n"));
if (! gpTDIR) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] StackXXX : ERROR_SERVICE_NOT_ACTIVE\n"));
return ERROR_SERVICE_NOT_ACTIVE;
}
for ( ; ; ) {
gpTDIR->Lock ();
if (! gpTDIR->fIsInitialized) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] StackXXX : ERROR_SERVICE_NOT_ACTIVE\n"));
gpTDIR->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
if (gpTDIR->GetRefCount() == 1)
break;
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"Waiting for ref count in StackXXX\n"));
gpTDIR->Unlock ();
Sleep (100);
}
if ((int)lpWhat == 1) {
gpTDIR->fIsConnected = TRUE;
} else if (((int)lpWhat == 2) || ((int)lpWhat == 3)) {
while (gpTDIR->pnlist) {
RFCOMM_PN_OBJECT *pNext = gpTDIR->pnlist->pNext;
delete gpTDIR->pnlist;
gpTDIR->pnlist = pNext;
}
gpTDIR->fIsConnected = FALSE;
gpTDIR->AddRef ();
for ( ; ; ) {
RFCOMM_CONNECTION_OBJECT *pC = gpTDIR->pcolist;
while (pC && (pC->eStage != OPENED) && (pC->eStage != OPENING))
pC = pC->pNext;
if (! pC)
break;
SignalConnectionLoss (pC, TDI_CONNECTION_ABORTED, TRUE);
}
gpTDIR->DelRef ();
if ((int)lpWhat == 3)
gpTDIR->fIsConnected = TRUE;
}
int iErr = ERROR_SUCCESS;
if (gpTDIR->fIsConnected) {
HANDLE h = gpTDIR->hHCI;
HCI_ReadBDADDR_In pCallback = gpTDIR->hci_if.hci_ReadBDADDR_In;
gpTDIR->AddRef ();
gpTDIR->Unlock ();
__try {
iErr = pCallback (h, NULL);
} __except (1) {
iErr = ERROR_INTERNAL_ERROR;
IFDBG(DebugOut (DEBUG_ERROR, L"[TDIR] : exception in StackXXX!\n"));
}
gpTDIR->Lock ();
gpTDIR->DelRef ();
}
else
gpTDIR->btAddr = SET_NAP_SAP(0, 0);
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"-StackXXX ERROR_SUCCESS\n"));
gpTDIR->Unlock ();
return iErr;
}
static int QueryNdisSize (NDIS_BUFFER *pNdisB) {
int cSize = 0;
while (pNdisB) {
PVOID pVA = NULL;
unsigned int uiLength = 0;
NdisQueryBuffer (pNdisB, &pVA, &uiLength);
if (! pVA)
break;
cSize += uiLength;
NdisGetNextBuffer(pNdisB, &pNdisB);
}
return cSize;
}
static int CopyNdisToFlat
(
NDIS_BUFFER *pNdisB,
unsigned char *pFlatBuf,
int cCount,
int cStartOffset
) {
int cOffset = 0;
int cCopied = 0;
while (pNdisB) {
unsigned char *pVA = NULL;
unsigned int uiLength = 0;
NdisQueryBuffer (pNdisB, (PVOID *)&pVA, &uiLength);
if (! pVA)
break;
if (cOffset + (int)uiLength > cStartOffset) {
SVSUTIL_ASSERT (cOffset <= cStartOffset);
int cBytesAvailable = cOffset + uiLength - cStartOffset;
int cOffsetInBuffer = cStartOffset - cOffset;
int cBytesToCopy = cBytesAvailable > cCount ? cCount : cBytesAvailable;
memcpy (pFlatBuf, pVA + cOffsetInBuffer, cBytesToCopy);
cCount -= cBytesToCopy;
cStartOffset += cBytesToCopy;
cCopied += cBytesToCopy;
pFlatBuf += cBytesToCopy;
SVSUTIL_ASSERT (cCount >= 0);
if (cCount == 0)
break;
}
cOffset += uiLength;
NdisGetNextBuffer(pNdisB, &pNdisB);
}
return cCopied;
}
static int CountPendingSends (RFCOMM_CONNECTION_OBJECT *pConn) {
RFCOMM_SEND_OBJECT *pSendList = pConn->pSendList;
int cTotalSize = 0;
while (pSendList) {
int cBytes = QueryNdisSize (pSendList->pNdisBuffer) - pSendList->cBytesUsed;
SVSUTIL_ASSERT (cBytes >= 0);
cTotalSize += cBytes;
pSendList = pSendList->pNext;
}
return cTotalSize;
}
static int TransferPendingSends (RFCOMM_CONNECTION_OBJECT *pConn, unsigned char *pBuff, int cBuff) {
RFCOMM_SEND_OBJECT *pSendList = pConn->pSendList;
int cTotalSent = 0;
while (pSendList && (cBuff > 0)) {
int cBytes = QueryNdisSize (pSendList->pNdisBuffer) - pSendList->cBytesUsed;
SVSUTIL_ASSERT (cBytes >= 0);
if (cBytes > cBuff)
cBytes = cBuff;
if (cBytes > 0) {
int cTransf = CopyNdisToFlat (pSendList->pNdisBuffer, pBuff, cBytes, pSendList->cBytesUsed);
SVSUTIL_ASSERT (cTransf == cBytes);
cBuff -= cBytes;
pBuff += cBytes;
pSendList->cBytesUsed += cBytes;
}
cTotalSent += cBytes;
pSendList = pSendList->pNext;
}
SVSUTIL_ASSERT (cBuff == 0);
return cTotalSent;
}
static int GetQuota (RFCOMM_CONNECTION_OBJECT *pC) {
if (pC->fc_credit && (pC->imax_recv < (pC->mtu * 2 * PORTEMU_CREDITS_LOWEST)))
return pC->mtu * 2 * PORTEMU_CREDITS_LOWEST;
return pC->imax_recv;
}
static int GiveCredits (RFCOMM_CONNECTION_OBJECT *pC) {
if ((! pC->fc_credit) || (pC->iGaveCredits > PORTEMU_CREDITS_LOW))
return 0;
int nCredits = (GetQuota (pC) - pC->irecvd) / pC->mtu - pC->iGaveCredits;
return nCredits > 0 ? nCredits : 0;
}
static void SendCredits (RFCOMM_CONNECTION_OBJECT *pC) {
SVSUTIL_ASSERT (pC->fc_credit);
if (pC->iGaveCredits > PORTEMU_CREDITS_LOWEST)
return;
int nCredits = (GetQuota (pC) - pC->irecvd) / pC->mtu - pC->iGaveCredits;
if (nCredits <= 0)
return;
IFDBG(DebugOut (DEBUG_TDI_PACKETS, L"[TDIR] SendCredits 0x%08x : sending %d credits\n", pC, nCredits));
BD_BUFFER *pBuffer = BufferAlloc (gpTDIR->cDeviceHeader + gpTDIR->cDeviceTrailer + DEBUG_OVERHEAD);
if (! pBuffer) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDIR] SendCredits 0x%08x : <out of memory>\n", pC));
return;
}
pBuffer->cStart = gpTDIR->cDeviceHeader;
pBuffer->cEnd = pBuffer->cSize - gpTDIR->cDeviceTrailer;
SVSUTIL_ASSERT (BufferTotal (pBuffer) == DEBUG_OVERHEAD);
pC->iGaveCredits += nCredits;
#if defined (DEBUG_CREDIT_FLOW)
pC->iCreditsSent += nCredits;
#endif
#if defined (DEBUG_PEER_SYNCHRONIZATION)
PeerDebugData pd;
#if defined (DEBUG_CREDIT_FLOW)
pd.iGaveCredits = pC->iGaveCredits;
pd.iHaveCredits = pC->iHaveCredits;
pd.iPacketsRecv = pC->iPacketsRecv;
pd.iPacketsSent = pC->iPacketsSent;
pd.iCreditsRecv = pC->iCreditsRecv;
pd.iCreditsSent = pC->iCreditsSent;
#endif
SVSUTIL_ASSERT (sizeof(pd) == DEBUG_OVERHEAD);
memcpy (pBuffer->pBuffer + pBuffer->cEnd - sizeof(pd), &pd, sizeof(pd));
#endif
HANDLE h = gpTDIR->hRFCOMM;
HANDLE hConn = pC->hConnect;
RFCOMM_DataDown_In pCallback = gpTDIR->rfcomm_if.rfcomm_DataDown_In;
gpTDIR->Unlock ();
__try {
pCallback (h, NULL, hConn, pBuffer, nCredits);
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDIR] SendCredits : exception in rfcomm_DataDown_In\n"));
}
gpTDIR->Lock ();
}
static TDI_STATUS SendData (RFCOMM_CONNECTION_OBJECT *pConn) {
if (pConn != GetConnectionObject ((HANDLE)pConn)) {
IFDBG(DebugOut (DEBUG_WARN, L"[TDIR] SendData : Connection 0x%08x not found\n", pConn));
return TDI_INVALID_CONNECTION;
}
if (pConn->fSending) // Guard against packets coming out of order
return TDI_PENDING;
for ( ; ; ) {
if (! gpTDIR->fIsConnected) {
IFDBG(DebugOut (DEBUG_WARN, L"[TDIR] SendData : disconnected\n"));
return TDI_INVALID_STATE;
}
if (pConn->eStage != OPENED) {
IFDBG(DebugOut (DEBUG_WARN, L"[TDIR] SendData : Connection 0x%08x not OPEN\n", pConn));
return TDI_CONNECTION_RESET;
}
if ((pConn->isent >= pConn->imax_send) ||
(pConn->fc_credit && (pConn->iHaveCredits <= 0)) ||
((! pConn->fc_credit) && (pConn->fc_remote || pConn->fc_aggregate)))
break;
int cSend = CountPendingSends (pConn);
SVSUTIL_ASSERT (cSend >= 0);
if (cSend == 0) {
if (pConn->fCloseHaveSend) {
SignalConnectionLoss (pConn, TDI_GRACEFUL_DISC, TRUE);
if (gpTDIR->fIsInitialized && (pConn == GetConnectionObject ((HANDLE)pConn)))
DisconnectConnection (pConn, NULL, NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -