sdp_util.c (7907f06931c075b55e3402fa469abbe35eebee25) sdp_util.c (f8fbdce0c5067e7e7edd3a29934b1f9b79c8ff2d)
1/*
2 * Copyright (C) 2014 BlueKitchen GmbH
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright

--- 72 unchanged lines hidden (view full) ---

81 uint32_t result = 0;
82 de_type_t de_type = de_get_element_type(header);
83 de_size_t de_size = de_get_size_type(header);
84 switch (de_size){
85 case DE_SIZE_VAR_8:
86 result = header[1];
87 break;
88 case DE_SIZE_VAR_16:
1/*
2 * Copyright (C) 2014 BlueKitchen GmbH
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright

--- 72 unchanged lines hidden (view full) ---

81 uint32_t result = 0;
82 de_type_t de_type = de_get_element_type(header);
83 de_size_t de_size = de_get_size_type(header);
84 switch (de_size){
85 case DE_SIZE_VAR_8:
86 result = header[1];
87 break;
88 case DE_SIZE_VAR_16:
89 result = READ_NET_16(header,1);
89 result = big_endian_read_16(header,1);
90 break;
91 case DE_SIZE_VAR_32:
90 break;
91 case DE_SIZE_VAR_32:
92 result = READ_NET_32(header,1);
92 result = bit_endian_read_32(header,1);
93 break;
94 default:
95 // case DE_SIZE_8:
96 // case DE_SIZE_16:
97 // case DE_SIZE_32:
98 // case DE_SIZE_64:
99 // case DE_SIZE_128:
100 if (de_type == DE_NIL) return 0;

--- 4 unchanged lines hidden (view full) ---

105
106int de_get_len(uint8_t *header){
107 return de_get_header_size(header) + de_get_data_size(header);
108}
109
110// @returns OK, if UINT16 value was read
111int de_element_get_uint16(uint8_t * element, uint16_t * value){
112 if (de_get_size_type(element) != DE_SIZE_16) return 0;
93 break;
94 default:
95 // case DE_SIZE_8:
96 // case DE_SIZE_16:
97 // case DE_SIZE_32:
98 // case DE_SIZE_64:
99 // case DE_SIZE_128:
100 if (de_type == DE_NIL) return 0;

--- 4 unchanged lines hidden (view full) ---

105
106int de_get_len(uint8_t *header){
107 return de_get_header_size(header) + de_get_data_size(header);
108}
109
110// @returns OK, if UINT16 value was read
111int de_element_get_uint16(uint8_t * element, uint16_t * value){
112 if (de_get_size_type(element) != DE_SIZE_16) return 0;
113 *value = READ_NET_16(element, de_get_header_size(element));
113 *value = big_endian_read_16(element, de_get_header_size(element));
114 return 1;
115}
116
117// @returns: element is valid UUID
118int de_get_normalized_uuid(uint8_t *uuid128, uint8_t *element){
119 de_type_t uuidType = de_get_element_type(element);
120 de_size_t uuidSize = de_get_size_type(element);
121 if (uuidType != DE_UUID) return 0;
122 uint32_t shortUUID;
123 switch (uuidSize){
124 case DE_SIZE_16:
114 return 1;
115}
116
117// @returns: element is valid UUID
118int de_get_normalized_uuid(uint8_t *uuid128, uint8_t *element){
119 de_type_t uuidType = de_get_element_type(element);
120 de_size_t uuidSize = de_get_size_type(element);
121 if (uuidType != DE_UUID) return 0;
122 uint32_t shortUUID;
123 switch (uuidSize){
124 case DE_SIZE_16:
125 shortUUID = READ_NET_16(element, 1);
125 shortUUID = big_endian_read_16(element, 1);
126 break;
127 case DE_SIZE_32:
126 break;
127 case DE_SIZE_32:
128 shortUUID = READ_NET_32(element, 1);
128 shortUUID = bit_endian_read_32(element, 1);
129 break;
130 case DE_SIZE_128:
131 memcpy(uuid128, element+1, 16);
132 return 1;
133 default:
134 return 0;
135 }
136 sdp_normalize_uuid(uuid128, shortUUID);
137 return 1;
138}
139
140// @returns 0 if no UUID16 or UUID32 is present, and UUID32 otherwise
141uint32_t de_get_uuid32(uint8_t * element){
142 uint8_t uuid128[16];
143 int validUuid128 = de_get_normalized_uuid(uuid128, element);
144 if (!validUuid128) return 0;
145 int hasBlueoothBaseUuid = sdp_has_blueooth_base_uuid(uuid128);
146 if (!hasBlueoothBaseUuid) return 0;
129 break;
130 case DE_SIZE_128:
131 memcpy(uuid128, element+1, 16);
132 return 1;
133 default:
134 return 0;
135 }
136 sdp_normalize_uuid(uuid128, shortUUID);
137 return 1;
138}
139
140// @returns 0 if no UUID16 or UUID32 is present, and UUID32 otherwise
141uint32_t de_get_uuid32(uint8_t * element){
142 uint8_t uuid128[16];
143 int validUuid128 = de_get_normalized_uuid(uuid128, element);
144 if (!validUuid128) return 0;
145 int hasBlueoothBaseUuid = sdp_has_blueooth_base_uuid(uuid128);
146 if (!hasBlueoothBaseUuid) return 0;
147 return READ_NET_32(uuid128, 0);
147 return bit_endian_read_32(uuid128, 0);
148}
149
150// functions to create record
151static void de_store_descriptor(uint8_t * header, de_type_t type, de_size_t size){
152 header[0] = (type << 3) | size;
153}
154
155void de_store_descriptor_with_len(uint8_t * header, de_type_t type, de_size_t size, uint32_t len){
156 header[0] = (type << 3) | size;
157 switch (size){
158 case DE_SIZE_VAR_8:
159 header[1] = len;
160 break;
161 case DE_SIZE_VAR_16:
148}
149
150// functions to create record
151static void de_store_descriptor(uint8_t * header, de_type_t type, de_size_t size){
152 header[0] = (type << 3) | size;
153}
154
155void de_store_descriptor_with_len(uint8_t * header, de_type_t type, de_size_t size, uint32_t len){
156 header[0] = (type << 3) | size;
157 switch (size){
158 case DE_SIZE_VAR_8:
159 header[1] = len;
160 break;
161 case DE_SIZE_VAR_16:
162 net_store_16(header, 1, len);
162 big_endian_store_16(header, 1, len);
163 break;
164 case DE_SIZE_VAR_32:
163 break;
164 case DE_SIZE_VAR_32:
165 net_store_32(header, 1, len);
165 big_endian_store_32(header, 1, len);
166 break;
167 default:
168 break;
169 }
170}
171
172// MARK: DataElement creation
173

--- 7 unchanged lines hidden (view full) ---

181 int element_len = de_get_len(header);
182 de_store_descriptor_with_len(header+element_len, DE_DES, DE_SIZE_VAR_16, 0); // DES, 2 Byte Length
183 return header + element_len;
184}
185
186/* closes the current sequence and updates the parent sequence */
187void de_pop_sequence(uint8_t * parent, uint8_t * child){
188 int child_len = de_get_len(child);
166 break;
167 default:
168 break;
169 }
170}
171
172// MARK: DataElement creation
173

--- 7 unchanged lines hidden (view full) ---

181 int element_len = de_get_len(header);
182 de_store_descriptor_with_len(header+element_len, DE_DES, DE_SIZE_VAR_16, 0); // DES, 2 Byte Length
183 return header + element_len;
184}
185
186/* closes the current sequence and updates the parent sequence */
187void de_pop_sequence(uint8_t * parent, uint8_t * child){
188 int child_len = de_get_len(child);
189 int data_size_parent = READ_NET_16(parent,1);
190 net_store_16(parent, 1, data_size_parent + child_len);
189 int data_size_parent = big_endian_read_16(parent,1);
190 big_endian_store_16(parent, 1, data_size_parent + child_len);
191}
192
193/* adds a single number value and 16+32 bit UUID to the sequence */
194void de_add_number(uint8_t *seq, de_type_t type, de_size_t size, uint32_t value){
191}
192
193/* adds a single number value and 16+32 bit UUID to the sequence */
194void de_add_number(uint8_t *seq, de_type_t type, de_size_t size, uint32_t value){
195 int data_size = READ_NET_16(seq,1);
195 int data_size = big_endian_read_16(seq,1);
196 int element_size = 1; // e.g. for DE_TYPE_NIL
197 de_store_descriptor(seq+3+data_size, type, size);
198 switch (size){
199 case DE_SIZE_8:
200 if (type != DE_NIL){
201 seq[4+data_size] = value;
202 element_size = 2;
203 }
204 break;
205 case DE_SIZE_16:
196 int element_size = 1; // e.g. for DE_TYPE_NIL
197 de_store_descriptor(seq+3+data_size, type, size);
198 switch (size){
199 case DE_SIZE_8:
200 if (type != DE_NIL){
201 seq[4+data_size] = value;
202 element_size = 2;
203 }
204 break;
205 case DE_SIZE_16:
206 net_store_16(seq, 4+data_size, value);
206 big_endian_store_16(seq, 4+data_size, value);
207 element_size = 3;
208 break;
209 case DE_SIZE_32:
207 element_size = 3;
208 break;
209 case DE_SIZE_32:
210 net_store_32(seq, 4+data_size, value);
210 big_endian_store_32(seq, 4+data_size, value);
211 element_size = 5;
212 break;
213 default:
214 break;
215 }
211 element_size = 5;
212 break;
213 default:
214 break;
215 }
216 net_store_16(seq, 1, data_size+element_size);
216 big_endian_store_16(seq, 1, data_size+element_size);
217}
218
219/* add a single block of data, e.g. as DE_STRING, DE_URL */
220void de_add_data( uint8_t *seq, de_type_t type, uint16_t size, uint8_t *data){
217}
218
219/* add a single block of data, e.g. as DE_STRING, DE_URL */
220void de_add_data( uint8_t *seq, de_type_t type, uint16_t size, uint8_t *data){
221 int data_size = READ_NET_16(seq,1);
221 int data_size = big_endian_read_16(seq,1);
222 if (size > 0xff) {
223 // use 16-bit lengh information (3 byte header)
224 de_store_descriptor_with_len(seq+3+data_size, type, DE_SIZE_VAR_16, size);
225 data_size += 3;
226 } else {
227 // use 8-bit lengh information (2 byte header)
228 de_store_descriptor_with_len(seq+3+data_size, type, DE_SIZE_VAR_8, size);
229 data_size += 2;
230 }
231 memcpy( seq + 3 + data_size, data, size);
232 data_size += size;
222 if (size > 0xff) {
223 // use 16-bit lengh information (3 byte header)
224 de_store_descriptor_with_len(seq+3+data_size, type, DE_SIZE_VAR_16, size);
225 data_size += 3;
226 } else {
227 // use 8-bit lengh information (2 byte header)
228 de_store_descriptor_with_len(seq+3+data_size, type, DE_SIZE_VAR_8, size);
229 data_size += 2;
230 }
231 memcpy( seq + 3 + data_size, data, size);
232 data_size += size;
233 net_store_16(seq, 1, data_size);
233 big_endian_store_16(seq, 1, data_size);
234}
235
236void de_add_uuid128(uint8_t * seq, uint8_t * uuid){
234}
235
236void de_add_uuid128(uint8_t * seq, uint8_t * uuid){
237 int data_size = READ_NET_16(seq,1);
237 int data_size = big_endian_read_16(seq,1);
238 de_store_descriptor(seq+3+data_size, DE_UUID, DE_SIZE_128);
239 memcpy( seq + 4 + data_size, uuid, 16);
238 de_store_descriptor(seq+3+data_size, DE_UUID, DE_SIZE_128);
239 memcpy( seq + 4 + data_size, uuid, 16);
240 net_store_16(seq, 1, data_size+1+16);
240 big_endian_store_16(seq, 1, data_size+1+16);
241}
242
243// MARK: DES iterator
244int des_iterator_init(des_iterator_t * it, uint8_t * element){
245 de_type_t type = de_get_element_type(element);
246 if (type != DE_DES) return 0;
247
248 it->element = element;

--- 50 unchanged lines hidden (view full) ---

299 de_type_t type = de_get_element_type(element);
300 if (type != DE_DES) return;
301 int pos = de_get_header_size(element);
302 int end_pos = de_get_len(element);
303 while (pos < end_pos){
304 de_type_t idType = de_get_element_type(element + pos);
305 de_size_t idSize = de_get_size_type(element + pos);
306 if (idType != DE_UINT || idSize != DE_SIZE_16) break; // wrong type
241}
242
243// MARK: DES iterator
244int des_iterator_init(des_iterator_t * it, uint8_t * element){
245 de_type_t type = de_get_element_type(element);
246 if (type != DE_DES) return 0;
247
248 it->element = element;

--- 50 unchanged lines hidden (view full) ---

299 de_type_t type = de_get_element_type(element);
300 if (type != DE_DES) return;
301 int pos = de_get_header_size(element);
302 int end_pos = de_get_len(element);
303 while (pos < end_pos){
304 de_type_t idType = de_get_element_type(element + pos);
305 de_size_t idSize = de_get_size_type(element + pos);
306 if (idType != DE_UINT || idSize != DE_SIZE_16) break; // wrong type
307 uint16_t attribute_id = READ_NET_16(element, pos + 1);
307 uint16_t attribute_id = big_endian_read_16(element, pos + 1);
308 pos += 3;
309 if (pos >= end_pos) break; // array out of bounds
310 de_type_t valueType = de_get_element_type(element + pos);
311 de_size_t valueSize = de_get_size_type(element + pos);
312 uint8_t done = (*handler)(attribute_id, element + pos, valueType, valueSize, context);
313 if (done) break;
314 pos += de_get_len(element + pos);
315 }

--- 6 unchanged lines hidden (view full) ---

322 int result;
323 uint16_t attributeID;
324};
325static int sdp_traversal_attributeID_search(uint8_t * element, de_type_t type, de_size_t size, void *my_context){
326 struct sdp_context_attributeID_search * context = (struct sdp_context_attributeID_search *) my_context;
327 if (type != DE_UINT) return 0;
328 switch (size) {
329 case DE_SIZE_16:
308 pos += 3;
309 if (pos >= end_pos) break; // array out of bounds
310 de_type_t valueType = de_get_element_type(element + pos);
311 de_size_t valueSize = de_get_size_type(element + pos);
312 uint8_t done = (*handler)(attribute_id, element + pos, valueType, valueSize, context);
313 if (done) break;
314 pos += de_get_len(element + pos);
315 }

--- 6 unchanged lines hidden (view full) ---

322 int result;
323 uint16_t attributeID;
324};
325static int sdp_traversal_attributeID_search(uint8_t * element, de_type_t type, de_size_t size, void *my_context){
326 struct sdp_context_attributeID_search * context = (struct sdp_context_attributeID_search *) my_context;
327 if (type != DE_UINT) return 0;
328 switch (size) {
329 case DE_SIZE_16:
330 if (READ_NET_16(element, 1) == context->attributeID) {
330 if (big_endian_read_16(element, 1) == context->attributeID) {
331 context->result = 1;
332 return 1;
333 }
334 break;
335 case DE_SIZE_32:
331 context->result = 1;
332 return 1;
333 }
334 break;
335 case DE_SIZE_32:
336 if (READ_NET_16(element, 1) <= context->attributeID
337 && context->attributeID <= READ_NET_16(element, 3)) {
336 if (big_endian_read_16(element, 1) <= context->attributeID
337 && context->attributeID <= big_endian_read_16(element, 3)) {
338 context->result = 1;
339 return 1;
340 }
341 break;
342 default:
343 break;
344 }
345 return 0;

--- 16 unchanged lines hidden (view full) ---

362 uint16_t usedBytes;
363 uint8_t *attributeIDList;
364};
365
366static int sdp_traversal_append_attributes(uint16_t attributeID, uint8_t * attributeValue, de_type_t type, de_size_t size, void *my_context){
367 struct sdp_context_append_attributes * context = (struct sdp_context_append_attributes *) my_context;
368 if (sdp_attribute_list_constains_id(context->attributeIDList, attributeID)) {
369 // DES_HEADER(3) + DES_DATA + (UINT16(3) + attribute)
338 context->result = 1;
339 return 1;
340 }
341 break;
342 default:
343 break;
344 }
345 return 0;

--- 16 unchanged lines hidden (view full) ---

362 uint16_t usedBytes;
363 uint8_t *attributeIDList;
364};
365
366static int sdp_traversal_append_attributes(uint16_t attributeID, uint8_t * attributeValue, de_type_t type, de_size_t size, void *my_context){
367 struct sdp_context_append_attributes * context = (struct sdp_context_append_attributes *) my_context;
368 if (sdp_attribute_list_constains_id(context->attributeIDList, attributeID)) {
369 // DES_HEADER(3) + DES_DATA + (UINT16(3) + attribute)
370 uint16_t data_size = READ_NET_16(context->buffer, 1);
370 uint16_t data_size = big_endian_read_16(context->buffer, 1);
371 int attribute_len = de_get_len(attributeValue);
372 if (3 + data_size + (3 + attribute_len) <= context->maxBytes) {
373 // copy Attribute
374 de_add_number(context->buffer, DE_UINT, DE_SIZE_16, attributeID);
375 data_size += 3; // 3 bytes
376 memcpy(context->buffer + 3 + data_size, attributeValue, attribute_len);
371 int attribute_len = de_get_len(attributeValue);
372 if (3 + data_size + (3 + attribute_len) <= context->maxBytes) {
373 // copy Attribute
374 de_add_number(context->buffer, DE_UINT, DE_SIZE_16, attributeID);
375 data_size += 3; // 3 bytes
376 memcpy(context->buffer + 3 + data_size, attributeValue, attribute_len);
377 net_store_16(context->buffer,1,data_size+attribute_len);
377 big_endian_store_16(context->buffer,1,data_size+attribute_len);
378 } else {
379 // not enought space left -> continue with previous element
380 return 1;
381 }
382 }
383 return 0;
384}
385

--- 43 unchanged lines hidden (view full) ---

429 // { Attribute ID (Descriptor, big endian 16-bit ID), AttributeValue (data)}
430
431 // handle Attribute ID
432 if (context->startOffset >= 3){
433 context->startOffset -= 3;
434 } else {
435 uint8_t idBuffer[3];
436 de_store_descriptor(idBuffer, DE_UINT, DE_SIZE_16);
378 } else {
379 // not enought space left -> continue with previous element
380 return 1;
381 }
382 }
383 return 0;
384}
385

