⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdpclt.c

📁 Affix - Bluetooth Protocol Stack for Linux has been developed at Nokia Research Center in Helsinki
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    Affix - Bluetooth Protocol Stack for Linux   Copyright (C) 2001,2002 Nokia Corporation   Author: Dmitry Kasatkin <dmitry.kasatkin@nokia.com>   Original Author: Guruprasad Krishnamurthy <kgprasad@hotmail.com>   This program is free software; you can redistribute it and/or modify it   under the terms of the GNU General Public License as published by the   Free Software Foundation; either version 2 of the License, or (at your   option) any later version.   This program is distributed in the hope that it will be useful, but   WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   General Public License for more details.   You should have received a copy of the GNU General Public License along   with this program; if not, write to the Free Software Foundation, Inc.,   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.*//*   $Id: sdpclt.c,v 1.56 2003/04/15 10:50:06 kds Exp $   Contains the implementation of the SDP service discovery API    Fixes:   		Dmitry Kasatkin		- Continuation Mechanism		Dmitry Kasatkin		- Port Request		Dmitry Kasatkin		- cleaning		Dmitry Kasatkin		- new simple API*/	 #include <affix/config.h>#include <stdio.h>#include <stdlib.h>#include <malloc.h>#include <string.h>#include <affix/sdp.h>#include <affix/sdpclt.h>#include "utils.h"#include "cstate.h"#include "attr.h"/*** This is a service search request. **** INPUT :****   slist_t *svcSearchList**     Singly linked list containing elements of the search**     pattern. Each entry in the list is a uuid_t (DataTypeSDP_DTD_UUID16)**     of the service to be searched****   uint16_t maxSvcRecordCount**      A 16 bit integer which tells the service, the maximum**      entries that the client can handle in the response. The**      server is obliged not to return > maxSvcRecordCount entries**** OUTPUT :****   int return value**     E_OK **       The request completed successfully. This does not**       mean the requested services were found**     E_FAILURE**       On any failure**     E_TIMEOUT **       The request completed unsuccessfully due to a timeout****   slist_t **svcHandleList**     This variable is set on a successful return if there are**     non-zero service handles. It is a singly linked list of**     service record handles (uint32_t)****   uint16_t *handleCount**     This is a pointer to a 16 bit integer, which is set to **     indicate the number of service record handles present in**     svcHandleList*/int sdp_search_req(		int srvHandle,		slist_t *svcSearchList, 		uint16_t maxSvcRecordCount,		slist_t **svcResponseList,		uint16_t *handleCountInResponse){	int status = 0;	int requestSize = 0, _requestSize;	int responseSize = 0;	int seqLength = 0;	char *pdata, *_pdata;	char *requestBuffer =  NULL;	char *responseBuffer =  NULL;	sdp_hdr_t *pduRequestHeader;	sdp_hdr_t *pduResponseHeader;	sdp_cs_t *pCState = NULL;	//sdppdu_t concatenatedResponseBuffer;	int responseLength = 0;	*handleCountInResponse = 0;	requestBuffer = (char *)malloc(SDP_REQ_BUF_SIZE);	if (!requestBuffer)		return -1;	responseBuffer = (char *)malloc(SDP_RSP_BUF_SIZE);	if (!responseBuffer) {		free(requestBuffer);		return -1;	}	pduRequestHeader = (sdp_hdr_t *)requestBuffer;	pduRequestHeader->pduId = SDP_PDU_SEARCH_REQ;	pdata = (char *)(requestBuffer + sizeof(sdp_hdr_t));	requestSize = sizeof(sdp_hdr_t);	/*	 ** Add service class IDs for search	 */	seqLength = sdp_gen_uuid_seq_pdu(pdata, svcSearchList);	DBPRT("Data seq added : %d\n", seqLength);	/*	 ** Now set the length and increment the pointer	 */	requestSize += seqLength;	pdata += seqLength;	/*	 ** Specify the maximum svc rec count that	 ** client expects	 */	__put_u16(pdata, htons(maxSvcRecordCount));	requestSize += sizeof(uint16_t);	pdata += sizeof(uint16_t);	_requestSize = requestSize;	_pdata = pdata;	*svcResponseList = NULL;	//important	do {		int bytesScanned = 0;		int totalServiceRecordCount, currentServiceRecordCount;		/*		 ** Add continuation state or NULL (first time)		 */		requestSize = _requestSize + sdp_copy_cstate(_pdata, pCState);		/*		 ** Set the request header's param length		 */		pduRequestHeader->paramLength = htons(requestSize - sizeof(sdp_hdr_t));		pduRequestHeader->transactionId = htons(sdp_gen_trans());		/*		 ** Send the request, wait for response and if		 ** not error, set the appropriate values		 ** and return		 */		status = sdp_send_req_w4_rsp(srvHandle, requestBuffer, 				responseBuffer, requestSize, &responseSize);		if (status)			break;		pduResponseHeader = (sdp_hdr_t *)responseBuffer;		if (pduResponseHeader->pduId == SDP_PDU_ERROR_RSP) {			status = pduResponseHeader->data[0];	// ErorrCode			break;		}		responseLength = ntohs(pduResponseHeader->paramLength);		pdata = responseBuffer + sizeof(sdp_hdr_t);		/*		 ** Net service record match count		 */		totalServiceRecordCount = 0;		currentServiceRecordCount = 0;		totalServiceRecordCount = ntohs(__get_u16(pdata));		pdata += sizeof(uint16_t);		bytesScanned += sizeof(uint16_t);		currentServiceRecordCount = ntohs(__get_u16(pdata));		pdata += sizeof(uint16_t);		bytesScanned += sizeof(uint16_t);		DBPRT("Total svc count : %d\n", totalServiceRecordCount);		DBPRT("Current svc count : %d\n", currentServiceRecordCount);		DBPRT("ResponseLength : %d\n", responseLength);		if (currentServiceRecordCount == 0)			break;		status = sdp_extr_svc_handles(pdata, svcResponseList, 				currentServiceRecordCount, &bytesScanned);		if (status)			break;				*handleCountInResponse = currentServiceRecordCount;		/*		 ** Check if we have sdp_cstate_t set, if yes,		 ** set the pCState pointer		 */		DBPRT("BytesScanned : %d\n", bytesScanned);		if (responseLength > bytesScanned) {			uint8_t cStateLength = 0;			pdata = responseBuffer + sizeof(sdp_hdr_t) + bytesScanned;			cStateLength = __get_u8(pdata);			if (cStateLength > 0) {				pCState = (sdp_cs_t *)pdata;				DBPRT("Continuation state present\n");				DBPRT("sdp_cs_t length : %d\n", cStateLength);			} else				pCState = NULL;		}	} while (pCState);		free(requestBuffer);	free(responseBuffer);	//if (concatenatedResponseBuffer.data != NULL)	//free(concatenatedResponseBuffer.data);	return status;}int __sdp_search_req(		struct sockaddr_affix *sa,		slist_t *svcSearchList, 		uint16_t maxSvcRecordCount,		slist_t **svcResponseList,		uint16_t *handleCountInResponse){	int status = 0;	int srvHandle;	srvHandle = sdp_connect(sa);	if (srvHandle < 0)		return srvHandle;	status  = sdp_search_req(srvHandle, svcSearchList, 			maxSvcRecordCount, svcResponseList, handleCountInResponse);	sdp_close(srvHandle);	return status;}/*** This is a service attribute request. **** INPUT :****   uint32_t svcHandle**     The handle of the service for which the attribute(s) are**     requested****   sdp_attrreq_t attrReqType**     Attribute identifiers are 16 bit unsigned integers specified**     in one of 2 ways described below :**     IndividualAttributes - 16bit individual identifiers**        They are the actual attribute identifiers in ascending order****     RangeOfAttributes - 32bit identifier range**        The high-order 16bits is the start of range**        the low-order 16bits are the end of range**        0x0000 to 0xFFFF gets all attributes****   slist_t *attrIDList**     Singly linked list containing attribute identifiers desired.**     Every element is either a uint16_t(attrSpec = IndividualAttributes)  **     or a uint32_t(attrSpec=RangeOfAttributes)****   uint16_t maxAttrIDByteCount**     The byte count of the number of attribute IDs specified**     in the request list**** OUTPUT :**   int return value**     E_OK **       The request completed successfully. This does not**       mean the requested services were found**     E_TIMEOUT **       The request completed unsuccessfully due to a timeout****   uint16_t *maxAttrResponseByteCount**     This is a pointer to a 16 bit integer, which is set to **     indicate the number of bytes of attributes returned. **     This pointer is set on successful return***/int sdp_attr_req(		int srvHandle,		uint32_t svcHandle,		sdp_attrreq_t attrReqType,		slist_t *attrIDList,		uint16_t maxAttrIDByteCount,		sdpsvc_t **_svcRec,		uint16_t *maxAttrResponseByteCount){	int		status = 0;	int 		requestSize = 0, _requestSize;	int 		responseSize = 0;	int 		attrListByteCount = 0;	int 		seqLength = 0;	char 		*pdata = NULL, *_pdata;	char 		*requestBuffer =  NULL;	char 		*responseBuffer =  NULL;	sdp_hdr_t	*pduRequestHeader;	sdp_hdr_t	*pduResponseHeader;	sdp_cs_t	*pCState = NULL;	uint8_t		cStateLength = 0;	sdppdu_t	concatenatedResponseBuffer;	sdpsvc_t	*svcRec = NULL;	*_svcRec = NULL;	*maxAttrResponseByteCount = 0;	if ((attrReqType != IndividualAttributes) && (attrReqType != RangeOfAttributes))		return SDP_ERR_INVALID_ARG;	requestBuffer = (char *)malloc(SDP_REQ_BUF_SIZE);	if (!requestBuffer)		return SDP_ERR_INVALID_ARG;	responseBuffer = (char *)malloc(SDP_RSP_BUF_SIZE);	if (!responseBuffer) {		free(requestBuffer);		return SDP_ERR_INVALID_ARG;	}	memset((char *)&concatenatedResponseBuffer, 0, sizeof(sdppdu_t));	pduRequestHeader = (sdp_hdr_t *)requestBuffer;	pduRequestHeader->pduId = SDP_PDU_ATTR_REQ;	pdata = (char *)(requestBuffer + sizeof(sdp_hdr_t));	requestSize = sizeof(sdp_hdr_t);	/*	 ** Add the service record handle	 */	__put_u32(pdata, htonl(svcHandle));	requestSize += sizeof(uint32_t);	pdata += sizeof(uint32_t);	/*	 ** Add the maxAttrIDByteCount specifying response limit	 */	__put_u16(pdata, htons(maxAttrIDByteCount));	requestSize += sizeof(uint16_t);	pdata += sizeof(uint16_t);	/*	 ** Get attr seq PDU form 	 */	seqLength = sdp_gen_attr_seq_pdu(pdata, attrIDList, 			((attrReqType == IndividualAttributes) ? SDP_DTD_UINT16 : SDP_DTD_UINT32));	if (seqLength < 0) {		status = seqLength;		goto exit;	} 	pdata += seqLength;	requestSize += seqLength;	DBPRT("Attr list length : %d\n", seqLength);	// save before Continuation State	_pdata = pdata;	_requestSize = requestSize;	do {		int responseCount = 0;		/*		 ** Add NULL continuation state		 */		requestSize = _requestSize + sdp_copy_cstate(_pdata, pCState);		/*		 ** Set the request header's param length		 */		pduRequestHeader->transactionId = htons(sdp_gen_trans());		pduRequestHeader->paramLength = htons(requestSize - sizeof(sdp_hdr_t));		status = sdp_send_req_w4_rsp(srvHandle, requestBuffer, 				responseBuffer, requestSize, &responseSize);		if (status)			goto exit;		pduResponseHeader = (sdp_hdr_t *)responseBuffer;		if (pduResponseHeader->pduId == SDP_PDU_ERROR_RSP) {			status = pduResponseHeader->data[0];	// ErrorCode			goto exit;		}		pdata = responseBuffer + sizeof(sdp_hdr_t);		responseCount  = ntohs(__get_u16(pdata));		attrListByteCount += responseCount;		pdata += sizeof(uint16_t);		/*		 ** Check if we have continuation state set, if yes, we		 ** need to re-issue request before we parse ..		 */		cStateLength = __get_u8(pdata + responseCount);		DBPRT("Response id : %d\n", pduResponseHeader->pduId);		DBPRT("Attrlist byte count : %d\n", responseCount);		DBPRT("sdp_cs_t length : %d\n", cStateLength);		/*		 ** This is a split response, need to concatenate the intermediate		 ** responses as well as the last one which will have cStateLength == 0		 */		if ((cStateLength > 0) || (concatenatedResponseBuffer.length != 0)) {			char *targetPtr = NULL;			if (cStateLength > 0)				pCState = (sdp_cs_t *)(pdata + responseCount);			else				pCState = NULL;			/*			 ** Build concatenated response buffer			 */			concatenatedResponseBuffer.data = (char *)realloc(					concatenatedResponseBuffer.data, 					concatenatedResponseBuffer.length + responseCount);			concatenatedResponseBuffer.size = 				concatenatedResponseBuffer.length + responseCount;			targetPtr = concatenatedResponseBuffer.data + 				concatenatedResponseBuffer.length;			memcpy(targetPtr, pdata, responseCount);			concatenatedResponseBuffer.length += responseCount;		}	} while (pCState);	if (attrListByteCount > 0) {		int bytesScanned = 0;		if (concatenatedResponseBuffer.length != 0) {			pdata = concatenatedResponseBuffer.data;		}		svcRec = sdp_clt_extr_pdu(pdata, svcHandle, &bytesScanned);		DBPRT("In sdp_attr_req function \n");		DBPRT("The status of extractServiceRecord is %d\n", status);		DBPRT("The svcHandle is 0x%x\n", svcHandle);		if (!svcRec) {			status = -1;			goto exit;		}		*_svcRec = svcRec;		*maxAttrResponseByteCount = bytesScanned;	}exit:	free(requestBuffer);	free(responseBuffer);	if (concatenatedResponseBuffer.data != NULL)		free(concatenatedResponseBuffer.data);	return status;}int __sdp_attr_req(		struct sockaddr_affix *sa,		uint32_t svcHandle,		sdp_attrreq_t attrReqType,		slist_t *attrIDList,		uint16_t maxAttrIDByteCount,		sdpsvc_t	**svcRec,		uint16_t *maxAttrResponseByteCount){	int status = 0;	int srvHandle;	srvHandle = sdp_connect(sa);	if (srvHandle < 0)		return srvHandle;	status = sdp_attr_req(srvHandle, svcHandle, attrReqType,			attrIDList, maxAttrIDByteCount, svcRec, maxAttrResponseByteCount);	sdp_close(srvHandle);	return status;}/*** This is a service search request combined with the service** attribute request. First a service class match is done and** for matching service, requested attributes are extracted**** INPUT :****   slist_t *svcSearchList**     Singly linked list containing elements of the search**     pattern. Each entry in the list is a uuid_t(DataTypeSDP_DTD_UUID16)**     of the service to be searched****   AttributeSpecification attrSpec**     Attribute identifiers are 16 bit unsigned integers specified**     in one of 2 ways described below :**     IndividualAttributes - 16bit individual identifiers**        They are the actual attribute identifiers in ascending order****     RangeOfAttributes - 32bit identifier range**        The high-order 16bits is the start of range**        the low-order 16bits are the end of range**        0x0000 to 0xFFFF gets all attributes****   slist_t *attrIDList**     Singly linked list containing attribute identifiers desired.**     Every element is either a uint16_t(attrSpec = IndividualAttributes)  **     or a uint32_t(attrSpec=RangeOfAttributes)****   uint16_t maxAttrIDByteCount**     The byte count of the number of attribute IDs specified**     in the request list**** OUTPUT :**   int return value**     E_OK **       The request completed successfully. This does not**       mean the requested services were found**     E_TIMEOUT **       The request completed unsuccessfully due to a timeout****   slist_t **svcResponseList**     This variable is set on a successful return to point to**     service(s) found. Each element of this list is of type**     uint32_t (of the services which matched the search list)****   uint16_t *maxAttrResponseByteCount**     This is a pointer to a 16 bit integer, which is set to **     indicate the number of bytes of attributes returned. **     This pointer is set on successful return***/int sdp_search_attr_req(		int srvHandle,		slist_t *svcSearchList, 		sdp_attrreq_t attrReqType,		slist_t *attrIDList,		uint16_t maxAttrByteCount,		slist_t **svcResponseList,		uint16_t *maxAttrResponseByteCount		){	int status = 0;	int requestSize = 0, _requestSize;	int responseSize = 0;	int seqLength = 0;	int attrListByteCount = 0;	char *pdata = NULL, *_pdata;	char *requestBuffer =  NULL;	char *responseBuffer =  NULL;	sdp_hdr_t *pduRequestHeader;	sdp_hdr_t *pduResponseHeader;	uint8_t dataType;	slist_t *svcRecHandleList = NULL;	sdppdu_t concatenatedResponseBuffer;	sdp_cs_t	*pCState = NULL;	int bytesScanned = 0;	*maxAttrResponseByteCount = 0;	if ((attrReqType != IndividualAttributes) && (attrReqType != RangeOfAttributes))		return SDP_ERR_INVALID_ARG;		requestBuffer = (char *)malloc(SDP_REQ_BUF_SIZE);	if (!requestBuffer)		return -1;	responseBuffer = (char *)malloc(SDP_RSP_BUF_SIZE);	if (!responseBuffer) {		free(requestBuffer);		return -1;	}	memset((char *)&concatenatedResponseBuffer, 0, sizeof(sdppdu_t));	pduRequestHeader = (sdp_hdr_t *)requestBuffer;	pduRequestHeader->pduId = SDP_PDU_SEARCH_ATTR_REQ;	// generate PDU

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -