📄 tdi.cxx
字号:
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));
if (pAddr->fAuthenticate || pAddr->fEncrypt) {
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"Address object 0x%08x requires authentication\n", pAddr));
SVSCookie cookie = btutil_ScheduleEvent (AuthenticateConnectionRequest, hConnection, 0);
if (cookie)
fSkipReply = TRUE;
else {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] Could not create authentication thread in tdir_connect_request_ind\n"));
}
} else {
cPinLength = pAddr->cPinLength;
memcpy (caPinData, pAddr->caPinData, sizeof(caPinData));
SVSUTIL_ASSERT ((cPinLength >= 0) && (cPinLength <= PIN_SIZE));
fAcceptConnection = AcceptIncomingCall (pAddr, hConnection);
}
} else
IFDBG(DebugOut (DEBUG_ERROR, L"Address translation failed for connection 0x%08x\n", hConnection));
} else
IFDBG(DebugOut (DEBUG_ERROR, L"Address translation failed for connection 0x%08x\n", hConnection));
if (gpTDIR->fIsConnected && (! fSkipReply)) {
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"tdir_connect_request_ind : %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 {
if (fAcceptConnection && cPinLength) {
bt_addr bt = SET_NAP_SAP (b.NAP, b.SAP);
BthSetPIN (&bt, cPinLength, caPinData);
}
pCallback (h, NULL, hConnection, fAcceptConnection);
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] tdir_connect_request_ind Exception in rfcomm_ConnectResponse_In\n"));
}
gpTDIR->Lock ();
gpTDIR->DelRef ();
}
if (gpTDIR->fIsConnected && (! fSkipReply) && fAcceptConnection) {
RFCOMM_CONNECTION_OBJECT *pConn = GetConnectionByHandle (hConnection);
if (pConn)
SendMSC (pConn, TDIR_V24_RTC|TDIR_V24_RTR, 0xff);
}
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"-tdir_connect_request_ind ERROR_SUCCESS\n"));
gpTDIR->Unlock ();
return ERROR_SUCCESS;
}
static int ConnectEntrySDP(RFCOMM_CONNECTION_OBJECT *pC) {
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"[TDIR] ConnectEntrySDP : 0x%08x\n", pC));
int iErr = ERROR_INTERNAL_ERROR;
BD_ADDR b;
b.NAP = GET_NAP(pC->BTAddr.btAddr);
b.SAP = GET_SAP(pC->BTAddr.btAddr);
HANDLE h = gpTDIR->hSDP;
SDP_Connect_In pCallback = gpTDIR->sdp_if.sdp_Connect_In;
gpTDIR->AddRef ();
gpTDIR->Unlock ();
__try {
iErr = pCallback (h, pC, &b);
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDIR] : exception in ConnectEntrySDP!\n"));
}
gpTDIR->Lock ();
gpTDIR->DelRef ();
if (!GetConnectionObject ((HANDLE)pC) || (!gpTDIR->fIsConnected && (iErr == ERROR_SUCCESS)))
iErr = ERROR_OPERATION_ABORTED;
return iErr;
}
static int ConnectEntryRFCOMM(RFCOMM_CONNECTION_OBJECT *pC) {
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"[TDIR] ConnectEntryRFCOMM : 0x%08x\n", pC));
SVSUTIL_ASSERT (! pC->hConnect);
int iErr = ERROR_INTERNAL_ERROR;
HANDLE hConnect = NULL;
HANDLE h = gpTDIR->hRFCOMM;
RFCOMM_CreateChannel pCallback = gpTDIR->rfcomm_if.rfcomm_CreateChannel;
unsigned char chPort = (unsigned char)pC->BTAddr.port;
bt_addr bt = pC->BTAddr.btAddr;
int cPinLength = pC->cPinLength;
unsigned char caPinData[PIN_SIZE];
memcpy (caPinData, pC->caPinData, sizeof(caPinData));
SVSUTIL_ASSERT ((cPinLength >= 0) && (cPinLength <= PIN_SIZE));
gpTDIR->AddRef ();
gpTDIR->Unlock ();
__try {
if (cPinLength)
BthSetPIN (&bt, cPinLength, caPinData);
BD_ADDR b;
b.NAP = GET_NAP(bt);
b.SAP = GET_SAP(bt);
iErr = pCallback (h, &b, chPort, &hConnect);
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDIR] : exception in ConnectEntryRFCOMM!\n"));
}
gpTDIR->Lock ();
gpTDIR->DelRef ();
#if defined (DEBUG) || defined (_DEBUG)
if (hConnect) {
RFCOMM_CONNECTION_OBJECT *pC2 = gpTDIR->pcolist;
while (pC2) {
SVSUTIL_ASSERT ((pC2 == pC) || (pC2->hConnect != hConnect));
pC2 = pC2->pNext;
}
}
#endif
pC = GetConnectionObject ((HANDLE)pC);
if (hConnect && gpTDIR->fIsConnected && pC && (iErr == ERROR_SUCCESS)) {
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"[TDIR] ConnectEntryRFCOMM : object 0x%08x handle 0x%08x channel = %d\n", pC, hConnect, chPort));
pC->hConnect = hConnect;
int n1 = pC->mtu;
RFCOMM_PNREQ_In pCallback2 = gpTDIR->rfcomm_if.rfcomm_PNREQ_In;
gpTDIR->AddRef ();
gpTDIR->Unlock ();
iErr = ERROR_INTERNAL_ERROR;
__try {
iErr = pCallback2 (h, pC, hConnect, TDIR_PRI, n1, RFCOMM_PN_CREDIT_IN, RFCOMM_PN_CREDIT_MAX);
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDIR] : exception in rfcomm_CreateChannel!\n"));
}
gpTDIR->Lock ();
gpTDIR->DelRef ();
if (gpTDIR->fIsInitialized)
pC = GetConnectionObject ((HANDLE)pC);
else
pC = NULL;
}
if (! pC)
iErr = ERROR_OPERATION_ABORTED;
return iErr;
}
void SDPDisconnect(unsigned short cid) {
HANDLE h = gpTDIR->hSDP;
SDP_Disconnect_In pCallback = gpTDIR->sdp_if.sdp_Disconnect_In;
SVSUTIL_ASSERT(gpTDIR->IsLocked());
gpTDIR->AddRef ();
gpTDIR->Unlock ();
__try {
pCallback (h,NULL,cid);
} __except (1) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDIR] : exception in sdp_disconnect_in!\n"));
}
gpTDIR->Lock ();
gpTDIR->DelRef ();
}
static int tdir_data_up_ind (void *pUserContext, HANDLE hConnection, BD_BUFFER *pba, int additional_credits) {
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"+tdir_data_up_ind, data = %d, extra credits = %d\n", BufferTotal (pba), additional_credits));
if (! gpTDIR) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] tdir_data_up_ind : ERROR_SERVICE_NOT_ACTIVE\n"));
return ERROR_SERVICE_NOT_ACTIVE;
}
gpTDIR->Lock ();
if (! gpTDIR->fIsConnected) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] tdir_data_up_ind : ERROR_SERVICE_NOT_ACTIVE\n"));
if ((! pba->fMustCopy) && pba->pFree)
pba->pFree (pba);
gpTDIR->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
#if defined (DEBUG_PEER_SYNCHRONIZATION)
PeerDebugData pd;
PeerDebugData *ppd = NULL;
if (BufferTotal (pba) >= sizeof(pd)) {
memcpy (&pd, pba->pBuffer + pba->cEnd - sizeof(pd), sizeof(pd));
if (pd.magic == DEBUG_PEER_MAGIC) {
pba->cEnd -= sizeof(pd);
ppd = &pd;
}
}
if (! ppd) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] tdir_data_up_ind : mismatch of peer debug builds!\n"));
SVSUTIL_ASSERT (0);
}
#endif
int fDataAccepted = FALSE;
// Try to satisfy outstanding RECVs first...
int cBytes = BufferTotal (pba);
RFCOMM_CONNECTION_OBJECT *pConn = GetConnectionByHandle (hConnection);
if ((cBytes > 0) && pConn && pConn->fc_credit)
--pConn->iGaveCredits;
#if defined (DEBUG_CREDIT_FLOW)
if (pConn && (cBytes > 0))
++pConn->iPacketsRecv;
if (pConn && pConn->fc_credit) {
pConn->iCreditsRecv += additional_credits;
// Credit Invariants
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 + additional_credits != (pConn->iCreditsRecv - pConn->iPacketsSent)) {
RETAILMSG(1, (L"Bluetooth TDI Credit mismatch: HaveCredits = %d (incl %d addtl) Total CreditsRecv = %d Total PacketsSent = %d\n", pConn->iHaveCredits + additional_credits, additional_credits, pConn->iCreditsRecv, pConn->iPacketsSent));
SVSUTIL_ASSERT (0);
}
}
#endif
#if defined (DEBUG_PEER_SYNCHRONIZATION) && defined (DEBUG_CREDIT_FLOW)
if (ppd && pConn) {
SVSUTIL_ASSERT (ppd->iPacketsSent == pConn->iPacketsRecv);
SVSUTIL_ASSERT (ppd->iCreditsSent == pConn->iCreditsRecv);
}
#endif
while (gpTDIR->fIsConnected && (cBytes > 0) && pConn && pConn->pRecvList && pConn->pRecvList->pNdisBuffer) {
SVSUTIL_ASSERT (! pConn->pRecvList->pBuffer);
NDIS_BUFFER *pNdis = pConn->pRecvList->pNdisBuffer;
DWORD dwPerms = SetProcPermissions (pConn->pRecvList->dwPerms);
BOOL bkm = SetKMode (TRUE);
int cBytesToTransfer = QueryNdisSize (pNdis);
if (cBytes < cBytesToTransfer)
cBytesToTransfer = cBytes;
SVSUTIL_ASSERT (pConn->pRecvList->iNdisUsed == 0);
uint StartOffset = 0;
CopyFlatToNdis (pNdis, pba->pBuffer + pba->cStart, cBytesToTransfer, &StartOffset);
SetKMode (bkm);
SetProcPermissions (dwPerms);
pba->cStart += cBytesToTransfer;
pConn->pRecvList->iNdisUsed = cBytesToTransfer;
cBytes = BufferTotal (pba);
RFCOMM_RECEIVE_OBJECT *pThis = pConn->pRecvList;
pConn->pRecvList = pConn->pRecvList->pNext;
PBT_RECV_COMPLETE pRecvEvent = pThis->pRecvEvent;
void *pRecvContext = pThis->pRecvContext;
int iNdisUsed = pThis->iNdisUsed;
delete pThis;
IFDBG(DebugOut (DEBUG_TDI_PACKETS, L"tdir_data_up_ind 0x%08x :: satisfied read request for %d bytes\n", pConn, iNdisUsed));
gpTDIR->AddRef ();
gpTDIR->Unlock ();
pRecvEvent (pRecvContext, TDI_SUCCESS, iNdisUsed);
gpTDIR->Lock ();
gpTDIR->DelRef ();
if (gpTDIR->fIsInitialized)
pConn = GetConnectionByHandle (hConnection);
else
pConn = NULL;
}
SVSUTIL_ASSERT (cBytes >= 0);
if (gpTDIR->fIsConnected && (cBytes > 0) && pConn && pConn->pAddr &&
((pConn->irecvd + cBytes) <= GetQuota (pConn))) {
SVSUTIL_ASSERT ((! pConn->pRecvList) || pConn->pRecvList->pBuffer);
RFCOMM_RECEIVE_OBJECT *pRecv = new RFCOMM_RECEIVE_OBJECT;
if (pRecv) {
memset (pRecv, 0, sizeof(*pRecv));
pRecv->pBuffer = pba->fMustCopy ? BufferCopy (pba) : pba;
if (! pConn->pRecvList)
pConn->pRecvList = pRecv;
else {
RFCOMM_RECEIVE_OBJECT *pRP = pConn->pRecvList;
while (pRP->pNext)
pRP = pRP->pNext;
pRP->pNext = pRecv;
}
fDataAccepted = TRUE;
pConn->irecvd += cBytes;
if (pConn->pAddr && (! pConn->cbDataIndicated)) {
// If we need to queue any data, we indicate it first.
// Only indicate the first time since we are using the same data.
pConn->cbDataIndicated = cBytes;
EventRcvBuffer EventRecvCompleteInfo;
int BytesTaken = 0;
void *pEventReceiveContext = pConn->pAddr->pEventReceiveContext;
void *pConnectionContext = pConn->pConnectionContext;
PRcvEvent pEventReceive = pConn->pAddr->pEventReceive;
gpTDIR->AddRef ();
gpTDIR->Unlock ();
TDI_STATUS TdiStatus = pEventReceive (pEventReceiveContext, pConnectionContext,
0, cBytes, cBytes, (unsigned int *)&BytesTaken, NULL, &EventRecvCompleteInfo);
gpTDIR->Lock ();
gpTDIR->DelRef ();
IFDBG(DebugOut (DEBUG_TDI_PACKETS, L"tdir_data_up_ind 0x%08x :: indicated %d bytes\n", pConn, cBytes));
SVSUTIL_ASSERT (TdiStatus == TDI_NOT_ACCEPTED);
SVSUTIL_ASSERT (BytesTaken == 0);
if (gpTDIR->fIsInitialized)
pConn = GetConnectionByHandle (hConnection);
else
pConn = NULL;
} else {
IFDBG(DebugOut (DEBUG_TDI_PACKETS, L"tdir_data_up_ind 0x%08x :: data already indicated, stored %d bytes\n", pConn, cBytes));
}
if (pConn && (pConn->irecvd > pConn->xon_lim) && (! pConn->fc_local) && (! pConn->fc_credit)) {
IFDBG(DebugOut (DEBUG_TDI_PACKETS, L"Switching flow off for connection 0x%08x\n", pConn));
pConn->fc_local = TRUE;
SendMSC (pConn, TDIR_V24_RTC|TDIR_V24_RTR, 0xff);
}
} else {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDIR] tdir_data_up_ind :: OOM !\n"));
}
}
#if defined (DEBUG) || defined (_DEBUG) || defined (RETAILLOG)
else if (cBytes != 0) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] Data came to nonexistent connection 0x%08x or overflow!\n", hConnection));
if (gpTDIR->fIsConnected && pConn)
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] Overflow details: received so far: %d, quota %d, bytes to queue %d\n", pConn->irecvd, GetQuota (pConn), cBytes));
}
#endif
if (! fDataAccepted) {
if ((! pba->fMustCopy) && pba->pFree)
pba->pFree (pba);
}
if (pConn && (pConn == GetConnectionByHandle (hConnection)) && pConn->fc_credit) {
pConn->iHaveCredits += additional_credits;
if (pConn->iHaveCredits - additional_credits <= 0)
SendData (pConn);
if (gpTDIR->fIsInitialized)
pConn = GetConnectionByHandle (hConnection);
else
pConn = NULL;
}
if (pConn && pConn->fc_credit)
SendCredits (pConn);
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"-tdir_data_up_ind ERROR_SUCCESS\n"));
gpTDIR->Unlock ();
return ERROR_SUCCESS;
}
static int tdir_disconnect_ind (void *pUserContext, HANDLE hConnection) {
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"+tdir_disconnect_ind\n"));
if (! gpTDIR) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] tdir_disconnect_ind : ERROR_SERVICE_NOT_ACTIVE\n"));
return ERROR_SERVICE_NOT_ACTIVE;
}
gpTDIR->Lock ();
if (! gpTDIR->fIsConnected) {
IFDBG(DebugOut (DEBUG_ERROR, L"[TDI] tdir_disconnect_ind : ERROR_SERVICE_NOT_ACTIVE\n"));
gpTDIR->Unlock ();
return ERROR_SERVICE_NOT_ACTIVE;
}
ExtractPN (hConnection, NULL, NULL, NULL);
RFCOMM_CONNECTION_OBJECT *pC = GetConnectionByHandle (hConnection);
if (pC) {
pC->hConnect = NULL;
SignalConnectionLoss (pC, TDI_GRACEFUL_DISC, FALSE);
} else
IFDBG(DebugOut (DEBUG_WARN, L"[TDI] tdir_disconnect_ind : connection for handle 0x%08x not found or in process of being closed!\n", hConnection));
IFDBG(DebugOut (DEBUG_TDI_TRACE, L"-tdir_disconnect_ind 0x%08x ERROR_SUCCESS\n", pC));
gpTDIR->Unlock ();
return ERROR_SUCCESS;
}
static int tdir_msc_ind (void *pUserContext, HANDLE hConnection, unsigned char v24, unsigned char bs) {
IFDBG(D
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -