📄 request.c
字号:
__put_u8(pdu->data,SDP_DTD_SEQ8); // DataSequence pdu->length += sizeof(uint8_t); //NOTE: The size of the DataSequence is set later in the code ! (in this case the value will be 0) } // End litos fix if (pdu->length > maxExpectedAttrSize) { sdp_cstate_t newState; memset((char *)&newState, 0, sizeof(sdp_cstate_t)); newState.timestamp = sdp_add_rsp_cscache(requestPdu->fd, pdu); /* ** Reset the buffer size to the maximum expected and ** set the sdp_cstate_t */ pdu->length = maxExpectedAttrSize; newState.value.maxBytesSent = maxExpectedAttrSize; continuationStateSize = sdp_set_cstate(pdu, &newState); } else continuationStateSize = sdp_set_cstate(pdu, NULL); } else { /* * Continuation State exists -> get from cache */ sdppdu_t *pCache; uint16_t bytesSent = 0; /* ** Get the cached response from the buffer */ pCache = sdp_get_rsp_cscache(requestPdu->fd, pCState); if (pCache != NULL) { pResponse = pCache->data; bytesSent = btmin(maxExpectedAttrSize, (pCache->length - pCState->value.maxBytesSent)); memcpy(pdu->data, (pResponse + pCState->value.maxBytesSent), bytesSent); pdu->length += bytesSent; pCState->value.maxBytesSent += bytesSent; if (pCState->value.maxBytesSent == pCache->length) { /* remove response from cache as well */ continuationStateSize = sdp_set_cstate(pdu, NULL); sdp_del_rsp_cscache(requestPdu->fd, pCState); } else continuationStateSize = sdp_set_cstate(pdu, pCState); } else { status = -1; DBPRT("Non null continuation state, but null cache buffer"); } } if ((responseCount == 0) && (pCState == NULL)) { //we've not found anything - create an empty sequence sdp_append_pdu(pdu, &localPDUForm); } // push header pdu->data -= sizeof(uint16_t); pdu->size += sizeof(uint16_t); if (status != 0) { __put_u16(pdu->data, htons(status)); pdu->length = sizeof(uint16_t); } else { /* * set attribute list byte count */ __put_u16(pdu->data, htons(pdu->length - continuationStateSize)); pdu->length += sizeof(uint16_t); } free(localPDUForm.data);exit: if (searchPattern) s_list_destroy(&searchPattern); if (attrSeq) s_list_destroy(&attrSeq); return status;}/* MAIN in service registraion */sdpsvc_t *sdp_srv_extr_pdu(char *pdata, uint32_t handleExpected, int *bytesScanned){ int localExtractedLength = 0; char *localSeqPtr = NULL; uint8_t dtd; int sequenceLength = 0; sdpsvc_t *svcRec = NULL; localSeqPtr = sdp_extr_seq_dtd(pdata, &dtd, &sequenceLength, bytesScanned); /* ** Check if the PDU already has a service record handle, ** int which case this may be a update request */ if (handleExpected != 0xffffffff) svcRec = sdp_find_svc(handleExpected); if (svcRec == NULL) { svcRec = sdp_create_svc(); svcRec->attributeList = NULL; } localExtractedLength = sdp_extr_attrs(svcRec, localSeqPtr, sequenceLength); if (localExtractedLength >= 0) *bytesScanned += localExtractedLength; return svcRec;}/* ** Request to create a brand new service record ** The newly created service record is added to the ** service repository * MAIN in service registraion */int _sdp_register_service(sdp_request_t *sdpReq, sdppdu_t *response){ char *pdata; int bytesScanned = 0; sdpsvc_t *svcRec; sdp_hdr_t *sdpPduHeader; int length = 0; sdpdata_t *browseAttrData = NULL; /* ** Extract buffer contents */ sdpPduHeader = (sdp_hdr_t *)sdpReq->data; pdata = sdpReq->data + sizeof(sdp_hdr_t); /* ** Extract and save image of PDU, since we need ** it when clients request thsi attribute */ svcRec = sdp_srv_extr_pdu(pdata, 0xffffffff, &bytesScanned); if (!svcRec) return SDP_ERR_REQUEST_SYNTAX; svcRec->serviceRecordHandle = (uint32_t)svcRec; sdp_add_svc(svcRec); sdp_append_attr(svcRec, SDP_ATTR_SERVICE_RECORD_HANDLE, sdp_put_u32(svcRec->serviceRecordHandle)); /* ** Also check if the browse group descriptor is NULL, ** ensure that the record belongs to the ROOT group */ if ((browseAttrData = sdp_get_attr(svcRec, SDP_ATTR_BROWSE_GROUP_LIST)) == NULL) sdp_add_uuid16_to_pattern(svcRec, SDP_UUID_PUBLIC_BROWSE_GROUP); sdp_gen_svc_pdu(svcRec); sdp_update_time(); /* ** Build a response buffer */ pdata = response->data; __put_u32(pdata, htonl(svcRec->serviceRecordHandle)); DBPRT("Sending back svcRecHandle : 0x%x", svcRec->serviceRecordHandle); length += sizeof(uint32_t); response->length = length; /* set owner of the service */ svcRec->fd = sdpReq->fd; return 0;}/* ** Register a service record (this means updating the ** contents of a newly created service record or updating ** the contents of an existing record) */int _sdp_update_service(sdp_request_t *sdpReq, sdppdu_t *response){ char *pdata; uint32_t svcRecHandle; sdpsvc_t *svcRecNew = NULL; sdpsvc_t *svcRecOld = NULL; sdp_hdr_t *sdpPduHeader; int bytesScanned = 0; /* ** Extract service record handle */ sdpPduHeader = (sdp_hdr_t *)sdpReq->data; pdata = sdpReq->data + sizeof(sdp_hdr_t); svcRecHandle = ntohl(__get_u32(pdata)); DBPRT("Svc Rec Handle : 0x%x\n", svcRecHandle); pdata += sizeof(uint32_t); svcRecOld = sdp_find_svc(svcRecHandle); DBPRT("SvcRecOld : 0x%x\n", (uint32_t)svcRecOld); if (!svcRecOld) return SDP_ERR_SERVICE_RECORD_HANDLE; svcRecNew = sdp_srv_extr_pdu(pdata, svcRecHandle, &bytesScanned); if ((svcRecNew != NULL) && (svcRecHandle == svcRecNew->serviceRecordHandle)) { sdp_gen_svc_pdu(svcRecNew); sdp_update_time(); } else { DBPRT("SvcRecHandle : 0x%x\n", svcRecHandle); DBPRT("SvcRecHandleNew : 0x%x\n", svcRecNew->serviceRecordHandle); DBPRT("SvcRecNew : 0x%x\n", (uint32_t)svcRecNew); DBPRT("SvcRecOld : 0x%x\n", (uint32_t)svcRecOld); DBPRT("Failure to update, restore old value\n"); if (svcRecNew) sdp_free_svc(svcRecNew); return SDP_ERR_REQUEST_SYNTAX; } return 0;}/* ** Remove a registered service record */int _sdp_delete_service(sdp_request_t *sdpReq, sdppdu_t *response){ char *pdata; int status = 0; uint32_t svcRecHandle; sdpsvc_t *svcRec; /* ** Extract service record handle */ pdata = sdpReq->data + sizeof(sdp_hdr_t); svcRecHandle = ntohl(__get_u32(pdata)); pdata += sizeof(uint32_t); svcRec = sdp_find_svc(svcRecHandle); if (!svcRec) { DBPRT("Could not find record : 0x%x\n", svcRecHandle); return SDP_ERR_SERVICE_RECORD_HANDLE; } status = sdp_del_svc(svcRecHandle); sdp_free_svc(svcRec); if (status == 0) sdp_update_time(); return status;}/* ** Top level request processor. Calls the appropriate processing ** function based on request type. Handles service registration ** client requests also */int _sdp_process_req(sdp_request_t *request){ int status; sdp_hdr_t *requestPduHeader; sdp_hdr_t *responsePduHeader = NULL; sdppdu_t responsePdu; char *bufferStart = NULL; int len; struct sdp_error err_rsp; DBPRT("In process req"); requestPduHeader = (sdp_hdr_t*)request->data; len = sizeof(sdp_hdr_t) + ntohs(requestPduHeader->paramLength); if (len != request->len) { status = SDP_ERR_PDU_SIZE; goto exit; }/* * Test HERE if the data element sequence size match with the total message length * If does not return an SDP_ERROR with status SDP_ERR_REQUEST_SYNTAX * NOTE: Check in the _sdp_* how the length of the request with current length of the message processed if bigger then SDP_ERR_REQUEST_SINTAX */ bufferStart = malloc(USHRT_MAX); if (!bufferStart) { status = -1; goto exit; } memset(bufferStart, 0, USHRT_MAX); //FIXME: necessary??? responsePdu.data = bufferStart + sizeof(sdp_hdr_t); responsePdu.length = 0; responsePdu.size = USHRT_MAX - sizeof(sdp_hdr_t); responsePduHeader = (sdp_hdr_t*)bufferStart; switch (requestPduHeader->pduId) { case SDP_PDU_SEARCH_REQ : DBPRT("Got a svc srch req"); status = _sdp_search_req(request, &responsePdu); responsePduHeader->pduId = SDP_PDU_SEARCH_RSP; break; case SDP_PDU_ATTR_REQ : DBPRT("Got a svc attr req"); status = _sdp_attr_req(request, &responsePdu); responsePduHeader->pduId = SDP_PDU_ATTR_RSP; break; case SDP_PDU_SEARCH_ATTR_REQ : DBPRT("Got a svc srch attr req"); status = _sdp_search_attr_req(request, &responsePdu); responsePduHeader->pduId = SDP_PDU_SEARCH_ATTR_RSP; break; /* Service Registration */ case SDP_PDU_REG_REQ : DBPRT("Service register request"); status = _sdp_register_service(request, &responsePdu); responsePduHeader->pduId = SDP_PDU_REG_RSP; break; case SDP_PDU_UPDATE_REQ : DBPRT("Service update request"); status = _sdp_update_service(request, &responsePdu); responsePduHeader->pduId = SDP_PDU_UPDATE_RSP; break; case SDP_PDU_REMOVE_REQ : DBPRT("Service removal request"); status = _sdp_delete_service(request, &responsePdu); responsePduHeader->pduId = SDP_PDU_REMOVE_RSP; break; default : BTERROR("Unknown PDU ID : 0x%x received", requestPduHeader->pduId); status = SDP_ERR_REQUEST_SYNTAX; break; }exit: if (status) { /* set error code */ if (!bufferStart) { responsePdu.data = (void*)&err_rsp.ErrorCode; responsePdu.size = sizeof(uint16_t); responsePduHeader = (sdp_hdr_t*)&err_rsp; } responsePduHeader->pduId = SDP_PDU_ERROR_RSP; if (status < 0) __put_u16(responsePdu.data, htons(SDP_ERR_RESOURCES)); else __put_u16(responsePdu.data, htons(status)); responsePdu.length = sizeof(uint16_t); } DBPRT("Status : %d", status); DBPRT("Sending a response back"); responsePduHeader->transactionId = requestPduHeader->transactionId; responsePduHeader->paramLength = htons(responsePdu.length); responsePdu.length += sizeof(sdp_hdr_t); responsePdu.data -= sizeof(sdp_hdr_t); len = send(request->fd, responsePdu.data, responsePdu.length, 0); DBPRT("Bytes Sent : %d, requested: %d", len, responsePdu.length); if (bufferStart) free(bufferStart); if (len < 0) return len; return status;}/* * Remove services by RequestSocket * */int _sdp_disc_req(int fd){ int i, status; sdp_del_rsp_cscache(fd, NULL);start_again: for (i = 0; i < s_list_length(serviceList); i++) { sdpsvc_t *svcRec; svcRec = (sdpsvc_t *)s_list_nth_data(serviceList, i); DBPRT("fd: %d, svc->fd: %d\n", fd, svcRec->fd); if (svcRec->fd == fd) { status = sdp_del_svc(svcRec->serviceRecordHandle); sdp_free_svc(svcRec); goto start_again; } } return 0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -