class library to access fischertechnik interfaces via USB

Dependencies:   FatFileSystem mbed myBlueUSB neigbourhood rfcomm sdp

Committer:
networker
Date:
Wed Jun 15 19:12:25 2011 +0000
Revision:
0:7da612835693
initial version
; Bluetooth support incomplete

Who changed what in which revision?

UserRevisionLine numberNew contents of line
networker 0:7da612835693 1 #include "mbed.h"
networker 0:7da612835693 2 #include "Utils.h"
networker 0:7da612835693 3 #include "hci.h"
networker 0:7da612835693 4 #include "sdp_data.h"
networker 0:7da612835693 5 #include "sdp.h"
networker 0:7da612835693 6
networker 0:7da612835693 7 SDPManager SDP; //instance
networker 0:7da612835693 8 const unsigned char base_uuid[16] = { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0, 0x07, 0x70, 0, 0x10, 0, 0};
networker 0:7da612835693 9 map<unsigned, serv_rec*> SDPManager::server;
networker 0:7da612835693 10 int SDPManager::serverSock = 0;
networker 0:7da612835693 11
networker 0:7da612835693 12 void attribHandler(serv_rec *r) {
networker 0:7da612835693 13 printf("Service 0x%08X\n", (*r)[0x0000]->asUnsigned());
networker 0:7da612835693 14 map<unsigned short, sdp_data*>::iterator it = r->begin();
networker 0:7da612835693 15 for (;it != r->end();it++) {
networker 0:7da612835693 16 printf(" 0x%04X: %s\n", (*it).first, (*it).second->asString());
networker 0:7da612835693 17 }
networker 0:7da612835693 18 }
networker 0:7da612835693 19
networker 0:7da612835693 20 #define BROWSEROOT 0x1002
networker 0:7da612835693 21 #define SERIALSERV 0x1101
networker 0:7da612835693 22
networker 0:7da612835693 23 SDPHandler::SDPHandler(): txid(1), tree(0) {
networker 0:7da612835693 24 ErrorResponse=errorhandler;
networker 0:7da612835693 25 ServiceSearchResponse=0;
networker 0:7da612835693 26 ServiceAttributeResponse=attribHandler;
networker 0:7da612835693 27 ServiceSearchAttributeResponse=0;
networker 0:7da612835693 28 buf = l2cap_buf+OFFSET;
networker 0:7da612835693 29 contBuf = 0;
networker 0:7da612835693 30 byteCount = 0;
networker 0:7da612835693 31 contState[0] = 0;
networker 0:7da612835693 32 _state = 0;
networker 0:7da612835693 33 }
networker 0:7da612835693 34
networker 0:7da612835693 35 void SDPHandler::Clear() {
networker 0:7da612835693 36 for (index = services.begin(); index != services.end(); index++) {//for all services
networker 0:7da612835693 37 for (serv_rec::iterator it = index->second->begin(); it != index->second->end(); it++)//for all attributes
networker 0:7da612835693 38 delete it->second; //delete the attribute value tree
networker 0:7da612835693 39 delete (*index).second; //delete the attribute list
networker 0:7da612835693 40 }
networker 0:7da612835693 41 services.clear();//and empty the services list
networker 0:7da612835693 42 }
networker 0:7da612835693 43
networker 0:7da612835693 44 //Called as: Socket_Open(SOCKET_SDP, addr, callback, userdata(this)) from SDPManager
networker 0:7da612835693 45 //never called
networker 0:7da612835693 46 int SDPHandler::Open(SocketInternal* sock, SocketAddrHdr* addr) {
networker 0:7da612835693 47 printf("Successfully opened SDP socket %d\n", sock->ID);
networker 0:7da612835693 48 sock->SetState(SocketState_Open);
networker 0:7da612835693 49 sdp_socket = sock->ID;
networker 0:7da612835693 50 return sdp_socket;
networker 0:7da612835693 51 }
networker 0:7da612835693 52
networker 0:7da612835693 53 int SDPHandler::Send(SocketInternal* sock, const u8* data, int len) {
networker 0:7da612835693 54 printf("SDPHandler::Send should not be called directly\n");
networker 0:7da612835693 55 // return Socket_Send(_l2cap, data, len);
networker 0:7da612835693 56 BTDevice *l2cap = (BTDevice*)sock->userData;
networker 0:7da612835693 57 return l2cap->Send(sock, data, len);
networker 0:7da612835693 58 }
networker 0:7da612835693 59
networker 0:7da612835693 60 int SDPHandler::Close(SocketInternal* sock) {
networker 0:7da612835693 61 printf("SDPHandler::Close(%d)\n", sock->ID);
networker 0:7da612835693 62 Clear();
networker 0:7da612835693 63 // printf("SDP socket %d and L2CAP socket %d closed, freemem=%d\n", sock->ID, _l2cap, AvailableMemory(1));
networker 0:7da612835693 64 int retval = 0;//Socket_Close(_l2cap);//could also keep it open for the next connection
networker 0:7da612835693 65 return retval;
networker 0:7da612835693 66 }
networker 0:7da612835693 67
networker 0:7da612835693 68 //this function is called when the L2CAP layer receives SDP packets (see SDPHandler::Open), userdata is the sdpmanager instance
networker 0:7da612835693 69 void SDPHandler::OnSdpRsp(int socket, SocketState state, const u8* data, int len, void* userData) {
networker 0:7da612835693 70 printf("\x1B[%dm", 35);
networker 0:7da612835693 71 // printf("OnSdpRsp(socket=%d, state=%d, len=%d)\n", socket, state, len);
networker 0:7da612835693 72 printf("SDPHandler::OnSdpRsp(socket=%d, state=%d, len=%d, freemem=%d\n", socket, state, len, AvailableMemory(1));
networker 0:7da612835693 73 SDPHandler *self = (SDPHandler*)userData;
networker 0:7da612835693 74 if (state == SocketState_Open) {
networker 0:7da612835693 75 self->sdp_socket = socket;
networker 0:7da612835693 76 self->OnSdpRsp(data, len);
networker 0:7da612835693 77 } else if (state == SocketState_Closed) {
networker 0:7da612835693 78 SDP.Destroy(socket);
networker 0:7da612835693 79 }
networker 0:7da612835693 80 printf("\x1B[%dm", 0);
networker 0:7da612835693 81 }
networker 0:7da612835693 82
networker 0:7da612835693 83 //this function is called when the L2CAP layer receives SDP packets (see SDPHandler::Open), userdata is the sdpmanager instance
networker 0:7da612835693 84 //void SDPHandler::OnSdpRsp(int socket, SocketState state, const u8* data, int len, void* userData) {
networker 0:7da612835693 85 void SDPHandler::OnSdpRsp(const u8* data, int len) {
networker 0:7da612835693 86 static sdp_data list(sdp_data::SEQUENCE);
networker 0:7da612835693 87 static sdp_data all(0x0000ffffU,4);
networker 0:7da612835693 88 static sdp_data serviceID(0U, 2);
networker 0:7da612835693 89 static sdp_data name(0x100U, 2);
networker 0:7da612835693 90 static sdp_data root(sdp_data::UUID, BROWSEROOT);
networker 0:7da612835693 91 static sdp_data req(sdp_data::SEQUENCE);
networker 0:7da612835693 92 static bool once = true;
networker 0:7da612835693 93 // printf("_state=%d first=%d ", _state, once);
networker 0:7da612835693 94 if (once) {
networker 0:7da612835693 95 list.add_element(&all);
networker 0:7da612835693 96 //list.add_element(&serviceID);
networker 0:7da612835693 97 //list.add_element(&name);
networker 0:7da612835693 98 req.add_element(&root);
networker 0:7da612835693 99 once = false;
networker 0:7da612835693 100 }
networker 0:7da612835693 101 if (data) {
networker 0:7da612835693 102 parseRsp(data, len);
networker 0:7da612835693 103 }
networker 0:7da612835693 104 switch (_state) {
networker 0:7da612835693 105 case 0: //closed
networker 0:7da612835693 106 if (len==0) { //socket just opened
networker 0:7da612835693 107 //'Open' cleared the services list
networker 0:7da612835693 108 ServiceSearchRequest(&req, 10);
networker 0:7da612835693 109 _state = 1; //wait for service handles
networker 0:7da612835693 110 }
networker 0:7da612835693 111 break;
networker 0:7da612835693 112 case 1: //service handles arriving
networker 0:7da612835693 113 if (contState[0]) {//continuation, repeat request
networker 0:7da612835693 114 ServiceSearchRequest(&req, 5);
networker 0:7da612835693 115 } else {
networker 0:7da612835693 116 if (data[0]==3) {
networker 0:7da612835693 117 index = services.begin();
networker 0:7da612835693 118 if (index != services.end()) {
networker 0:7da612835693 119 unsigned handle = (*index).first;
networker 0:7da612835693 120 //printf("req.: handle %#X\n", handle);
networker 0:7da612835693 121 ServiceAttributeRequest(handle, 100, &list);//0x1001D
networker 0:7da612835693 122 } else
networker 0:7da612835693 123 printf(" - empty list - \n");//should not happen
networker 0:7da612835693 124 _state = 2; //wait for attribute response
networker 0:7da612835693 125 } else
networker 0:7da612835693 126 printf("Expected a ServiceSearchResponse 0x03, got %#x\n", data[0]);
networker 0:7da612835693 127 }
networker 0:7da612835693 128 break;
networker 0:7da612835693 129 case 2:
networker 0:7da612835693 130 if (contState[0])//repeat request
networker 0:7da612835693 131 ServiceAttributeRequest((*index).first, 100, &list);
networker 0:7da612835693 132 else {
networker 0:7da612835693 133 if (data[0]==5) {
networker 0:7da612835693 134 index++; //move to next service
networker 0:7da612835693 135 if (index != services.end()) {
networker 0:7da612835693 136 //printf("req.: handle %#X\n", (*index).first);
networker 0:7da612835693 137 ServiceAttributeRequest((*index).first, 100, &list);
networker 0:7da612835693 138 } else {
networker 0:7da612835693 139 printf(" - end of list - \n");
networker 0:7da612835693 140 Socket_Close(sdp_socket); //Note: socket=L2CAP, sdp_socket=SDP !!!
networker 0:7da612835693 141 _state = 0;
networker 0:7da612835693 142 }
networker 0:7da612835693 143 } else
networker 0:7da612835693 144 printf("Expected a ServiceAttributeResponse 0x05, got %#x\n", data[0]);
networker 0:7da612835693 145 }
networker 0:7da612835693 146 break;
networker 0:7da612835693 147 }
networker 0:7da612835693 148 }
networker 0:7da612835693 149
networker 0:7da612835693 150 //this function is called when the SDP sockets receives data (see HCICallback in TestShell),
networker 0:7da612835693 151 //currently does not happen because not forwarded from OnSdpRsp, can be used to handle multiple connections
networker 0:7da612835693 152 void SDPHandler::OnSockCallback(int socket, SocketState state, const u8* data, int len, void* userData) {
networker 0:7da612835693 153 printf("SDPHandler::OnSockCallback(socket=%d, state=%d, len=%d)\n", socket, state, len);
networker 0:7da612835693 154 printfBytes("Got SDP Response from socket: ", data, len);
networker 0:7da612835693 155 }
networker 0:7da612835693 156
networker 0:7da612835693 157 //void SDPHandler::errorhandler(unsigned err) {//default error handler
networker 0:7da612835693 158 void errorhandler(unsigned err) {//default error handler
networker 0:7da612835693 159 switch (err) {
networker 0:7da612835693 160 case 1:
networker 0:7da612835693 161 printf("Unsupported version of SDP\n");
networker 0:7da612835693 162 break;
networker 0:7da612835693 163 case 2:
networker 0:7da612835693 164 printf("Invalid SDP ServiceRecordHandle\n");
networker 0:7da612835693 165 break;
networker 0:7da612835693 166 case 3:
networker 0:7da612835693 167 printf("SDP syntax error\n");
networker 0:7da612835693 168 break;
networker 0:7da612835693 169 case 4:
networker 0:7da612835693 170 printf("PDU size was invalid\n");
networker 0:7da612835693 171 break;
networker 0:7da612835693 172 case 5:
networker 0:7da612835693 173 printf("Continuation state was invalid\n");
networker 0:7da612835693 174 break;
networker 0:7da612835693 175 case 6:
networker 0:7da612835693 176 printf("SDP server has insufficient resources\n");
networker 0:7da612835693 177 break;
networker 0:7da612835693 178 default:
networker 0:7da612835693 179 printf("Unknown SDP error code\n");
networker 0:7da612835693 180 break;
networker 0:7da612835693 181 }
networker 0:7da612835693 182 }
networker 0:7da612835693 183
networker 0:7da612835693 184 int SDPHandler::ServiceSearchRequest(sdp_data *sp, unsigned count, unsigned cs) {
networker 0:7da612835693 185 int parlen = sp->Size() + contState[0] + 3;
networker 0:7da612835693 186 buf[0] = 2; //pdu
networker 0:7da612835693 187 buf[1] = txid>>8;
networker 0:7da612835693 188 buf[2] = txid++;
networker 0:7da612835693 189 buf[4] = parlen;
networker 0:7da612835693 190 buf[3] = parlen>>8;
networker 0:7da612835693 191 int p = sp->build(buf+5, 100-10);
networker 0:7da612835693 192 buf[p+6] = count;
networker 0:7da612835693 193 buf[p+5] = count>>8;
networker 0:7da612835693 194 buf[p+7] = contState[0];
networker 0:7da612835693 195 for (int j = 1; j <= contState[0]; j++)
networker 0:7da612835693 196 buf[p+j+7] = contState[j];
networker 0:7da612835693 197 //printfBytes("SDP Send: ", buf, parlen+5);
networker 0:7da612835693 198 return Socket_Send(sdp_socket, l2cap_buf, parlen + 5 + OFFSET);
networker 0:7da612835693 199 }
networker 0:7da612835693 200
networker 0:7da612835693 201 int SDPHandler::ServiceAttributeRequest(unsigned handle, unsigned count, sdp_data* al, unsigned cs) {
networker 0:7da612835693 202 int parlen = al->Size() + contState[0] + 7;
networker 0:7da612835693 203 buf[0] = 4; //pdu
networker 0:7da612835693 204 buf[1] = txid>>8;
networker 0:7da612835693 205 buf[2] = txid++;
networker 0:7da612835693 206 buf[4] = parlen;
networker 0:7da612835693 207 buf[3] = parlen>>8;
networker 0:7da612835693 208 for (int i = 0; i < 4; i++)
networker 0:7da612835693 209 buf[i+5] = ((char*)&handle)[3-i];
networker 0:7da612835693 210 buf[9] = count>>8;
networker 0:7da612835693 211 buf[10] = count;
networker 0:7da612835693 212 int p = al->build(buf+11, 100-26);
networker 0:7da612835693 213 buf[p+11] = contState[0];
networker 0:7da612835693 214 for (int j = 1; j <= contState[0]; j++)
networker 0:7da612835693 215 buf[p+j+11] = contState[j];
networker 0:7da612835693 216 //printfBytes("SDP Send: ", buf, parlen+5);
networker 0:7da612835693 217 return Socket_Send(sdp_socket, l2cap_buf, parlen + 5 + OFFSET);
networker 0:7da612835693 218 }
networker 0:7da612835693 219
networker 0:7da612835693 220 int SDPHandler::ServiceSearchAttributeRequest(sdp_data *sp, unsigned count, sdp_data* al, unsigned cs) {
networker 0:7da612835693 221 int parlen = sp->Size() + al->Size() + contState[0] + 3; // count (2 bytes) + at least 1 cont
networker 0:7da612835693 222 buf[0] = 6; //pdu
networker 0:7da612835693 223 buf[1] = txid>>8;
networker 0:7da612835693 224 buf[2] = txid++;
networker 0:7da612835693 225 buf[4] = parlen;
networker 0:7da612835693 226 buf[3] = parlen>>8;
networker 0:7da612835693 227 int p = sp->build(buf+5, 30);
networker 0:7da612835693 228 buf[p+6] = count;
networker 0:7da612835693 229 buf[p+5] = count>>8;
networker 0:7da612835693 230 p += al->build(buf+11, 100-38);
networker 0:7da612835693 231 buf[p+7] = contState[0];
networker 0:7da612835693 232 for (int j = 1; j <= contState[0]; j++)
networker 0:7da612835693 233 buf[p+j+7] = contState[j];
networker 0:7da612835693 234 //printfBytes("SDP Send: ", buf, parlen+5);
networker 0:7da612835693 235 return Socket_Send(sdp_socket, l2cap_buf, parlen + 5 + OFFSET);
networker 0:7da612835693 236 }
networker 0:7da612835693 237
networker 0:7da612835693 238 int SDPManager::ServiceSearchAttributeReply(unsigned rxid, sdp_data* al, unsigned count, unsigned cs) {
networker 0:7da612835693 239 unsigned size = al->Size();
networker 0:7da612835693 240 unsigned cont = 0;//outgoing continuation
networker 0:7da612835693 241 unsigned char *_buf = new unsigned char[OFFSET+5+2+size+3];
networker 0:7da612835693 242 unsigned char *buf = _buf+OFFSET;
networker 0:7da612835693 243 unsigned byteCount = size - cs; //remainder of data to send
networker 0:7da612835693 244 unsigned parlen = 2 + byteCount + 1 ;// attributelistbytecount+payload+no_continuation
networker 0:7da612835693 245 if (byteCount > count) {//still too large, need continuation
networker 0:7da612835693 246 byteCount = count; //limit at maximum
networker 0:7da612835693 247 cont = cs + count; //start for next iteration
networker 0:7da612835693 248 parlen = 2 + byteCount + 3; //adjusted for payload and continuation
networker 0:7da612835693 249 printf("Need continuation, sending bytes [%d, %d> of attributeList\n", cs, cont);
networker 0:7da612835693 250 } else {
networker 0:7da612835693 251 // printf("Final or only block, sending bytes [%d, %d> of attributeList\n", cs, cs+byteCount);
networker 0:7da612835693 252 }
networker 0:7da612835693 253 buf[0] = 7; //pdu
networker 0:7da612835693 254 buf[1] = rxid>>8;
networker 0:7da612835693 255 buf[2] = rxid;
networker 0:7da612835693 256 buf[3] = parlen>>8;
networker 0:7da612835693 257 buf[4] = parlen;
networker 0:7da612835693 258 buf[5] = byteCount>>8;
networker 0:7da612835693 259 buf[6] = byteCount;
networker 0:7da612835693 260 int p = al->build(buf+7, size);//limited only by buffersize
networker 0:7da612835693 261 //printf("'build' added %d bytes to the buffer\n", p);
networker 0:7da612835693 262 if (cs == 0) { //this is not a continuation
networker 0:7da612835693 263 buf[byteCount+7] = 0;
networker 0:7da612835693 264 } else { //this is a continuation
networker 0:7da612835693 265 memcpy(buf+7, buf+7+cs, byteCount);//move part of interrest to beginning of buffer
networker 0:7da612835693 266 buf[byteCount+7] = 2;
networker 0:7da612835693 267 buf[byteCount+8] = cont>>8;
networker 0:7da612835693 268 buf[byteCount+9] = cont;
networker 0:7da612835693 269 }
networker 0:7da612835693 270 //printfBytes("SDP Send: ", buf, parlen+5);
networker 0:7da612835693 271 int retval = Socket_Send(serverSock, _buf, parlen + 5 + OFFSET);
networker 0:7da612835693 272 delete[] _buf;
networker 0:7da612835693 273 return retval;
networker 0:7da612835693 274 }
networker 0:7da612835693 275
networker 0:7da612835693 276 //unsigned SDPHandler::getval(const unsigned char *p, int n) {
networker 0:7da612835693 277 unsigned getval(const unsigned char *p, int n) {
networker 0:7da612835693 278 unsigned ret = 0;
networker 0:7da612835693 279 for (int i = 0; i < n; i++)
networker 0:7da612835693 280 ret = (ret<<8) + (unsigned)p[i];
networker 0:7da612835693 281 return ret;
networker 0:7da612835693 282 }
networker 0:7da612835693 283
networker 0:7da612835693 284 //unsigned SDPHandler::length(const unsigned char *el, unsigned &p) {
networker 0:7da612835693 285 unsigned length(const unsigned char *el, unsigned &p) {
networker 0:7da612835693 286 unsigned len = 0;
networker 0:7da612835693 287 switch (el[p++] & 7) {//length
networker 0:7da612835693 288 case 0:
networker 0:7da612835693 289 len = 1;
networker 0:7da612835693 290 break;
networker 0:7da612835693 291 case 1:
networker 0:7da612835693 292 len = 2;
networker 0:7da612835693 293 break;
networker 0:7da612835693 294 case 2:
networker 0:7da612835693 295 len = 4;
networker 0:7da612835693 296 break;
networker 0:7da612835693 297 case 3:
networker 0:7da612835693 298 len = 8;
networker 0:7da612835693 299 break;
networker 0:7da612835693 300 case 4:
networker 0:7da612835693 301 len = 16;
networker 0:7da612835693 302 break;
networker 0:7da612835693 303 case 7://4bytes
networker 0:7da612835693 304 len= el[p++]<<24;
networker 0:7da612835693 305 len += el[p++]<<16;
networker 0:7da612835693 306 case 6://2bytes
networker 0:7da612835693 307 len += el[p++]<<8;
networker 0:7da612835693 308 case 5://1byte
networker 0:7da612835693 309 len += el[p++];
networker 0:7da612835693 310 break;
networker 0:7da612835693 311 }
networker 0:7da612835693 312 return len;
networker 0:7da612835693 313 }
networker 0:7da612835693 314
networker 0:7da612835693 315 extern "C" void HardFault_Handler() {
networker 0:7da612835693 316 printf("Hard Fault! %d bytes left\n", AvailableMemory(1));
networker 0:7da612835693 317 while (1);
networker 0:7da612835693 318 }
networker 0:7da612835693 319
networker 0:7da612835693 320 unsigned SDPHandler::parseLight (const unsigned char *el, unsigned count, sdp_data* &result, serv_rec* &record) {
networker 0:7da612835693 321 unsigned p = 0;
networker 0:7da612835693 322 unsigned len = length(el, p);
networker 0:7da612835693 323 int end = p+len;//end is the index of the item just after the sequence
networker 0:7da612835693 324 sdp_data *item = 0;
networker 0:7da612835693 325 switch (el[0]>>3) {//type
networker 0:7da612835693 326 case sdp_data::NULL_:
networker 0:7da612835693 327 printf("NULL ");
networker 0:7da612835693 328 break;
networker 0:7da612835693 329 case sdp_data::UNSIGNED:
networker 0:7da612835693 330 printf("UINT%d=%u ", len, (unsigned)getval(el+p, len));
networker 0:7da612835693 331 break;
networker 0:7da612835693 332 case sdp_data::SIGNED:
networker 0:7da612835693 333 printf("INT%d=%d ", len, (unsigned)getval(el+p, len));
networker 0:7da612835693 334 break;
networker 0:7da612835693 335 case sdp_data::UUID:
networker 0:7da612835693 336 if (len==16) {
networker 0:7da612835693 337 printf("UUID16= ");
networker 0:7da612835693 338 for (int i = 0; i < 16; i++)
networker 0:7da612835693 339 printf("%02x ", el[p+i]);
networker 0:7da612835693 340 } else
networker 0:7da612835693 341 printf("UUID%d=%u ", len, (unsigned)getval(el+p, len));
networker 0:7da612835693 342 break;
networker 0:7da612835693 343 case sdp_data::STRING:
networker 0:7da612835693 344 printf("STR%d='%s' ", len, (char*)el+p);
networker 0:7da612835693 345 break;
networker 0:7da612835693 346 case sdp_data::BOOL:
networker 0:7da612835693 347 printf("BOOL%d=%d ", len, (unsigned)getval(el+p, len));
networker 0:7da612835693 348 break;
networker 0:7da612835693 349 case sdp_data::SEQUENCE:
networker 0:7da612835693 350 goto skip;
networker 0:7da612835693 351 case sdp_data::ALTERNATIVE:
networker 0:7da612835693 352 skip: {//p points just after the length indicator, hence at the first item IN the sequence
networker 0:7da612835693 353 printf("SEQ%d{%p ", len, item);
networker 0:7da612835693 354 int n = 0;
networker 0:7da612835693 355 unsigned short key;
networker 0:7da612835693 356 serv_rec *dummy = 0;
networker 0:7da612835693 357 while (p < end) {
networker 0:7da612835693 358 sdp_data *elem = 0;
networker 0:7da612835693 359 p += parseLight(el + p, len-p, elem, dummy);//parse each element in the sequence, the second arg is as yet unused
networker 0:7da612835693 360 if (record) {
networker 0:7da612835693 361 if (n & 1) { //value
networker 0:7da612835693 362 record->insert(pair<unsigned short, sdp_data*>(key, elem));
networker 0:7da612835693 363 } else //key
networker 0:7da612835693 364 key = n;
networker 0:7da612835693 365 n++;
networker 0:7da612835693 366 }
networker 0:7da612835693 367 }
networker 0:7da612835693 368 }
networker 0:7da612835693 369 printf("}\n");
networker 0:7da612835693 370 break;
networker 0:7da612835693 371 case 8:
networker 0:7da612835693 372 printf("URL%d='%s' ", len, (char*)el+p);
networker 0:7da612835693 373 break;
networker 0:7da612835693 374 default:
networker 0:7da612835693 375 printf("Parse: Unknown type %d, len=%d (code=%#02X)\n", el[0]>>3, len, el[0]);
networker 0:7da612835693 376 }
networker 0:7da612835693 377 result = item;
networker 0:7da612835693 378 return end;
networker 0:7da612835693 379 }
networker 0:7da612835693 380
networker 0:7da612835693 381 unsigned SDPHandler::parse (const unsigned char *el, unsigned count, sdp_data* &result, serv_rec* &record) {
networker 0:7da612835693 382 unsigned p = 0;
networker 0:7da612835693 383 unsigned len = length(el, p);
networker 0:7da612835693 384 int end = p+len;//end is the index of the item just after the sequence
networker 0:7da612835693 385 sdp_data *item = 0;
networker 0:7da612835693 386 switch (el[0]>>3) {//type
networker 0:7da612835693 387 case sdp_data::NULL_:
networker 0:7da612835693 388 item = new sdp_data();
networker 0:7da612835693 389 break;
networker 0:7da612835693 390 case sdp_data::UNSIGNED:
networker 0:7da612835693 391 item = new sdp_data((unsigned)getval(el+p, len), len);
networker 0:7da612835693 392 break;
networker 0:7da612835693 393 case sdp_data::SIGNED:
networker 0:7da612835693 394 item = new sdp_data((int)getval(el+p, len), len);
networker 0:7da612835693 395 break;
networker 0:7da612835693 396 case sdp_data::UUID:
networker 0:7da612835693 397 if (len==16) {
networker 0:7da612835693 398 char rev[16];
networker 0:7da612835693 399 for (int i = 0; i < 16; i++)
networker 0:7da612835693 400 rev[i] = el[p+15-i];
networker 0:7da612835693 401 item = new sdp_data(sdp_data::UUID, rev, len);
networker 0:7da612835693 402 } else
networker 0:7da612835693 403 item = new sdp_data(sdp_data::UUID, getval(el+p, len), len);
networker 0:7da612835693 404 break;
networker 0:7da612835693 405 case sdp_data::STRING:
networker 0:7da612835693 406 item = new sdp_data((char*)el+p, len);
networker 0:7da612835693 407 break;
networker 0:7da612835693 408 case sdp_data::BOOL:
networker 0:7da612835693 409 item = new sdp_data((bool)getval(el+p, len), len);
networker 0:7da612835693 410 break;
networker 0:7da612835693 411 case sdp_data::SEQUENCE:
networker 0:7da612835693 412 item = new sdp_data(sdp_data::SEQUENCE);
networker 0:7da612835693 413 goto skip;
networker 0:7da612835693 414 case sdp_data::ALTERNATIVE:
networker 0:7da612835693 415 item = new sdp_data(sdp_data::ALTERNATIVE);
networker 0:7da612835693 416 skip: {//p points just after the length indicator, hence at the first item IN the sequence
networker 0:7da612835693 417 //printf("SEQ%d{%p ", len, item);
networker 0:7da612835693 418 int n = 0;
networker 0:7da612835693 419 unsigned short key;
networker 0:7da612835693 420 serv_rec *dummy = 0;//means: there is no service record to fill in for deeper levels
networker 0:7da612835693 421 while (p < end) {
networker 0:7da612835693 422 sdp_data *elem = 0; //this becomes the tree with attribute values
networker 0:7da612835693 423 p += parse(el + p, len-p, elem, dummy);//parse each element in the sequence, the second arg is as yet unused
networker 0:7da612835693 424 if (record) { //if at the level of attribute list, add elem to record as key/value pair
networker 0:7da612835693 425 if (n & 1) { //value
networker 0:7da612835693 426 record->insert(pair<unsigned short, sdp_data*>(key, elem));
networker 0:7da612835693 427 } else //key
networker 0:7da612835693 428 key = elem->asUnsigned();
networker 0:7da612835693 429 n++;
networker 0:7da612835693 430 } else //just add the elements to the value tree
networker 0:7da612835693 431 item->add_element(elem);
networker 0:7da612835693 432 }
networker 0:7da612835693 433 }
networker 0:7da612835693 434 //printf("}\n");
networker 0:7da612835693 435 break;
networker 0:7da612835693 436 case 8:
networker 0:7da612835693 437 item = new sdp_data(sdp_data::URL, (char*)el+p, len);
networker 0:7da612835693 438 break;
networker 0:7da612835693 439 default:
networker 0:7da612835693 440 printf("Parse: Unknown type %d, len=%d (code=%#02X)\n", el[0]>>3, len, el[0]);
networker 0:7da612835693 441 }
networker 0:7da612835693 442 result = item;
networker 0:7da612835693 443 return end;
networker 0:7da612835693 444 }
networker 0:7da612835693 445
networker 0:7da612835693 446 void SDPHandler::append(const unsigned char *payload, int len) {
networker 0:7da612835693 447 unsigned char *tmp = new unsigned char[byteCount + len];//append the payload to the previous continuation buffer
networker 0:7da612835693 448 if (contBuf && byteCount) {
networker 0:7da612835693 449 memcpy(tmp, contBuf, byteCount); //copy the existing part
networker 0:7da612835693 450 delete[] contBuf;//delete the old buffer
networker 0:7da612835693 451 }
networker 0:7da612835693 452 memcpy(tmp+byteCount, payload, len); //append the new part
networker 0:7da612835693 453 contBuf = tmp;
networker 0:7da612835693 454 byteCount += len;
networker 0:7da612835693 455 }
networker 0:7da612835693 456
networker 0:7da612835693 457 void SDPHandler::freeBuf() {
networker 0:7da612835693 458 if (contBuf) {
networker 0:7da612835693 459 delete[] contBuf;
networker 0:7da612835693 460 contBuf = 0;
networker 0:7da612835693 461 }
networker 0:7da612835693 462 byteCount = 0;
networker 0:7da612835693 463 }
networker 0:7da612835693 464
networker 0:7da612835693 465
networker 0:7da612835693 466 //TODO: test case 7, add server support (cases 2, 4, 6)
networker 0:7da612835693 467 //3 cases: cont==0 && contBuf==0 -> use rsp; cont!=0 -> append; cont==0 && contBuf!=0 -> append and use contBuf
networker 0:7da612835693 468 int SDPHandler::parseRsp(const unsigned char*rsp, int len) {
networker 0:7da612835693 469 //unsigned tid = rsp[2] + ((unsigned)rsp[1]<<8);
networker 0:7da612835693 470 unsigned parlen = rsp[4] + ((unsigned)rsp[3]<<8);
networker 0:7da612835693 471 //printf("ParseRsp: tid=%04X, parlen=%d ", tid, parlen);
networker 0:7da612835693 472 unsigned cont = 0;
networker 0:7da612835693 473 switch (rsp[0]) {
networker 0:7da612835693 474 case 1: {//errorRsp
networker 0:7da612835693 475 unsigned errorcode = rsp[6] + ((unsigned)rsp[5]<<8);
networker 0:7da612835693 476 if (parlen > 2) {
networker 0:7da612835693 477 printf("ErrorInfo (%d bytes) for error %d is available\n", parlen-2, errorcode);
networker 0:7da612835693 478 }
networker 0:7da612835693 479 if (ErrorResponse)
networker 0:7da612835693 480 ErrorResponse(errorcode);
networker 0:7da612835693 481 return errorcode;
networker 0:7da612835693 482 }
networker 0:7da612835693 483 //break;
networker 0:7da612835693 484 case 3: { //servicesearchRsp
networker 0:7da612835693 485 //unsigned total = rsp[6] + ((unsigned)rsp[5]<<8);
networker 0:7da612835693 486 unsigned current = rsp[8] + ((unsigned)rsp[7]<<8);
networker 0:7da612835693 487 cont = rsp[9+4*current];
networker 0:7da612835693 488 memcpy(contState, &rsp[9+4*current], cont+1);//copy the continuation state
networker 0:7da612835693 489 //printf("total=%d, current=%d, cont=%d\n", total, current, cont);
networker 0:7da612835693 490 if (cont) {
networker 0:7da612835693 491 //no special handling here, just append the servicerecordhandles
networker 0:7da612835693 492 }
networker 0:7da612835693 493 //linear list of 32bit service-handles
networker 0:7da612835693 494 for (int i = 0; i < current; i++) {
networker 0:7da612835693 495 unsigned result = 0;
networker 0:7da612835693 496 for (int j = 0; j< 4; j++)
networker 0:7da612835693 497 result = (result<<8) + rsp[9 + 4*i + j];
networker 0:7da612835693 498 printf("SDP Search handle %08X\n", result);
networker 0:7da612835693 499 services.insert(pair<unsigned, serv_rec*>(result, 0));
networker 0:7da612835693 500 }
networker 0:7da612835693 501 if (ServiceSearchResponse)
networker 0:7da612835693 502 ServiceSearchResponse();
networker 0:7da612835693 503 }
networker 0:7da612835693 504 break;
networker 0:7da612835693 505 case 5: { //serviceattributeRsp
networker 0:7da612835693 506 unsigned count = rsp[6] + ((unsigned)rsp[5]<<8);//bytes in this part of the attribute list
networker 0:7da612835693 507 // append(rsp+7, count);
networker 0:7da612835693 508 cont = rsp[7+count];
networker 0:7da612835693 509 memcpy(contState, &rsp[7+count], cont+1);//copy the continuation state
networker 0:7da612835693 510 if (cont) {
networker 0:7da612835693 511 append(rsp+7, count);
networker 0:7da612835693 512 break;
networker 0:7da612835693 513 }
networker 0:7da612835693 514 //printf("count=%d parsing...\n", byteCount);
networker 0:7da612835693 515 serv_rec *serv = new serv_rec;
networker 0:7da612835693 516 if (contBuf) {
networker 0:7da612835693 517 append(rsp+7, count);
networker 0:7da612835693 518 parse(contBuf, byteCount, tree, serv);
networker 0:7da612835693 519 } else
networker 0:7da612835693 520 parse(rsp+7, count, tree, serv);
networker 0:7da612835693 521 //printf("...parsing done, ");
networker 0:7da612835693 522 //get the AttributeID, make sure attribId 0 is always included in the request
networker 0:7da612835693 523 unsigned key = (*serv)[0]->asUnsigned();//AttributeID '0' always refers to the serviceID
networker 0:7da612835693 524 //printf("Key=%#X\n", key); //key will be 0 when not requested
networker 0:7da612835693 525 services[key] = serv; //Add the attribute list to the services
networker 0:7da612835693 526 freeBuf();
networker 0:7da612835693 527 if (ServiceAttributeResponse)
networker 0:7da612835693 528 ServiceAttributeResponse(serv);
networker 0:7da612835693 529 }
networker 0:7da612835693 530 break;
networker 0:7da612835693 531 //below is UNTESTED
networker 0:7da612835693 532 case 7: { //servicesearchattributeRsp
networker 0:7da612835693 533 unsigned count = rsp[6] + ((unsigned)rsp[5]<<8);
networker 0:7da612835693 534 append(rsp+7, count);
networker 0:7da612835693 535 cont = rsp[7+count];
networker 0:7da612835693 536 memcpy(contState, &rsp[7+count], cont+1);
networker 0:7da612835693 537 if (cont)
networker 0:7da612835693 538 break;
networker 0:7da612835693 539 unsigned pos = 0;
networker 0:7da612835693 540 if (contBuf[pos]>>3 != sdp_data::SEQUENCE) {
networker 0:7da612835693 541 printf("Expected a sequence of attribute lists\n");
networker 0:7da612835693 542 break;
networker 0:7da612835693 543 }
networker 0:7da612835693 544 unsigned len = length(contBuf, pos);//get the length of the list of lists and advance pos to the first list
networker 0:7da612835693 545 while (pos<len) {
networker 0:7da612835693 546 printf("pos=%d, count=%d, parsing...\n", pos, len);
networker 0:7da612835693 547 serv_rec *serv = new serv_rec;
networker 0:7da612835693 548 pos = parse(contBuf+pos, len, tree, serv);
networker 0:7da612835693 549 unsigned key = (*serv)[0]->asUnsigned();
networker 0:7da612835693 550 services[key] = serv;
networker 0:7da612835693 551 }
networker 0:7da612835693 552 freeBuf();
networker 0:7da612835693 553 printf("...parsing done, pos=%d\n", pos);
networker 0:7da612835693 554 if (ServiceSearchAttributeResponse)
networker 0:7da612835693 555 ServiceSearchAttributeResponse();
networker 0:7da612835693 556 }
networker 0:7da612835693 557 break;
networker 0:7da612835693 558 default:
networker 0:7da612835693 559 printf("Unknown SDP response type %02X\n", rsp[0]);
networker 0:7da612835693 560 break;
networker 0:7da612835693 561 }
networker 0:7da612835693 562 return 0;
networker 0:7da612835693 563 }
networker 0:7da612835693 564
networker 0:7da612835693 565 //************************ SERVER related *******************************************//
networker 0:7da612835693 566
networker 0:7da612835693 567 //unsigned SDPHandler::parseUUID(const u8* data, int len, unsigned &p) {
networker 0:7da612835693 568 unsigned parseUUID(const u8* data, int len, unsigned &p) {
networker 0:7da612835693 569 unsigned u = 0;
networker 0:7da612835693 570 if ((data[p]>>3) != sdp_data::UUID) {
networker 0:7da612835693 571 printf(" UUID expected, got %d ", data[p]>>3);
networker 0:7da612835693 572 return (unsigned)-1;
networker 0:7da612835693 573 }
networker 0:7da612835693 574 switch (data[p++] & 7) {
networker 0:7da612835693 575 case 1:
networker 0:7da612835693 576 u = getval(data+p, 2);
networker 0:7da612835693 577 p +=2;
networker 0:7da612835693 578 break;
networker 0:7da612835693 579 case 2:
networker 0:7da612835693 580 u = getval(data+p, 4);
networker 0:7da612835693 581 p += 4;
networker 0:7da612835693 582 break;
networker 0:7da612835693 583 case 4:
networker 0:7da612835693 584 u = getval(data+p, 4);
networker 0:7da612835693 585 p += 16;
networker 0:7da612835693 586 break;
networker 0:7da612835693 587 default:
networker 0:7da612835693 588 printf(" UUID must be 2, 4 or 16 bytes, got type %d\n", data[p-1]);
networker 0:7da612835693 589 }
networker 0:7da612835693 590 return u;
networker 0:7da612835693 591 }
networker 0:7da612835693 592
networker 0:7da612835693 593 #define SVC_HANDLE 0x0001001DU //serial service
networker 0:7da612835693 594 void SDPManager::buildServer() {
networker 0:7da612835693 595 static sdp_data rfcomm(sdp_data::SEQUENCE);
networker 0:7da612835693 596 static sdp_data l2cap(sdp_data::SEQUENCE);
networker 0:7da612835693 597 static sdp_data protocol(sdp_data::SEQUENCE);
networker 0:7da612835693 598 static sdp_data serviceclass(sdp_data::SEQUENCE);
networker 0:7da612835693 599 static sdp_data browsegroup(sdp_data::SEQUENCE);
networker 0:7da612835693 600 static sdp_data root(sdp_data::UUID, BROWSEROOT);
networker 0:7da612835693 601 static sdp_data l2capuuid(sdp_data::UUID, 0x0100);
networker 0:7da612835693 602 static sdp_data rfcommuuid(sdp_data::UUID, 0x003);
networker 0:7da612835693 603 static sdp_data serial(sdp_data::UUID, 0x1101);
networker 0:7da612835693 604 static sdp_data chan(1U,1);
networker 0:7da612835693 605 static sdp_data handle(SVC_HANDLE,4);
networker 0:7da612835693 606 static sdp_data serviceID(0U, 2);
networker 0:7da612835693 607 static sdp_data name("MBED BlueUSB RFCOMM Serial");
networker 0:7da612835693 608 rfcomm.add_element(&rfcommuuid);
networker 0:7da612835693 609 rfcomm.add_element(&chan);
networker 0:7da612835693 610 l2cap.add_element(&l2capuuid);
networker 0:7da612835693 611 protocol.add_element(&l2cap);
networker 0:7da612835693 612 protocol.add_element(&rfcomm);
networker 0:7da612835693 613 serviceclass.add_element(&serial);
networker 0:7da612835693 614 browsegroup.add_element(&root);
networker 0:7da612835693 615 static serv_rec attr_list;
networker 0:7da612835693 616 attr_list[0] = &handle;
networker 0:7da612835693 617 attr_list[1] = &serviceclass;
networker 0:7da612835693 618 attr_list[4] = &protocol;
networker 0:7da612835693 619 attr_list[5] = &browsegroup;
networker 0:7da612835693 620 attr_list[0x100] = &name;
networker 0:7da612835693 621 server[SVC_HANDLE] = &attr_list;//server is static and this statement crashes the program when invoked from the constructor which is also invoked statically
networker 0:7da612835693 622 }
networker 0:7da612835693 623
networker 0:7da612835693 624 int SDPManager::findUUID(unsigned h, unsigned uuid) {
networker 0:7da612835693 625 serv_rec *rec = server[h];
networker 0:7da612835693 626 for ( serv_rec::iterator it = rec->begin(); it != rec->end(); it++) {
networker 0:7da612835693 627 if (it->second->findUUID(uuid))
networker 0:7da612835693 628 return it->first;
networker 0:7da612835693 629 }
networker 0:7da612835693 630 printf("rejected %08X because of %04Xx\n", h, uuid);
networker 0:7da612835693 631 return -1;
networker 0:7da612835693 632 }
networker 0:7da612835693 633
networker 0:7da612835693 634 void SDPManager::match(bool elig[], unsigned uuid) {
networker 0:7da612835693 635 map<unsigned, serv_rec*>::iterator idx;
networker 0:7da612835693 636 int i = 0;
networker 0:7da612835693 637 for (idx = server.begin(); idx != server.end(); idx++, i++)
networker 0:7da612835693 638 if (findUUID(idx->first, uuid) < 0)
networker 0:7da612835693 639 elig[i] = false;
networker 0:7da612835693 640 }
networker 0:7da612835693 641
networker 0:7da612835693 642 bool SDPManager::isInList(unsigned short id, const unsigned char* list, int end) {
networker 0:7da612835693 643 int len;
networker 0:7da612835693 644 for (unsigned pos = 0; pos < end; pos += len) {
networker 0:7da612835693 645 len = length(list, pos);
networker 0:7da612835693 646 switch (len) {
networker 0:7da612835693 647 case 2: //single value
networker 0:7da612835693 648 if (getval(list+pos, 2) == id)
networker 0:7da612835693 649 return true;
networker 0:7da612835693 650 break;
networker 0:7da612835693 651 case 4: //range
networker 0:7da612835693 652 if (getval(list+pos, 2) > id) break;
networker 0:7da612835693 653 if (getval(list+pos+2, 2) < id) break;
networker 0:7da612835693 654 return true;
networker 0:7da612835693 655 default:
networker 0:7da612835693 656 printf("Unexpected length %d\n", len);
networker 0:7da612835693 657 }
networker 0:7da612835693 658 }
networker 0:7da612835693 659 return false;
networker 0:7da612835693 660 }
networker 0:7da612835693 661
networker 0:7da612835693 662 void SDPManager::addToReply(sdp_data *svc, serv_rec *list, const unsigned char* att, int end) {
networker 0:7da612835693 663 unsigned short len, low, high;
networker 0:7da612835693 664 serv_rec::iterator from, to, idx;
networker 0:7da612835693 665 for (unsigned pos = 0; pos < end; pos += len) {
networker 0:7da612835693 666 len = length(att, pos);
networker 0:7da612835693 667 switch (len) {
networker 0:7da612835693 668 case 2: //single value
networker 0:7da612835693 669 low = getval(att+pos, 2);
networker 0:7da612835693 670 svc->add_element(new sdp_data(low, 2));
networker 0:7da612835693 671 svc->add_element((*list)[low]);
networker 0:7da612835693 672 printf("Found attrib %d\n", low);
networker 0:7da612835693 673 break;
networker 0:7da612835693 674 case 4: //range
networker 0:7da612835693 675 low = getval(att+pos, 2);
networker 0:7da612835693 676 high = getval(att+pos+2, 2);
networker 0:7da612835693 677 from = list->lower_bound(low);
networker 0:7da612835693 678 to = list->upper_bound(high);
networker 0:7da612835693 679 for (idx = from; idx != to; idx++) {
networker 0:7da612835693 680 svc->add_element(new sdp_data(idx->first, 2));
networker 0:7da612835693 681 svc->add_element(idx->second);
networker 0:7da612835693 682 printf("Found attrib %d\n", idx->first);
networker 0:7da612835693 683 }
networker 0:7da612835693 684 break;
networker 0:7da612835693 685 default:
networker 0:7da612835693 686 printf("Unexpected length %d\n", len);
networker 0:7da612835693 687 }
networker 0:7da612835693 688 }
networker 0:7da612835693 689 }
networker 0:7da612835693 690
networker 0:7da612835693 691 //for continuations, just generate the entire list, truncate to desired length and append position of the remainder as continuation
networker 0:7da612835693 692 //on the next iteration, generate the list again, use continuation to find remainder and reiterate
networker 0:7da612835693 693 void SDPManager::SDPServer(int socket, SocketState state, const u8* data, int len, void* userData) {
networker 0:7da612835693 694 unsigned tid = data[2] + ((unsigned)data[1]<<8);
networker 0:7da612835693 695 unsigned parlen = data[4] + ((unsigned)data[3]<<8);
networker 0:7da612835693 696 //printf("ParseReq: PDU_ID=%d, tid=%04X, parlen=%d ", data[0], tid, parlen);
networker 0:7da612835693 697 unsigned pos = 5;
networker 0:7da612835693 698 switch (data[0]) {
networker 0:7da612835693 699 case 1: {//errorRsp
networker 0:7da612835693 700 unsigned errorcode = data[6] + ((unsigned)data[5]<<8);
networker 0:7da612835693 701 if (parlen > 2) {
networker 0:7da612835693 702 printf("ErrorInfo (%d bytes) for error %d is available\n", parlen-2, errorcode);
networker 0:7da612835693 703 }
networker 0:7da612835693 704 errorhandler(errorcode);
networker 0:7da612835693 705 }
networker 0:7da612835693 706 break;
networker 0:7da612835693 707 case 2: { //servicesearchReq
networker 0:7da612835693 708 }
networker 0:7da612835693 709 break;
networker 0:7da612835693 710 case 4: { //serviceattributeReq
networker 0:7da612835693 711 }
networker 0:7da612835693 712 break;
networker 0:7da612835693 713 case 6: { //servicesearchattributeReq
networker 0:7da612835693 714 sdp_data reply(sdp_data::SEQUENCE);//the attributelist of the reply
networker 0:7da612835693 715
networker 0:7da612835693 716 unsigned pat[12];//the received search pattern
networker 0:7da612835693 717 int pn;//number of uuids in the pattern
networker 0:7da612835693 718 if (data[pos]>>3 != sdp_data::SEQUENCE) {//the uuids are wrapped in a sequence
networker 0:7da612835693 719 printf("Expected a sequence of UUIDs\n");
networker 0:7da612835693 720 break;
networker 0:7da612835693 721 }
networker 0:7da612835693 722 unsigned end = pos + length(data, pos);//get the length of the list of lists and advance pos to the first list
networker 0:7da612835693 723 bool *eligible = new bool[server.size()];//marks for the services identified by the search pattern
networker 0:7da612835693 724 for (int i = 0; i < server.size(); i++) eligible[i] = true;
networker 0:7da612835693 725 for (pn = 0; pn < 12 && pos < end; pn++) {
networker 0:7da612835693 726 pat[pn] = parseUUID(data,end, pos);//store uuid from the sequence in the pattern
networker 0:7da612835693 727 match(eligible, pat[pn]);//unmark a service when it does not contain the uuid
networker 0:7da612835693 728 //printf("pos=%d, count=%d, uuid=%#X\n", pos, len, pat[pn]);
networker 0:7da612835693 729 }
networker 0:7da612835693 730
networker 0:7da612835693 731 unsigned count = getval(data+pos, 2); //maximum length of attribute list to return
networker 0:7da612835693 732 pos += 2;
networker 0:7da612835693 733
networker 0:7da612835693 734 int len = length(data, pos); //get the length of the attributeID list
networker 0:7da612835693 735 int cont = pos + len;
networker 0:7da612835693 736 //printf("Count = %d pos=%d, data[pos]=%02x, len=%d, cont=%d\n", count, pos, data[pos], len, cont);
networker 0:7da612835693 737 int i = 0;
networker 0:7da612835693 738 for (map<unsigned, serv_rec*>::iterator idx = server.begin(); idx != server.end(); idx++, i++) {//foreach service
networker 0:7da612835693 739 //printf("testing service handle %08X\n", idx->first);
networker 0:7da612835693 740 if (!eligible[i]) continue; //skip services that don't match the pattern
networker 0:7da612835693 741 sdp_data *svc = new sdp_data(sdp_data::SEQUENCE); //create a sequence for the attributes of the present service
networker 0:7da612835693 742 #if 0
networker 0:7da612835693 743 for (serv_rec::iterator attr = idx->second->begin(); attr != idx->second->end(); attr++) {//foreach attrib in the service
networker 0:7da612835693 744 //printf("testing attribID %u\n", attr->first);
networker 0:7da612835693 745 if (isInList(attr->first, data+pos, len)) {//check if it is requested
networker 0:7da612835693 746 printf("Found attribID %d\n", attr->first);
networker 0:7da612835693 747 sdp_data *p = attr->second; //the attribute
networker 0:7da612835693 748 svc->add_element(new sdp_data(attr->first, 2)); //add the attribute ID as an unsigned short
networker 0:7da612835693 749 svc->add_element(p); //add the attribute
networker 0:7da612835693 750 //printf("appending %d bytes\n", p->Size());
networker 0:7da612835693 751 }
networker 0:7da612835693 752 }
networker 0:7da612835693 753 #else
networker 0:7da612835693 754 //alternatively use map::lower/upper_bound and equal_range, needs only one pass over the range list for each service
networker 0:7da612835693 755 addToReply(svc, idx->second, data+pos, len);
networker 0:7da612835693 756 #endif
networker 0:7da612835693 757 reply.add_element(svc); //append the new attribute list to the reply list
networker 0:7da612835693 758 }
networker 0:7da612835693 759
networker 0:7da612835693 760 unsigned tail = data[cont];
networker 0:7da612835693 761 if (tail) {
networker 0:7da612835693 762 tail = getval(data+cont+1, tail);
networker 0:7da612835693 763 printf("requested continuation tailpos=%u, size=%u\n", tail, reply.Size());
networker 0:7da612835693 764 }
networker 0:7da612835693 765 else {
networker 0:7da612835693 766 //printf("No continuation requested\n");
networker 0:7da612835693 767 }
networker 0:7da612835693 768 ServiceSearchAttributeReply(tid, &reply, count, tail);
networker 0:7da612835693 769
networker 0:7da612835693 770 for (int j = 0; j < reply.items(); j++) {
networker 0:7da612835693 771 sdp_data *al = reply.item(j);
networker 0:7da612835693 772 for (int k = 0; k < al->items(); k++) {
networker 0:7da612835693 773 if ((k & 1) == 0) //even hence ID
networker 0:7da612835693 774 delete al->item(k); //destroy the ID
networker 0:7da612835693 775 al->remove(k); //set all items to nil to prevent destruction of the DB
networker 0:7da612835693 776 }
networker 0:7da612835693 777 delete al; //destroy the list;
networker 0:7da612835693 778 reply.remove(j);
networker 0:7da612835693 779 }
networker 0:7da612835693 780 delete[] eligible;
networker 0:7da612835693 781 }
networker 0:7da612835693 782 break;
networker 0:7da612835693 783 default:
networker 0:7da612835693 784 printf("Unknown SDP request type %02X\n", data[0]);
networker 0:7da612835693 785 break;
networker 0:7da612835693 786 }
networker 0:7da612835693 787 }