📄 sdpbase.cxx
字号:
while (VerifyLink(pLink) && pLink->pCallQueue) {
Call *pCall = pLink->pCallQueue->pCall;
IFDBG(DebugOut(DEBUG_SDP_PACKETS,L"ProcessNextCall: About to process call 0x%08x\r\n",pLink->pCallQueue->pCall));
if (ERROR_SUCCESS != (iErr = pCall->pSdpConnection->SendInitialRequestToServer())) {
if (VerifyCall(pCall))
NotifySdpClientOfCompletion(pCall,iErr);
continue;
}
return ERROR_SUCCESS;
}
return iErr;
}
void CreateCallForServer(Link *pLink) {
Call *pNewCall = AllocCall(CALL_SDP_SERVER_WORKER,pLink,NULL,NULL);
SdpConnection *pSdpConn = pNewCall ? AllocSdpConnection(pNewCall) : NULL;
if (!pNewCall || !pSdpConn || !AddItemToCallQueue(pLink,pNewCall)) {
if (pNewCall)
DeleteCall(pNewCall);
if (VerifyLink(pLink))
SdpDisconnect(pLink,NULL);
}
}
//******************************************************************
// L2Cap Interface Layer.
//******************************************************************
static int sdp_DataUpInd(void *pUserContext, unsigned short cid, BD_BUFFER *pBuffer) {
int iSize;
IFDBG(DebugOut(DEBUG_SDP_TRACE,L"sdp_DataUpInd(0x%08x,0x%04x,0x%08x)\r\n",pUserContext,cid,pBuffer));
if (! gpSDP) {
if (! pBuffer->fMustCopy)
pBuffer->pFree(pBuffer);
return ERROR_SERVICE_NOT_ACTIVE;
}
gpSDP->Lock();
if (gpSDP->eStage != Connected) {
if (! pBuffer->fMustCopy)
pBuffer->pFree(pBuffer);
IFDBG(DebugOut(DEBUG_WARN,L"sdp_DataUpInd:: ERROR_SERVICE_NOT_ACTIVE\r\n"));
gpSDP->Unlock();
return ERROR_SERVICE_NOT_ACTIVE;
}
iSize = BufferTotal(pBuffer);
BufferGetChunk(pBuffer,iSize,gpSdpReadBuffer);
IFDBG(DumpBuff(DEBUG_SDP_PACKETS, gpSdpReadBuffer, iSize));
if (! pBuffer->fMustCopy)
pBuffer->pFree(pBuffer);
Link *pLink = FindLink(cid);
if (! pLink) {
IFDBG(DebugOut(DEBUG_WARN,L"sdp_DataUpInd:: cid 0x%04x not found\r\n",cid));
gpSDP->Unlock();
return ERROR_NOT_FOUND;
}
Call *pCall = NULL;
if (!pLink->fCallCanceled && pLink->pCallQueue)
pCall = pLink->pCallQueue->pCall;
if (! pCall) {
// This will occur if the call has been canceled by the client.
SVSUTIL_ASSERT(!pLink->fIncoming);
IFDBG(DebugOut(DEBUG_SDP_PACKETS,L"sdp_DataUpInd:: pCall 0x%08x not found\r\n",pCall));
// Send off next request in call queue if there is one.
pLink->fCallCanceled = 0;
ProcessNextCall(pLink);
gpSDP->Unlock();
return ERROR_NOT_FOUND;
}
SVSUTIL_ASSERT(pCall->fWhat & CALL_SDP_SEARCH_WORKER);
SdpConnection *pSdpConn = pCall->pSdpConnection;
unsigned long status = pSdpConn->ReadWorkItemWorker(gpSdpReadBuffer,iSize);
if (!pLink->fIncoming && status != STATUS_PENDING) {
NotifySdpClientOfCompletion(pCall,MapStatusToErrorCode(status));
if (VerifyLink(pLink))
ProcessNextCall(pLink);
}
else if (pLink->fIncoming && status != ERROR_SUCCESS) {
ResetSdpConnection(pCall->pSdpConnection);
}
gpSDP->Unlock();
return ERROR_SUCCESS;
}
static int sdp_DisconnectInd(void *pUserContext, unsigned short cid, int iErr) {
IFDBG(DebugOut(DEBUG_SDP_TRACE,L"sdp_DisconnectInd(0x%08x,0x%04x)\r\n",pUserContext,cid));
if (! gpSDP)
return ERROR_SERVICE_NOT_ACTIVE;
gpSDP->Lock();
if (gpSDP->eStage != Connected) {
gpSDP->Unlock();
return ERROR_SERVICE_NOT_ACTIVE;
}
Link *pLink = FindLink(cid);
if (!pLink) {
IFDBG(DebugOut(DEBUG_SDP_PACKETS,L"sdp_DisconnectInd: cid=0x%04x doesn't have corresponding SDP connection\r\n",cid));
gpSDP->Unlock();
return ERROR_NOT_FOUND;
}
// The call associated with creating the link should've been deleted already.
DeleteLink(pLink);
gpSDP->Unlock();
return ERROR_SUCCESS;
}
static int sdp_lStackEvent(void *pUserContext, int iEvent, void *pEventContext) {
IFDBG(DebugOut(DEBUG_SDP_TRACE,L"sdp_lStackEvent(0x%08x,%d,0x%08x)\r\n",pUserContext,iEvent,pEventContext));
switch (iEvent) {
case BTH_STACK_NONE:
case BTH_STACK_HOST_BUFFER:
IFDBG(DebugOut (DEBUG_ERROR, L"Unexpected event - none or host buffer. Doing nothing\n"));
break;
case BTH_STACK_RESET:
IFDBG(DebugOut (DEBUG_SDP_INIT, L"SDP : Stack reset\n"));
btutil_ScheduleEvent (StackReset, NULL);
break;
case BTH_STACK_DOWN:
IFDBG(DebugOut (DEBUG_SDP_INIT, L"SDP : Stack down\n"));
btutil_ScheduleEvent (StackDown, NULL);
break;
case BTH_STACK_UP:
IFDBG(DebugOut (DEBUG_SDP_INIT, L"SDP : Stack up\n"));
btutil_ScheduleEvent (StackUp, NULL);
break;
case BTH_STACK_DISCONNECT:
IFDBG(DebugOut (DEBUG_SDP_INIT, L"SDP : Stack disconnect\n"));
btutil_ScheduleEvent (StackDisconnect, NULL);
break;
case BTH_STACK_FLOW_ON:
IFDBG(DebugOut (DEBUG_SDP_INIT, L"SDP: Somebody turned flow on. Not supported. Disconnecting\n"));
btutil_ScheduleEvent (StackDown, NULL);
break;
case BTH_STACK_FLOW_OFF:
IFDBG(DebugOut (DEBUG_SDP_INIT, L"SDP : HCI Flow back off. Turning stack back on.\n"));
btutil_ScheduleEvent (StackUp, NULL);
break;
default:
IFDBG(DebugOut (DEBUG_ERROR, L"SDP: unknown stack event. Disconnecting out of paranoia.\n"));
btutil_ScheduleEvent (StackDown, NULL);
}
return ERROR_SUCCESS;
}
static int sdp_lCallAborted(void *pCallContext, int iError) {
IFDBG(DebugOut(DEBUG_SDP_TRACE,L"sdp_lCallAborted(0x%08x,%d)\r\n",pCallContext,iError));
if (! gpSDP)
return ERROR_SERVICE_NOT_ACTIVE;
gpSDP->Lock();
if (!gpSDP->IsStackRunning()) {
gpSDP->Unlock();
return ERROR_SERVICE_NOT_ACTIVE;
}
Call *pCall = VerifyCall((Call *)pCallContext);
if (! pCall) {
gpSDP->Unlock();
return ERROR_NOT_FOUND;
}
if (pCall->fWhat & CALL_SDP_SEARCH) {
SVSUTIL_ASSERT(VerifyLink (pCall->pLink));
Link *pLink = pCall->pLink;
// If the call is currently pending then when we get a response it'll be
// to this call (and item that'll be on head of queue at response time).
if (pLink->pCallQueue && pLink->pCallQueue->pCall==pCall) {
IFDBG(DebugOut(DEBUG_SDP_PACKETS,L"Call (0x%08x) aborted is outstanding on link (0x%08x), further sends will pend it's response\r\n",pCall,pLink));
pLink->fCallCanceled = 1;
}
}
// During connection it's possible mutliple calls are pointing to same link. Remove all of them.
if (pCall->fWhat == CALL_SDP_CONNECT) {
Call *pTrav = gpSDP->pCalls;
Link *pLink = pCall->pLink; // save in case memory goes away during NotifySdpClientOfCompletion release of CritSec.
while (pTrav) {
if ((pTrav != pCall) && (pTrav->pLink == pLink)) {
SVSUTIL_ASSERT(pTrav->fWhat == CALL_SDP_CONNECT);
NotifySdpClientOfCompletion(pTrav,iError);
// since we gave up CritSec in above call list may have changed, start @ beginning.
pTrav = gpSDP->pCalls;
continue;
}
pTrav = pTrav->pNext;
}
}
if (VerifyCall(pCall)) {
if ((pCall->fWhat & CALL_SDP_ACCEPT_CONNECT) && VerifyLink(pCall->pLink))
SdpDisconnect(pCall->pLink,NULL);
if (VerifyCall(pCall))
NotifySdpClientOfCompletion(pCall,iError);
}
gpSDP->Unlock();
return ERROR_SUCCESS;
}
static int sdp_ConfigInd(void *pUserContext, unsigned char id, unsigned short cid, unsigned short usOutMTU, unsigned short usInFlushTO, struct btFLOWSPEC *pInFlow, int cOptNum, struct btCONFIGEXTENSION **ppExtendedOptions) {
IFDBG(DebugOut(DEBUG_SDP_TRACE,L"sdp_ConfigInd(0x%08x,%c,%d,%d,%d)\r\n",pUserContext,id,cid,usOutMTU,usInFlushTO));
if (! gpSDP)
return ERROR_SERVICE_NOT_ACTIVE;
gpSDP->Lock();
if (gpSDP->eStage != Connected) {
gpSDP->Unlock();
return ERROR_SERVICE_NOT_ACTIVE;
}
Link *pLink = FindLink(cid);
Call *pCall = pLink ? FindCall(pLink) : NULL;
if (! pCall) {
IFDBG(DebugOut(DEBUG_SDP_PACKETS,L"sdp_ConfigInd: can't find link 0x%04x, returns ERROR_NOT_FOUND\r\n",cid));
gpSDP->Unlock();
return ERROR_NOT_FOUND;
}
SVSUTIL_ASSERT(pLink == pCall->pLink);
SVSUTIL_ASSERT(pCall->fWhat & CALL_SDP_ACCEPT_CONNECT);
int fAccept = FALSE;
if ((usInFlushTO == 0xffff) && (!pInFlow || (pInFlow->service_type == 0x01)) && btutil_VerifyExtendedL2CAPOptions (cOptNum, ppExtendedOptions)) {
pCall->pLink->fStage |= CONFIG_IND_DONE;
pCall->pLink->outMTU = usOutMTU ? usOutMTU : L2CAP_MTU;
fAccept = TRUE;
if (pLink->fStage == UP) {
IFDBG(DebugOut(DEBUG_SDP_PACKETS,L"sdp_ConfigInd:: connection complete for pCall=0x%08x\r\n",pCall));
}
}
HANDLE hL2CAP = gpSDP->hL2CAP;
L2CA_ConfigResponse_In pCallback = gpSDP->l2cap_if.l2ca_ConfigResponse_In;
IFDBG(DebugOut(DEBUG_SDP_CALLBACK,L"Going into l2ca_ConfigResponse_In\r\n"));
gpSDP->AddRef();
gpSDP->Unlock();
__try {
pCallback(hL2CAP, pCall, id, cid, fAccept ? 0 : 2, 0, 0xffff, NULL, 0, NULL);
} __except (1) {
IFDBG(DebugOut(DEBUG_ERROR,L"Exception in l2ca_ConfigResponse_In\r\n"));
}
gpSDP->Lock();
gpSDP->DelRef();
if (gpSDP->eStage == Connected && VerifyLink (pLink) && (pLink->fStage == UP)) {
// There maybe multiple calls waiting for connection with this link. Run through all of them.
// We delete the call in NotifySdpClientOfCompletion for client case.
if (NULL != (pCall = FindCall(pLink,CALL_SDP_ACCEPT_CONNECT))) {
SVSUTIL_ASSERT((pCall->pLink == pLink) && VerifyCall(pCall));
if (pLink->fIncoming) {
CreateCallForServer(pLink);
DeleteCall(pCall);
}
else {
NotifySdpClientOfCompletion(pCall,ERROR_SUCCESS);
}
}
}
IFDBG(DebugOut(DEBUG_SDP_CALLBACK,L"Came from l2ca_ConfigResponse_In\r\n"));
gpSDP->Unlock();
return ERROR_SUCCESS;
}
static int sdp_ConfigReq_Out(void *pCallContext, unsigned short usResult, unsigned short usInMTU, unsigned short usOutFlushTO, struct btFLOWSPEC *pOutFlow, int cOptNum, struct btCONFIGEXTENSION **ppExtendedOptions) {
IFDBG(DebugOut (DEBUG_SDP_TRACE,L"sdp_ConfigReq_Out(0x%08x,%d,%d,%d)\r\n",pCallContext,usResult,usInMTU,usOutFlushTO));
if (! gpSDP)
return ERROR_SERVICE_NOT_ACTIVE;
gpSDP->Lock();
if (gpSDP->eStage != Connected) {
gpSDP->Unlock();
return ERROR_SERVICE_NOT_ACTIVE;
}
Call *pCall = VerifyCall((Call *)pCallContext,CALL_SDP_ACCEPT_CONNECT);
if (! pCall) {
gpSDP->Unlock();
return ERROR_NOT_FOUND;
}
Link *pLink = pCall->pLink;
SVSUTIL_ASSERT(VerifyLink(pLink));
if (usResult == 0) {
SVSUTIL_ASSERT(! (pLink->fStage & CONFIG_REQ_DONE));
SVSUTIL_ASSERT(pLink->fStage & CONNECTED);
SVSUTIL_ASSERT(pLink->cid);
SVSUTIL_ASSERT(pLink->psm);
pLink->fStage |= CONFIG_REQ_DONE;
if (pLink->fStage == UP) {
IFDBG(DebugOut(DEBUG_SDP_PACKETS,L"sdp_ConfigInd:: connection complete for pCall=0x%08x\r\n",pCall));
// There maybe multiple calls waiting for connection with this link. Run through all of them.
while (NULL != (pCall = FindCall(pLink,CALL_SDP_ACCEPT_CONNECT))) {
SVSUTIL_ASSERT(pCall->pLink == pLink && VerifyCall(pCall));
if (pLink->fIncoming) {
CreateCallForServer(pLink);
DeleteCall(pCall);
}
else {
NotifySdpClientOfCompletion(pCall,ERROR_SUCCESS);
}
}
}
gpSDP->Unlock();
return ERROR_SUCCESS;
}
gpSDP->Unlock();
sdp_lCallAborted(pCallContext, ERROR_CONNECTION_ABORTED);
return ERROR_SUCCESS;
}
static int sdp_ConnectInd(void *pUserContext, BD_ADDR *pba, unsigned short cid, unsigned char id, unsigned short psm) {
IFDBG(DebugOut(DEBUG_SDP_TRACE,L"sdp_ConnectInd(0x%08x,0x%04x 0x%08x,%d,%c,%d)\r\n",pUserContext,pba->NAP,pba->SAP,cid,id,psm));
if (! gpSDP)
return ERROR_SERVICE_NOT_ACTIVE;
gpSDP->Lock();
if (gpSDP->eStage != Connected) {
gpSDP->Unlock();
return ERROR_SERVICE_NOT_ACTIVE;
}
unsigned short result;
unsigned short status = 0;
unsigned short mtu = 0;
if (psm != PSM_SDP) {
IFDBG(DebugOut(DEBUG_ERROR,L"sdp_ConnectInd received connect for psm = %d (not SDP PSM)\r\n",psm));
SVSUTIL_ASSERT(0); // hitting this means that L2CAP has given us a request for a caller on a PSM that SDP did not specify.
gpSDP->Unlock();
return ERROR_INVALID_PARAMETER;
}
Call *pCall = AllocCall(CALL_SDP_ACCEPT,NULL,NULL,NULL);
Link *pLink = pCall ? AllocLink() : NULL;
if (pLink) {
pCall->pLink = pLink;
pLink->b = *pba;
pLink->cid = cid;
pLink->fStage = CONNECTED;
pLink->inMTU = DEFAULT_IN_MTU_SIZE;
pLink->outMTU = 0;
pLink->psm = psm;
pLink->fIncoming = TRUE;
pLink->pNext = gpSDP->pLinks;
gpSDP->pLinks = pLink;
result = 0;
mtu = pLink->inMTU;
} else {
if (pCall)
DeleteCall(pCall);
result = 4;
}
HANDLE hL2CAP = gpSDP->hL2CAP;
L2CA_ConnectResponse_In pCallbackConnect = gpSDP->l2cap_if.l2ca_ConnectResponse_In;
L2CA_ConfigReq_In pCallbackConfig = gpSDP->l2cap_if.l2ca_ConfigReq_In;
IFDBG(DebugOut(DEBUG_SDP_CALLBACK,L"Calling into l2ca_ConnectResponse_In\r\n"));
gpSDP->AddRef();
gpSDP->Unlock();
__try {
pCallbackConnect(hL2CAP, NULL, pba, id, cid, result, status);
} __except (1) {
IFDBG(DebugOut(DEBUG_ERROR,L"Exception in l2ca_ConfigReq_In\r\n"));
}
IFDBG(DebugOut(DEBUG_SDP_CALLBACK,L"Came from l2ca_ConnectResponse_In\r\n"));
if (result == 0) {
int iRes = ERROR_INTERNAL_ERROR;
IFDBG(DebugOut(DEBUG_SDP_CALLBACK,L"Calling into l2ca_ConfigReq_In\r\n"));
__try {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -