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

📄 sdp_parser.c

📁 bluetooth 驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * sdp_parser.c -- This file describes a parser that parses incomming *                 bluetooth sdp data and sends it to the sdp_server * * Copyright (C) 2000, 2001  Axis Communications AB * * Author: Mats Friden <mats.friden@axis.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. * * Exceptionally, Axis Communications AB grants discretionary and * conditional permissions for additional use of the text contained * in the company's release of the AXIS OpenBT Stack under the * provisions set forth hereunder. * * Provided that, if you use the AXIS OpenBT Stack with other files, * that do not implement functionality as specified in the Bluetooth * System specification, to produce an executable, this does not by * itself cause the resulting executable to be covered by the GNU * General Public License. Your use of that executable is in no way * restricted on account of using the AXIS OpenBT Stack code with it. * * This exception does not however invalidate any other reasons why * the executable file might be covered by the provisions of the GNU * General Public License. * * $Id: sdp_parser.c,v 1.21 2001/08/27 15:08:58 mattiasagren Exp $ * *//****************** INCLUDE FILES SECTION ***********************************/#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <string.h>#include <sys/time.h>#include <syslog.h>#include <unistd.h>#include <sys/socket.h>#include <sys/un.h>#include <sys/ioctl.h>#include <sys/uio.h>#include "sdp_server.h"#include "sdp_parser.h"/****************** CONSTANT AND MACRO SECTION ******************************/#define SDP_DEBUG_XMIT       0#define SDP_DEBUG_REC        0#define SDP_DEBUG_MISC       0#define SDP_DEBUG_MEM        0#define SDP_DEBUG_PROC       0#define SDP_DEBUG_PRINT_DATA 0#ifdef BTD_USERSTACK#define syslog(x, fmt...) do { fprintf(stderr, __FILE__ "::"); fprintf(stderr, fmt); fprintf(stderr, "\n"); } while (0)#endif#if SDP_DEBUG_XMIT#define D_XMIT(fmt...) syslog(LOG_INFO, __FUNCTION__ ": " fmt)#else#define D_XMIT(fmt...)#endif#if SDP_DEBUG_REC#define D_REC(fmt...) syslog(LOG_INFO, __FUNCTION__ ": " fmt)#else#define D_REC(fmt...)#endif#if SDP_DEBUG_MISC#define D_MISC(fmt...) syslog(LOG_INFO, __FUNCTION__ ": " fmt)#else#define D_MISC(fmt...)#endif#if SDP_DEBUG_MEM#define D_MEM(fmt...) syslog(LOG_INFO, __FUNCTION__ ": " fmt)#else#define D_MEM(fmt...)#endif#if SDP_DEBUG_PROC#define D_PROC(fmt...) syslog(LOG_INFO, __FUNCTION__ ": " fmt)#else#define D_PROC(fmt...)#endif#if SDP_DEBUG_PRINT_DATA#define PRINT_DATA(str, data, len) print_data(str, data, len)#else#define PRINT_DATA(str, data, len)#endif#define D_ERR(fmt...) do { fprintf(stderr, __FUNCTION__ ": ERROR: " fmt); fprintf(stderr, "\n"); } while (0)#define GET_TYPE(ch) (((ch) >> 3) & 0x1f)#define GET_SIZE(ch) ((ch) & 0x7)#define SET_DE_HDR(type, size) ((((type) << 3) & 0xf8) + ((size) & 0x7))#define SDP_HDR_SIZE 5/* The size of the SDP packet header */#define DES_TYPE 0x6#define DES_HDR_LEN 2#define UUID16_HDR 0x19#define UUID32_HDR 0x1a#define UUID128_HDR 0x1c/****************** TYPE DEFINITION SECTION *********************************//****************** LOCAL FUNCTION DECLARATION SECTION **********************/void sdp_parse_data(unsigned char* data, unsigned int len);void process_service_search_req(database_query_struct *db, unsigned char *data,                                unsigned short len);void process_service_attr_req(database_query_struct *db, unsigned char *data,                              unsigned short len);void process_service_search_attr_req(database_query_struct *db,				     unsigned char *data, unsigned short len);void process_service_search_rsp(int sdp_con_id, unsigned char *data);void process_service_attr_rsp(int sdp_con_id, unsigned char *data);void process_service_search_attr_rsp(int sdp_con_id, unsigned char *data);int get_size(unsigned char *data, unsigned int *new_pos);/****************** GLOBAL VARIABLE DECLARATION SECTION *********************//****************** LOCAL VARIABLE DECLARATION SECTION **********************/static int stack_if_fd;int malloc_dbg = 0;/* pointers to contionuationstate data */cont_state_struct *cont_state_buf = NULL;/****************** FUNCTION DEFINITION SECTION *****************************/void sdp_parse_data(unsigned char* data, unsigned int len){  database_query_struct db;  unsigned char id;  unsigned short par_len;  unsigned int pkt_len;  data_struct *db_hdl;  D_REC("%d bytes",len);  PRINT_DATA(__FUNCTION__, data, len);  db_hdl = (data_struct*)data;  data += sizeof(*db_hdl);  len -= sizeof(*db_hdl);  db.sdp_con_id = db_hdl->sdp_con_id;  db.l2cap_mtu = db_hdl->l2cap_mtu;  pkt_len = db_hdl->len;  id = data[SDP_HDR_TYPE];  db.trans_id = CHAR2INT16(data[SDP_HDR_TRANS_ID_MS], data[SDP_HDR_TRANS_ID_LS]);  par_len = CHAR2INT16(data[SDP_HDR_LENGTH_MS], data[SDP_HDR_LENGTH_LS]);  data += SDP_HDR_SIZE;  if (par_len > (len - SDP_HDR_SIZE))  {    D_XMIT("Packet length (%d) does not match received data length (%d)",           len - SDP_HDR_SIZE, par_len);    send_error_rsp(&db, SDP_INVALID_PDU_SIZE);    return;  }  D_REC("id: 0x%x, trans_id: 0x%x, par_len: %d", id, db.trans_id, par_len);  switch (id)  {  case SDP_ERROR_RSP:    switch (CHAR2INT16(data[0], data[1]))    {    case SDP_INVALID_SDP_VERSION:      D_ERR("Got Invalid/unsupported SDP version");      break;    case SDP_INVALID_SERVICE_RECORD_HANDLE:      D_ERR("Got Invalid Service Record Handle");      break;    case SDP_INVALID_REQUEST_SYNTAX:      D_ERR("Got Invalid Request Syntax");      break;    case SDP_INVALID_PDU_SIZE:      D_ERR("Got Invalid PDU Size");      break;    case SDP_INVALID_CONTINUATION_STATE:      D_ERR("Got Invalid Continuation State");      break;    case SDP_INSUFFICIENT_RESOURCES:      D_ERR("Got Insufficient Resources to satisfy Request");      break;    default:      D_ERR("Error code 0x%04x is not specified",            CHAR2INT16(data[0], data[1]));      break;    }    break;  case SDP_SERVICESEARCH_REQ:    D_REC("SDP_SERVICESEARCH_REQ %d bytes", par_len);    process_service_search_req(&db, data, par_len);    break;      case SDP_SERVICESEARCH_RSP:    D_REC("SDP_SERVICESEARCH_RSP");    process_service_search_rsp(db.sdp_con_id, data);    break;      case SDP_SERVICEATTR_REQ:    D_REC("SDP_SERVICEATTR_REQ");    process_service_attr_req(&db, data, par_len);    break;      case SDP_SERVICEATTR_RSP:    D_REC("SDP_SERVICEATTR_RSP");    process_service_attr_rsp(db.sdp_con_id, data);    break;      case SDP_SERVICESEARCHATTR_REQ:    D_REC("SDP_SERVICESEARCHATTR_REQ");    process_service_search_attr_req(&db, data, par_len);    break;      case SDP_SERVICESEARCHATTR_RSP:    D_REC("SDP_SERVICESEARCHATTR_RSP");    process_service_search_attr_rsp(db.sdp_con_id, data);    break;      default:    D_REC("ERROR Invalid pdu type");    /* Send an error response with error code Invalid request syntax */    send_error_rsp(&db, SDP_INVALID_REQUEST_SYNTAX);    break;  }}voidprocess_service_search_req(database_query_struct *db, unsigned char *data, unsigned short len){  unsigned int service_search_uuid[12];  int service_search_uuid_cnt;  unsigned char des_len;  int tmp_pos, i, cur_pos = 0;  int max_rec_cnt;  int new_pos[1];  int cont_state_len;  D_REC("Got %d bytes", len);  if (GET_TYPE(data[cur_pos]) != DES_TYPE)  {    D_REC("Incorrect packet: Data Element Sequence expected");    /* Send an error msg with error code Invalid request syntax */    send_error_rsp(db, SDP_INVALID_REQUEST_SYNTAX);    return;  }  des_len = get_size(data + cur_pos, new_pos);  cur_pos += *new_pos;  D_MISC("des_len: %d, new_pos: %d", des_len, *new_pos);  if (des_len > (len - DES_HDR_LEN))  {    D_REC("Incorrect packet: Incorrect length field or whole packet was not received");    /* Send an error msg with error code Invalid request syntax */    send_error_rsp(db, SDP_INVALID_REQUEST_SYNTAX);    return;  }  tmp_pos = 0;  i = 0;  while (tmp_pos < des_len)  {    if (i >= 12)    {      D_REC("More than 12 UUID in one request");      /* Send an error msg with error code Invalid request syntax */      send_error_rsp(db, SDP_INVALID_REQUEST_SYNTAX);      break;    }    if (data[cur_pos] == UUID16_HDR)    {      service_search_uuid[i] = CHAR2INT16(data[cur_pos + 1],                                          data[cur_pos + 2]);      D_MISC("Found UUID16 0x%04x", service_search_uuid[i]);       i++;      tmp_pos += 3;      cur_pos += 3;    }    else if (data[cur_pos] == UUID32_HDR)    {      cur_pos += 2;      service_search_uuid[i] = CHAR2INT16(data[cur_pos + 1],                                          data[cur_pos + 2]);      D_MISC("Found UUID32 0x%08x", service_search_uuid[i]);       i++;      tmp_pos += 5;      cur_pos += 3;    }    else if (data[cur_pos] == UUID128_HDR)    {      cur_pos += 2;      service_search_uuid[i] = CHAR2INT16(data[cur_pos + 1],                                          data[cur_pos + 2]);      D_MISC("Found UUID128 0x%08x", service_search_uuid[i]);      i++;      tmp_pos += 17;      cur_pos += 15;    }    else    {      D_REC("Unknown UUID size 0x%02x", data[cur_pos]);      /* Send an error msg with error code Invalid request syntax */      send_error_rsp(db, SDP_INVALID_REQUEST_SYNTAX);      return;    }  }  service_search_uuid_cnt = i;  max_rec_cnt = CHAR2INT16(data[cur_pos], data[cur_pos + 1]);  D_MISC("max_rec_cnt: %d", max_rec_cnt);  cur_pos += 2;  cont_state_len = data[cur_pos++];  if (len < cur_pos)  {    D_ERR("Packet length (%d) shorter than actual packet length (%d)", len, cur_pos);    send_error_rsp(db, SDP_INVALID_PDU_SIZE);    return;  }  else if (len > cur_pos)  {    D_ERR("Packet length (%d) longer than actual packet length (%d)", len, cur_pos);    send_error_rsp(db, SDP_INVALID_PDU_SIZE);    return;  }    if (cont_state_len)  {    cur_pos += data[cur_pos];        D_MISC("Sending continuationstate packet");    send_cont_state_search_rsp(cont_state_len, data + cur_pos, max_rec_cnt,db);  }  else  {    service_search_struct db_hdl;    db->pkt_type = SDP_SERVICESEARCH_REQ;    memcpy(&db_hdl.db, db, sizeof(database_query_struct));    db_hdl.max_rec_cnt = max_rec_cnt;    db_hdl.service_class_cnt = service_search_uuid_cnt;    memcpy(db_hdl.service_class_list, service_search_uuid,           service_search_uuid_cnt * sizeof(*service_search_uuid));    /* Here we ask the database for the requested attributes */    handle_query(&db_hdl.db);  }}void process_service_attr_req(database_query_struct *db, unsigned char *data, unsigned short len){  service_attr_struct *db_hdl;  int tmp_len, cur_pos = 0;  unsigned char des_len;  unsigned int rec_hdl;  unsigned int max_attr_cnt;  unsigned int attr_list[256];  int attr_list_pos = 0;  int cont_state_len;    int new_pos[1];  D_REC("Got %d bytes", len);  rec_hdl = CHAR2INT32(data[cur_pos], data[cur_pos + 1],                       data[cur_pos  + 2], data[cur_pos + 3]);  D_MISC("rec_hdl: 0x%08x", rec_hdl);  cur_pos += 4;  max_attr_cnt = CHAR2INT16(data[cur_pos], data[cur_pos + 1]);  D_MISC("max_attr_cnt: %d", max_attr_cnt);  cur_pos += 2;  if (GET_TYPE(data[cur_pos]) != DES_TYPE)  {    D_REC("Incorrect packet: Data Element Sequence expected");    /* Send an error msg with error code Invalid request syntax */    send_error_rsp(db, SDP_INVALID_REQUEST_SYNTAX);    return;  }  des_len = get_size(data + cur_pos, new_pos);  cur_pos += *new_pos;  D_MISC("des_len: %d, new_pos: %d", des_len, *new_pos);  if (des_len > (len - DES_HDR_LEN))  {    D_REC("Incorrect packet: Incorrect length field or whole packet was not received");    /* Send an error msg with error code Invalid request syntax */    send_error_rsp(db, SDP_INVALID_REQUEST_SYNTAX);    return;  }  /* Now we parses the third parameter which is a data element list. i.e     we have to go through the whole list and pick out one element at     time */  while (des_len > 0)  {    /* Get the length of the data element */    tmp_len = get_size(data + cur_pos, new_pos);    D_MISC("tmp_len: %d, new_pos: %d", tmp_len, *new_pos);    /* Move the data pointer past the length field to the start of       the data element */    cur_pos += *new_pos;    if (tmp_len == 4)    {      /* Now we got a range of attributes */      attr_list[attr_list_pos] = CHAR2INT32(data[cur_pos], data[cur_pos + 1], data[cur_pos  + 2], data[cur_pos + 3]);      D_MISC("Found range of attributes: 0x%08x", attr_list[attr_list_pos]);       cur_pos += 4;      attr_list_pos++;    }    else    {      /* Just a single attributes */      attr_list[attr_list_pos] = CHAR2INT16(data[cur_pos], data[cur_pos + 1]);      /* We stor all attributes as ranges */      attr_list[attr_list_pos] |= attr_list[attr_list_pos] << 16;      D_MISC("Found single attributes: 0x%04x", attr_list[attr_list_pos]);       cur_pos += 2;      attr_list_pos++;    }    des_len -= (*new_pos + tmp_len);  }  cont_state_len = data[cur_pos++];  cur_pos += cont_state_len;  if (len < cur_pos)

⌨️ 快捷键说明

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