--- 43 unchanged lines hidden (view full) ---

429 // { Attribute ID (Descriptor, big endian 16-bit ID), AttributeValue (data)}
430
431 // handle Attribute ID
432 if (context->startOffset >= 3){
433 context->startOffset -= 3;
434 } else {
435 uint8_t idBuffer[3];
436 de_store_descriptor(idBuffer, DE_UINT, DE_SIZE_16);
437 net_store_16(idBuffer,1,attributeID);
437 big_endian_store_16(idBuffer,1,attributeID);
438
439 int ok = spd_append_range(context, 3, idBuffer);
440 if (!ok) {
441 context->complete = 0;
442 return 1;
443 }
444 }
445

--- 85 unchanged lines hidden (view full) ---

531 context->attributeFound = 1;
532 switch (size){
533 case DE_SIZE_8:
534 if (attributeType != DE_NIL){
535 attributeValue[1] = context->attributeValue;
536 }
537 break;
538 case DE_SIZE_16:
438
439 int ok = spd_append_range(context, 3, idBuffer);
440 if (!ok) {
441 context->complete = 0;
442 return 1;
443 }
444 }
445

--- 85 unchanged lines hidden (view full) ---

531 context->attributeFound = 1;
532 switch (size){
533 case DE_SIZE_8:
534 if (attributeType != DE_NIL){
535 attributeValue[1] = context->attributeValue;
536 }
537 break;
538 case DE_SIZE_16:
539 net_store_16(attributeValue, 1, context->attributeValue);
539 big_endian_store_16(attributeValue, 1, context->attributeValue);
540 break;
541 case DE_SIZE_32:
540 break;
541 case DE_SIZE_32:
542 net_store_32(attributeValue, 1, context->attributeValue);
542 big_endian_store_32(attributeValue, 1, context->attributeValue);
543 break;
544 // Might want to support STRINGS to, copy upto original length
545 default:
546 break;
547 }
548 return 1;
549 }
550 return 0;

