📄 tdi.cxx
字号:
}
break;
}
if (cSend > pConn->mtu)
cSend = pConn->mtu;
if (cSend > pConn->imax_send - pConn->isent)
cSend = pConn->imax_send - pConn->isent;
RFCOMM_PACKET_OBJECT *pPacket = new RFCOMM_PACKET_OBJECT;
if (! pPacket) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] SendData <out of memory>\n"));
break;
}
BD_BUFFER *pBuffer = BufferAlloc (cSend + gpTDIR->cDeviceHeader + gpTDIR->cDeviceTrailer + DEBUG_OVERHEAD);
if (! pBuffer) {
delete pPacket;
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] SendData <out of memory>\n"));
break;
}
pPacket->pConn = pConn;
pPacket->cBytesSent = cSend;
pPacket->pNext = pConn->pPacketList;
pConn->pPacketList = pPacket;
pBuffer->cEnd = pBuffer->cSize - gpTDIR->cDeviceTrailer;
pBuffer->cStart = gpTDIR->cDeviceHeader;
SVSUTIL_ASSERT (BufferTotal (pBuffer) == (int)(cSend + DEBUG_OVERHEAD));
int cCopiedData = TransferPendingSends (pConn, pBuffer->pBuffer + pBuffer->cStart, cSend);
SVSUTIL_ASSERT (cCopiedData == cSend);
pConn->isent += cSend;
int iCredits = GiveCredits (pConn);
if (pConn->fc_credit) {
--pConn->iHaveCredits;
pConn->iGaveCredits += iCredits;
#if defined (DEBUG_CREDIT_FLOW)
pConn->iCreditsSent += iCredits;
pConn->iPacketsSent += 1;
if (pConn->iGaveCredits != (pConn->iCreditsSent - pConn->iPacketsRecv)) {
SVSUTIL_ASSERT (0);
RETAILMSG(1, (L"Bluetooth TDI Credit mismatch: GaveCredits = %d Total SentCredits = %d Total PacketsRecv = %d\n", pConn->iGaveCredits, pConn->iCreditsSent, pConn->iPacketsRecv));
}
if (pConn->iHaveCredits != (pConn->iCreditsRecv - pConn->iPacketsSent)) {
RETAILMSG(1, (L"Bluetooth TDI Credit mismatch: HaveCredits = %d Total CreditsRecv = %d Total PacketsSent = %d\n", pConn->iHaveCredits, pConn->iCreditsRecv, pConn->iPacketsSent));
SVSUTIL_ASSERT (0);
}
#endif
}
#if defined (DEBUG_PEER_SYNCHRONIZATION)
PeerDebugData pd;
#if defined (DEBUG_CREDIT_FLOW)
pd.iGaveCredits = pConn->iGaveCredits;
pd.iHaveCredits = pConn->iHaveCredits;
pd.iPacketsRecv = pConn->iPacketsRecv;
pd.iPacketsSent = pConn->iPacketsSent;
pd.iCreditsRecv = pConn->iCreditsRecv;
pd.iCreditsSent = pConn->iCreditsSent;
#endif
SVSUTIL_ASSERT (sizeof(pd) == DEBUG_OVERHEAD);
memcpy (pBuffer->pBuffer + pBuffer->cEnd - sizeof(pd), &pd, sizeof(pd));
#endif
HANDLE h = gpTDIR->hRFCOMM;
HANDLE hConnect = pConn->hConnect;
RFCOMM_DataDown_In pCallback = gpTDIR->rfcomm_if.rfcomm_DataDown_In;
IFDBG(DebugOut (DEBUG_TDI_PACKETS, L"SendData 0x%08x : sending %d bytes and %d credits\n", pConn, BufferTotal(pBuffer), iCredits));
pConn->fSending = TRUE;
gpTDIR->AddRef ();
gpTDIR->Unlock ();
__try {
int iRes = pCallback (h, pPacket, hConnect, pBuffer, iCredits);
#if defined (DEBUG) || defined (_DEBUG) || defined (RETAILLOG)
if (iRes != ERROR_SUCCESS)
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] SendData return %d\n", iRes));
#endif
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] SendData Exception in rfcomm_DataDown_In!\n"));
}
gpTDIR->Lock ();
gpTDIR->DelRef ();
if (pConn != GetConnectionObject ((HANDLE)pConn))
return TDI_INVALID_CONNECTION;
pConn->fSending = FALSE;
}
return TDI_PENDING;
}
static int RegisterTransferCompletion (RFCOMM_CONNECTION_OBJECT *pConn, int cBytes) {
RFCOMM_SEND_OBJECT *pS = pConn->pSendList;
pConn->isent -= cBytes;
SVSUTIL_ASSERT (pConn->isent >= 0);
while (pS && (cBytes > 0)) {
int cUnconfirmed = pS->cBytesUsed - pS->cBytesConfirmed;
int cConfirm = cUnconfirmed;
if (cBytes < cConfirm)
cConfirm = cBytes;
pS->cBytesConfirmed += cConfirm;
cBytes -= cConfirm;
pS = pS->pNext;
}
SVSUTIL_ASSERT (cBytes == 0);
for ( ; ; ) {
if (! (gpTDIR->fIsConnected && (pConn == GetConnectionObject ((HANDLE)pConn))))
return ERROR_OPERATION_ABORTED;
if ((! pConn->pSendList) || (pConn->pSendList->cBytesConfirmed != QueryNdisSize (pConn->pSendList->pNdisBuffer)))
break;
RFCOMM_SEND_OBJECT *pNext = pConn->pSendList->pNext;
PBT_SEND_COMPLETE pCallback = pConn->pSendList->pSendCallback;
void *pCallbackContext = pConn->pSendList->pSendContext;
int cBytesSent = pConn->pSendList->cBytesUsed;
delete pConn->pSendList;
pConn->pSendList = pNext;
gpTDIR->AddRef ();
gpTDIR->Unlock ();
pCallback (pCallbackContext, TDI_SUCCESS, cBytesSent);
gpTDIR->Lock ();
gpTDIR->DelRef ();
}
SendData (pConn);
return ERROR_SUCCESS;
}
static int AcceptIncomingCall (RFCOMM_ADDRESS_OBJECT *pAddr, HANDLE hConnection) {
BD_ADDR b;
unsigned char c;
int fLocal;
int fAcceptConnection = FALSE;
int imtu = TDIR_MTU;
int fcreditflow = FALSE;
int icredits = 0;
ExtractPN (hConnection, &imtu, &fcreditflow, &icredits);
if (ERROR_SUCCESS != gpTDIR->rfcomm_if.rfcomm_GetChannelAddress (gpTDIR->hRFCOMM, hConnection, &b, &c, &fLocal)) {
IFDBG(DebugOut (DEBUG_WARN, L"[TDI] AcceptIncomingCall : Cannot resolve address from 0x%08x\n", hConnection));
return FALSE;
} else
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"Connection from %04x%08x 0x%02x accepted\n", b.NAP, b.SAP, c));
BYTE AddrBuf[sizeof(TRANSPORT_ADDRESS) + sizeof(SOCKADDR_BTH)];
PTRANSPORT_ADDRESS pTA = (PTRANSPORT_ADDRESS)AddrBuf;
pTA->TAAddressCount = 1;
pTA->Address[0].AddressLength = sizeof(SOCKADDR_BTH) - 2;
SOCKADDR_BTH *pSockAddr = (SOCKADDR_BTH *) &(pTA->Address[0].AddressType);
BT_ADDR bt = SET_NAP_SAP(b.NAP, b.SAP);
memset (pSockAddr, 0x00, sizeof(SOCKADDR_BTH));
memcpy (&pSockAddr->btAddr, &bt, sizeof(bt));
pSockAddr->addressFamily = AF_BT;
pSockAddr->port = c;
void *pConnectionContext = NULL;
ConnectEventInfo ci;
PConnectEvent pEventConnect = pAddr->pEventConnect;
gpTDIR->AddRef ();
gpTDIR->Unlock ();
TDI_STATUS TdiStatus = pEventConnect (pAddr->pEventConnectContext, TA_SIZE,
pTA, 0x00, NULL, 0x00, NULL, &pConnectionContext, &ci);
gpTDIR->Lock ();
gpTDIR->DelRef ();
if (gpTDIR->fIsConnected && (TdiStatus == TDI_MORE_PROCESSING)) {
RFCOMM_CONNECTION_OBJECT *pConn = GetConnectionByContext (pConnectionContext);
if (pConn) {
SVSUTIL_ASSERT (pConn->pAddr); // This has to be an associated connection!
SVSUTIL_ASSERT (! pConn->pPacketList);
SVSUTIL_ASSERT (! pConn->pSendList);
SVSUTIL_ASSERT (! pConn->pRecvList);
SVSUTIL_ASSERT ((pConn->eStage == INITED) || (pConn->eStage == OPENING));
ResetConnection (pConn, TRUE); // Note - this resets the flow/credits
TransferOptions (pConn, pConn->pAddr); // Note - this overwrites MTU
pConn->hConnect = hConnection;
memset (&pConn->BTAddr, 0, sizeof(pConn->BTAddr));
pConn->BTAddr.addressFamily = AF_BTH;
pConn->BTAddr.port = c;
pConn->BTAddr.btAddr = SET_NAP_SAP(b.NAP, b.SAP);
pConn->mtu = imtu;
if (fcreditflow) {
pConn->fc_credit = TRUE;
pConn->iGaveCredits = RFCOMM_PN_CREDIT_MAX;
pConn->iHaveCredits = icredits;
#if defined (DEBUG_CREDIT_FLOW)
pConn->iCreditsRecv = icredits;
pConn->iCreditsSent = RFCOMM_PN_CREDIT_MAX;
#endif
} else {
pConn->fc_credit = FALSE;
pConn->iGaveCredits = 0;
pConn->iHaveCredits = 0;
#if defined (DEBUG_CREDIT_FLOW)
pConn->iCreditsRecv = 0;
pConn->iCreditsSent = 0;
#endif
}
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"+AcceptIncomingCall 0x%08x : negotiated parms mtu = %d, credit fc = %s, gave credits = %d, have credits = %d\n", pConn, pConn->mtu, pConn->fc_credit ? L"on" : L"off", pConn->iGaveCredits, pConn->iHaveCredits));
pConn->eStage = OPENED;
gpTDIR->AddRef ();
gpTDIR->Unlock ();
ci.cei_rtn(ci.cei_context, TDI_SUCCESS, 0);
gpTDIR->Lock ();
gpTDIR->DelRef ();
return TRUE;
} else
ci.cei_rtn(ci.cei_context, TDI_INVALID_CONNECTION, 0);
} else {
if (TdiStatus == TDI_MORE_PROCESSING)
ci.cei_rtn(ci.cei_context, TDI_CANCELLED, 0);
IFDBG(DebugOut (DEBUG_WARN, L"[TDI] AcceptIncomingCall : AFD doesn't want us :-(\n"));
}
return FALSE;
}
DWORD WINAPI AuthenticateOutgoingConnection (LPVOID arg) {
HANDLE hConnection = (HANDLE)arg;
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"+AuthenticateOutgoingConnection h = 0x%04x\n", hConnection));
if (! gpTDIR) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] AuthenticateOutgoingConnection : ERROR_SERVICE_NOT_ACTIVE\n"));
return ERROR_SERVICE_NOT_ACTIVE;
}
gpTDIR->Lock ();
if (! gpTDIR->fIsConnected) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] AuthenticateOutgoingConnection : ERROR_SERVICE_NOT_ACTIVE\n"));
gpTDIR->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
RFCOMM_CONNECTION_OBJECT *pConn = GetConnectionByHandle (hConnection);
if (pConn) {
SVSUTIL_ASSERT (pConn->pAddr); // This must be an associated connection!
SVSUTIL_ASSERT (! pConn->pPacketList);
SVSUTIL_ASSERT (! pConn->pSendList);
SVSUTIL_ASSERT (! pConn->pRecvList);
SVSUTIL_ASSERT (pConn->hConnect == hConnection);
SVSUTIL_ASSERT (pConn->fAuthenticate || pConn->fEncrypt);
SVSUTIL_ASSERT (pConn->eStage == OPENING);
int TdiStatus = TDI_SUCCESS;
int fAuthenticate = pConn->fAuthenticate;
int fEncrypt = pConn->fEncrypt;
BT_ADDR bt = pConn->BTAddr.btAddr;
gpTDIR->Unlock ();
if (fAuthenticate && (BthAuthenticate (&bt) != ERROR_SUCCESS))
TdiStatus = TDI_CONN_REFUSED;
if (fEncrypt && (TdiStatus == TDI_SUCCESS) && (BthSetEncryption (&bt, TRUE) != ERROR_SUCCESS))
TdiStatus = TDI_CONN_REFUSED;
if (! gpTDIR)
return ERROR_INTERNAL_ERROR;
gpTDIR->Lock ();
if (TdiStatus == TDI_SUCCESS)
ResetConnection (pConn, FALSE); // Leave credits be - they were set in PN process
else
TdiStatus = TDI_CONN_REFUSED;
SignalConnectionCompleteUp (pConn, TdiStatus);
if (gpTDIR->fIsConnected && (pConn == GetConnectionByHandle (hConnection)) && (pConn->eStage == OPENED))
SendMSC (pConn, TDIR_V24_RTC|TDIR_V24_RTR, 0xff);
} else
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] AuthenticateOutgoingConnection : no connection for handle 0x%08x\n", hConnection));
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"-AuthenticateOutgoingConnection ERROR_SUCCESS\n"));
gpTDIR->Unlock ();
return ERROR_SUCCESS;
}
DWORD WINAPI AuthenticateConnectionRequest (LPVOID arg) {
HANDLE hConnection = (HANDLE)arg;
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"+AuthenticateConnectionRequest 0x%04x\n", hConnection));
if (! gpTDIR) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] AuthenticateConnectionRequest : ERROR_SERVICE_NOT_ACTIVE\n"));
return ERROR_SERVICE_NOT_ACTIVE;
}
gpTDIR->Lock ();
if (! gpTDIR->fIsConnected) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] AuthenticateConnectionRequest : ERROR_SERVICE_NOT_ACTIVE\n"));
gpTDIR->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
BD_ADDR b;
unsigned char c;
int fLocal;
int fAcceptConnection = TRUE;
if (ERROR_SUCCESS == gpTDIR->rfcomm_if.rfcomm_GetChannelAddress (gpTDIR->hRFCOMM, hConnection, &b, &c, &fLocal)) {
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"Got connection request from %04x%08x 0x%02x\n", b.NAP, b.SAP, c));
// Find address object...
RFCOMM_ADDRESS_OBJECT *pAddr = gpTDIR->paolist;
while (pAddr &&
(! ((((pAddr->b.NAP == 0) && (pAddr->b.SAP == 0)) || (pAddr->b == b)) && pAddr->fListenOn && pAddr->pEventConnect && (pAddr->ch == c))))
pAddr = pAddr->pNext;
if (pAddr) {
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"Found address object 0x%08x\n", pAddr));
SVSUTIL_ASSERT (pAddr->fAuthenticate || pAddr->fEncrypt);
int fAuthenticate = pAddr->fAuthenticate;
int fEncrypt = pAddr->fEncrypt;
BT_ADDR bt = SET_NAP_SAP (b.NAP, b.SAP);
int cPinLength = pAddr->cPinLength;
unsigned char caPinData[PIN_SIZE];
memcpy (caPinData, pAddr->caPinData, sizeof(caPinData));
SVSUTIL_ASSERT ((cPinLength >= 0) && (cPinLength <= PIN_SIZE));
gpTDIR->Unlock ();
__try {
if (cPinLength)
BthSetPIN (&bt, cPinLength, caPinData);
if (fAuthenticate && (BthAuthenticate (&bt) != ERROR_SUCCESS))
fAcceptConnection = FALSE;
if (fEncrypt && fAcceptConnection && (BthSetEncryption (&bt, TRUE) != ERROR_SUCCESS))
fAcceptConnection = FALSE;
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] exception in security code!\n"));
fAcceptConnection = FALSE;
}
if (! gpTDIR)
return ERROR_INTERNAL_ERROR;
gpTDIR->Lock ();
if (fAcceptConnection && gpTDIR->fIsConnected && (pAddr == GetAddressObject ((HANDLE)pAddr)))
fAcceptConnection = AcceptIncomingCall (pAddr, hConnection);
else
fAcceptConnection = FALSE;
} else {
IFDBG(DebugOut (DEBUG_ERROR, L"Address translation failed for connection 0x%08x\n", hConnection));
fAcceptConnection = FALSE;
}
} else {
IFDBG(DebugOut (DEBUG_ERROR, L"Address translation failed for connection 0x%08x\n", hConnection));
fAcceptConnection = FALSE;
}
if (gpTDIR->fIsConnected) {
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"AuthenticateConnectionRequest : %s connection\n", fAcceptConnection ? L"Accepting" : L"Declining"));
HANDLE h = gpTDIR->hRFCOMM;
RFCOMM_ConnectResponse_In pCallback = gpTDIR->rfcomm_if.rfcomm_ConnectResponse_In;
gpTDIR->AddRef ();
gpTDIR->Unlock ();
__try {
pCallback (h, NULL, hConnection, fAcceptConnection);
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] AuthenticateConnectionRequest Exception in rfcomm_ConnectResponse_In\n"));
}
gpTDIR->Lock ();
gpTDIR->DelRef ();
}
if (gpTDIR->fIsConnected && fAcceptConnection) {
RFCOMM_CONNECTION_OBJECT *pConn = GetConnectionByHandle (hConnection);
if (pConn)
SendMSC (pConn, TDIR_V24_RTC|TDIR_V24_RTR, 0xff);
}
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"-AuthenticateConnectionRequest ERROR_SUCCESS\n"));
gpTDIR->Unlock ();
return ERROR_SUCCESS;
}
//
// RFCOMM interface
//
static int tdir_connect_request_ind (void *pUserContext, HANDLE hConnection, BD_ADDR *pba, unsigned char channel) {
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"+tdir_connect_request_ind\n"));
if (! gpTDIR) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] tdir_connect_request_ind : ERROR_SERVICE_NOT_ACTIVE\n"));
return ERROR_SERVICE_NOT_ACTIVE;
}
gpTDIR->Lock ();
if (! gpTDIR->fIsConnected) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] tdir_connect_request_ind : ERROR_SERVICE_NOT_ACTIVE\n"));
gpTDIR->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
BD_ADDR b;
unsigned char c;
int fLocal;
int fAcceptConnection = FALSE;
int fSkipReply = FALSE;
int cPinLength = 0;
unsigned char caPinData[PIN_SIZE];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -