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

📄 request.c

📁 Affix - Bluetooth Protocol Stack for Linux has been developed at Nokia Research Center in Helsinki
💻 C
📖 第 1 页 / 共 3 页
字号:
/*    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: request.c,v 1.50 2003/11/13 19:23:16 litos Exp $   Contains the SDP service discovery client request handling code.   Fixes:   		Dmitry Kasatkin		- Continuation mechanism, MTU support*/#include <affix/config.h>#include <sys/types.h>#include <stdio.h>#include <stdlib.h>#include <stdint.h>#include <string.h>#include <affix/sdp.h>#include <affix/sdpclt.h>#include <affix/sdpsrv.h>#include "servicedb.h"#include "utils.h"#include "attr.h"#include "cstate.h"extern void sdp_update_time(void);extern slist_t	*serviceList;/* ** Search/Attribute element sequence extractor. Builds ** a slist_t whose elements are those found in the  ** sequence. The data type of elements found in the ** sequence (now populated in slist_t) is returned ** in the reference pDataType */int sdp_extr_data_seq(char *pduBuffer, slist_t **svcReqSeq, uint8_t *pDataType){	int	status, bytesScanned;	char	*pdata;	uint8_t	seqType;	int 	length = 0;	short	numberOfElements;	int	seqLength;	slist_t	*pSeq;	uint8_t	dataType;	bytesScanned = 0;	pdata = sdp_extr_seq_dtd(pduBuffer, &seqType, &length, &bytesScanned);	DBPRT("Seq type : %d", seqType);	if (!pdata || (SDP_DTD_TYPE(seqType) != SDP_DTD_SEQ)) {		BTERROR("Unknown seq type");		return -1;	}	DBPRT("Data size : %d", length);	numberOfElements = 0;	seqLength = 0; 	pSeq = NULL;	for (;;) {		char	*pElem = NULL;		int	localSeqLength = 0;		dataType = __get_u8(pdata);		DBPRT("Data type : %d", dataType);		switch (dataType) {			case SDP_DTD_UINT16 :				pdata += sizeof(uint8_t);				seqLength += sizeof(uint8_t);				pElem = (char *)malloc(sizeof(uint16_t));				if (!pElem)					break;				*(uint16_t *)pElem = ntohs(__get_u16(pdata));				pdata += sizeof(uint16_t);				seqLength += sizeof(uint16_t);				break;			case SDP_DTD_UINT32 :				pdata += sizeof(uint8_t);				seqLength += sizeof(uint8_t);				pElem = (char *)malloc(sizeof(uint32_t));				if (!pElem)					break;				*(uint32_t *)pElem = ntohl(__get_u32(pdata));				pdata += sizeof(uint32_t);				seqLength += sizeof(uint32_t);				break;			case SDP_DTD_UUID16 :			case SDP_DTD_UUID32 :			case SDP_DTD_UUID128 :				pElem = (char *)malloc(sizeof(uuid_t));				if (!pElem)					break;				status = __sdp_extr_uuid(pdata, (uuid_t *)pElem, &localSeqLength);				if (status) {					free(pElem);					return status;				}				seqLength += localSeqLength;				pdata += localSeqLength;				break;		}		if (!pElem)			continue;		s_list_append(&pSeq, pElem);		numberOfElements++;		DBPRT("No of elements : %d", numberOfElements);		if (seqLength == length)			break;		else if (seqLength > length)			return -1;	}	*svcReqSeq = pSeq;	bytesScanned += seqLength;	*pDataType = dataType;	return bytesScanned;}/* ** Service search request PDU. This methods extracts the "search pattern" ** which is a seqquence of UUIDs calls the matching function ** to find matching services */int _sdp_search_req(sdp_request_t *requestPdu, sdppdu_t *pdu){	int		status = 0, i;	char		*pdata;	int		bytesScanned = 0;	slist_t		*searchPattern = NULL;	int		maxExpectedServiceRecordCount, realServiceRecordCount;	uint8_t		dataType;	sdp_cstate_t	*pCState = NULL;	char		*pCacheBuffer = NULL;	int		handleSize = 0;	long		cStateId = -1;	short		responseCount = 0;	short		*pTotalRecordCount;	short		*pCurrentRecordCount;	int		MTU;	pdata = requestPdu->data + sizeof(sdp_hdr_t);	bytesScanned = sdp_extr_data_seq(pdata, &searchPattern, &dataType);	if ((bytesScanned < 0) || ((bytesScanned + sizeof(uint16_t) + sizeof(uint8_t) + sizeof(sdp_hdr_t)) > requestPdu->len)){ 		status = SDP_ERR_REQUEST_SYNTAX;		goto exit;	}	pdata += bytesScanned;	maxExpectedServiceRecordCount = ntohs(__get_u16(pdata));	DBPRT("Expected count: %d", maxExpectedServiceRecordCount);	DBPRT("Bytes scanned : %d", bytesScanned);	pdata += sizeof(uint16_t);	//bytesScanned += sizeof(uint16_t); //Fix	/*	 ** Check if continuation state exists, if yes attempt	 ** to get response remainder from cache, else send error	 */	pCState = sdp_get_cstate(pdata);	if ((pCState) && ((pCState->length + bytesScanned + sizeof(uint16_t) + sizeof(sdp_hdr_t)) > requestPdu->len)){		status = SDP_ERR_REQUEST_SYNTAX;		goto exit;	}		MTU = requestPdu->mtu - sizeof(sdp_hdr_t) - sizeof(uint16_t) - sizeof(uint16_t) - sizeof(sdp_cstate_t);	realServiceRecordCount = btmin(maxExpectedServiceRecordCount, (MTU >> 2));	DBPRT("MTU: %d, realrec: %d", MTU, realServiceRecordCount);	/*	 ** Make space in the response buffer for total	 ** and current record counts	 */	pdata = pdu->data;	/*	 ** Total service record count = 0	 */	pTotalRecordCount = (short *)pdata;	__put_u16(pdata, 0);	pdata += sizeof(uint16_t);	pdu->length += sizeof(uint16_t);	/*	 ** current service record count = 0	 */	pCurrentRecordCount = (short *)pdata;	__put_u16(pdata, 0);	pdata += sizeof(uint16_t);	pdu->length += sizeof(uint16_t);	if (pCState == NULL) {		/*		 ** For every element in the sdpsvc_t DB,		 ** do a pattern search		 */		int index = 0;		handleSize = 0;		for (;;) {			void * data;			sdpsvc_t *svcRec;			data = s_list_nth_data(serviceList, index);			if (data != NULL) {				svcRec = (sdpsvc_t *)data;				DBPRT("Checking svcRec : 0x%x", svcRec->serviceRecordHandle);				if (sdp_match_uuid(searchPattern, svcRec->targetPattern)) {					responseCount++; 					__put_u32(pdata, htonl(svcRec->serviceRecordHandle));					pdata += sizeof(uint32_t);					handleSize += sizeof(uint32_t);				}				index++;			} else				break;		}		DBPRT("Match count : %d", responseCount);		/*		 ** Add "handleSize" to pdu buffer size		 */		pdu->length += handleSize;		__put_u16(pTotalRecordCount,  htons(responseCount));		__put_u16(pCurrentRecordCount, htons(responseCount));		if (responseCount > realServiceRecordCount) {			/* 			 ** We need to cache the response and generate a 			 ** continuation state 			 */			cStateId = sdp_add_rsp_cscache(requestPdu->fd, pdu);			/*			 ** Subtract the handleSize since we now send only			 ** a subset of handles			 */			pdu->length -= handleSize;		} else {			/*			 ** NULL continuation state			 */			sdp_set_cstate(pdu, NULL);		}	}	/*	 ** Under both the conditions below, the response buffer is not	 ** built up yet	 */	if ((pCState != NULL) || (cStateId != -1)) {		short lastIndex = 0;		if (pCState != NULL) {			sdppdu_t *pCache;			/*			 ** Get the previous sdp_cstate_t and obtain			 ** the cached response			 */			pCache = sdp_get_rsp_cscache(requestPdu->fd, pCState);			if (!pCache) {				status = -1;				goto exit;			}			pCacheBuffer = pCache->data;			responseCount = ntohs(__get_u16(pCacheBuffer));			/*			 ** Get the index of the last sdpsvc_t sent			 */			lastIndex = pCState->value.lastIndexSent;		} else {			pCacheBuffer = pdu->data;			lastIndex = 0;		}		/*		 ** Set the local buffer pointer to beyond the		 ** current record count. And increment the cached		 ** buffer pointer to beyond the counters ..		 */		pdata = (char *)pCurrentRecordCount + sizeof(uint16_t);		/*		 ** There is the toatalCount and the currentCount 		 ** fields to increment beyond		 */		pCacheBuffer += (2 * sizeof(uint16_t));		if (pCState == NULL) {			handleSize = realServiceRecordCount << 2; //sizeof(uint32_t); 			i = realServiceRecordCount;		} else {			handleSize = 0;			for (i = lastIndex; (i-lastIndex) < realServiceRecordCount &&					i < responseCount; i++) {				__put_u32(pdata, __get_u32(((uint32_t*)pCacheBuffer) + i));				pdata += sizeof(uint32_t);				handleSize += sizeof(uint32_t);			}		}		/*		 ** Add "handleSize" to pdu buffer size		 */		pdu->length += handleSize;		__put_u16(pTotalRecordCount,  htons(responseCount));		__put_u16(pCurrentRecordCount, htons(i-lastIndex));		if (i == responseCount) {			/*			 ** Set "null" continuationState & and remove it from cache			 */			sdp_set_cstate(pdu, NULL);			sdp_del_rsp_cscache(requestPdu->fd, pCState);		} else {			/*			 ** There is more to it .. set the lastIndexSent to			 ** the new value and move on ..			 */			sdp_cstate_t newState;			DBPRT("Setting non-NULL sdp_cs_t");			memset(&newState, 0, sizeof(sdp_cstate_t));			if (pCState != NULL) {				memcpy(&newState, pCState, sizeof(sdp_cstate_t));				newState.value.lastIndexSent = i;			} else {				newState.timestamp = cStateId;				newState.value.lastIndexSent = i;			}			sdp_set_cstate(pdu, &newState);		}	}exit:	if (searchPattern)		s_list_destroy(&searchPattern);	return status;}/* ** This function generates the PDU form of a service record for ** a specified set of attributes and not the entire set. This is ** driven by a service discovery client which asks for attributes ** of a service record by speicifying a subset of attribute  ** identifiers */void sdp_gen_svc_pdu_by_attr(sdpsvc_t *svcRec, uint16_t attrId, sdppdu_t *attrSubsetPDUForm){	sdpdata_t *pData;	pData = (sdpdata_t*)sdp_get_attr(svcRec, attrId);	if (!pData || !pData->pdu.data || !pData->pdu.length)		return;	sdp_append_pdu(attrSubsetPDUForm, &pData->pdu);}/* ** Extract attribute identifiers from the request PDU. ** Clients could request a subset of attributes (by id) ** from a service record, instead of the whole set. The ** requested identifiers are present in the PDU form of ** the request */

⌨️ 快捷键说明

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