--- 81 unchanged lines hidden (view full) ---

632 printf("\n");
633 } else if (de_type == DE_STRING) {
634 int len = 0;
635 switch (de_size){
636 case DE_SIZE_VAR_8:
637 len = element[1];
638 break;
639 case DE_SIZE_VAR_16:
543 break;
544 // Might want to support STRINGS to, copy upto original length
545 default:
546 break;
547 }
548 return 1;
549 }
550 return 0;

--- 81 unchanged lines hidden (view full) ---

632 printf("\n");
633 } else if (de_type == DE_STRING) {
634 int len = 0;
635 switch (de_size){
636 case DE_SIZE_VAR_8:
637 len = element[1];
638 break;
639 case DE_SIZE_VAR_16:
640 len = READ_NET_16(element, 1);
640 len = big_endian_read_16(element, 1);
641 break;
642 default:
643 break;
644 }
645 printf("len %u (0x%02x)\n", len, len);
646 printf_hexdump(&element[pos], len);
647 } else {
648 uint32_t value = 0;
649 switch (de_size) {
650 case DE_SIZE_8:
651 if (de_type != DE_NIL){
652 value = element[pos];
653 }
654 break;
655 case DE_SIZE_16:
641 break;
642 default:
643 break;
644 }
645 printf("len %u (0x%02x)\n", len, len);
646 printf_hexdump(&element[pos], len);
647 } else {
648 uint32_t value = 0;
649 switch (de_size) {
650 case DE_SIZE_8:
651 if (de_type != DE_NIL){
652 value = element[pos];
653 }
654 break;
655 case DE_SIZE_16:
656 value = READ_NET_16(element,pos);
656 value = big_endian_read_16(element,pos);
657 break;
658 case DE_SIZE_32:
657 break;
658 case DE_SIZE_32:
659 value = READ_NET_32(element,pos);
659 value = bit_endian_read_32(element,pos);
660 break;
661 default:
662 break;
663 }
664 printf(", value: 0x%08" PRIx32 "\n", value);
665 }
666 return 0;
667}

--- 83 unchanged lines hidden ---
660 break;
661 default:
662 break;
663 }
664 printf(", value: 0x%08" PRIx32 "\n", value);
665 }
666 return 0;
667}

--- 83 unchanged lines hidden ---