Home | History | Annotate | Line # | Download | only in libbluetooth
sdp_put.c revision 1.1.2.2
      1 /*	$NetBSD: sdp_put.c,v 1.1.2.2 2009/05/13 19:18:20 jym Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2009 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Iain Hibbert.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __RCSID("$NetBSD: sdp_put.c,v 1.1.2.2 2009/05/13 19:18:20 jym Exp $");
     34 
     35 #include <bluetooth.h>
     36 #include <limits.h>
     37 #include <sdp.h>
     38 #include <string.h>
     39 
     40 /******************************************************************************
     41  *	sdp_put_xxxx(data, value)
     42  *
     43  * write a value to data space and advance data pointers,
     44  * fail if data space is not large enough
     45  */
     46 
     47 bool
     48 sdp_put_data(sdp_data_t *data, sdp_data_t *value)
     49 {
     50 	ssize_t len;
     51 
     52 	len = value->end - value->next;
     53 
     54 	if (data->next + len > data->end)
     55 		return false;
     56 
     57 	memcpy(data->next, value->next, (size_t)len);
     58 	data->next += len;
     59 	return true;
     60 }
     61 
     62 bool
     63 sdp_put_attr(sdp_data_t *data, uint16_t attr, sdp_data_t *value)
     64 {
     65 	sdp_data_t d = *data;
     66 
     67 	if (!sdp_put_uint16(&d, attr)
     68 	    || sdp_put_data(&d, value))
     69 		return false;
     70 
     71 	*data = d;
     72 	return true;
     73 }
     74 
     75 bool
     76 sdp_put_uuid(sdp_data_t *data, const uuid_t *uuid)
     77 {
     78 	uuid_t u = *uuid;
     79 
     80 	u.time_low = 0;
     81 
     82 	if (uuid_equal(&u, &BLUETOOTH_BASE_UUID, NULL) == 0)
     83 		return sdp_put_uuid128(data, uuid);
     84 
     85 	if (uuid->time_low > UINT16_MAX)
     86 		return sdp_put_uuid32(data, (uint32_t)uuid->time_low);
     87 
     88 	return sdp_put_uuid16(data, (uint16_t)uuid->time_low);
     89 }
     90 
     91 bool
     92 sdp_put_uuid16(sdp_data_t *data, uint16_t uuid)
     93 {
     94 
     95 	if (data->next + 3 > data->end)
     96 		return false;
     97 
     98 	data->next[0] = SDP_DATA_UUID16;
     99 	be16enc(data->next + 1, uuid);
    100 	data->next += 3;
    101 	return true;
    102 }
    103 
    104 bool
    105 sdp_put_uuid32(sdp_data_t *data, uint32_t uuid)
    106 {
    107 
    108 	if (data->next + 5 > data->end)
    109 		return false;
    110 
    111 	data->next[0] = SDP_DATA_UUID32;
    112 	be32enc(data->next + 1, uuid);
    113 	data->next += 5;
    114 	return true;
    115 }
    116 
    117 bool
    118 sdp_put_uuid128(sdp_data_t *data, const uuid_t *uuid)
    119 {
    120 
    121 	if (data->next + 17 > data->end)
    122 		return false;
    123 
    124 	data->next[0] = SDP_DATA_UUID128;
    125 	uuid_enc_be(data->next + 1, uuid);
    126 	data->next += 17;
    127 	return true;
    128 }
    129 
    130 bool
    131 sdp_put_bool(sdp_data_t *data, bool value)
    132 {
    133 
    134 	if (data->next + 2 > data->end)
    135 		return false;
    136 
    137 	data->next[0] = SDP_DATA_BOOL;
    138 	data->next[1] = (value ? 0x01 : 0x00);
    139 	data->next += 2;
    140 	return true;
    141 }
    142 
    143 bool
    144 sdp_put_uint(sdp_data_t *data, uintmax_t value)
    145 {
    146 
    147 	if (value > UINT64_MAX)
    148 		return false;
    149 
    150 	if (value > UINT32_MAX)
    151 		return sdp_put_uint64(data, (uint64_t)value);
    152 
    153 	if (value > UINT16_MAX)
    154 		return sdp_put_uint32(data, (uint32_t)value);
    155 
    156 	if (value > UINT8_MAX)
    157 		return sdp_put_uint16(data, (uint16_t)value);
    158 
    159 	return sdp_put_uint8(data, (uint8_t)value);
    160 }
    161 
    162 bool
    163 sdp_put_uint8(sdp_data_t *data, uint8_t value)
    164 {
    165 
    166 	if (data->next + 2 > data->end)
    167 		return false;
    168 
    169 	data->next[0] = SDP_DATA_UINT8;
    170 	data->next[1] = value;
    171 	data->next += 2;
    172 	return true;
    173 }
    174 
    175 bool
    176 sdp_put_uint16(sdp_data_t *data, uint16_t value)
    177 {
    178 
    179 	if (data->next + 3 > data->end)
    180 		return false;
    181 
    182 	data->next[0] = SDP_DATA_UINT16;
    183 	be16enc(data->next + 1, value);
    184 	data->next += 3;
    185 	return true;
    186 }
    187 
    188 bool
    189 sdp_put_uint32(sdp_data_t *data, uint32_t value)
    190 {
    191 
    192 	if (data->next + 5 > data->end)
    193 		return false;
    194 
    195 	data->next[0] = SDP_DATA_UINT32;
    196 	be32enc(data->next + 1, value);
    197 	data->next += 5;
    198 	return true;
    199 }
    200 
    201 bool
    202 sdp_put_uint64(sdp_data_t *data, uint64_t value)
    203 {
    204 
    205 	if (data->next + 9 > data->end)
    206 		return false;
    207 
    208 	data->next[0] = SDP_DATA_UINT64;
    209 	be64enc(data->next + 1, value);
    210 	data->next += 9;
    211 	return true;
    212 }
    213 
    214 bool
    215 sdp_put_int(sdp_data_t *data, intmax_t value)
    216 {
    217 
    218 	if (value > INT64_MAX || value < INT64_MIN)
    219 		return false;
    220 
    221 	if (value > INT32_MAX || value < INT32_MIN)
    222 		return sdp_put_int64(data, (int64_t)value);
    223 
    224 	if (value > INT16_MAX || value < INT16_MIN)
    225 		return sdp_put_int32(data, (int32_t)value);
    226 
    227 	if (value > INT8_MAX || value < INT8_MIN)
    228 		return sdp_put_int16(data, (int16_t)value);
    229 
    230 	return sdp_put_int8(data, (int8_t)value);
    231 }
    232 
    233 bool
    234 sdp_put_int8(sdp_data_t *data, int8_t value)
    235 {
    236 
    237 	if (data->next + 2 > data->end)
    238 		return false;
    239 
    240 	data->next[0] = SDP_DATA_INT8;
    241 	data->next[1] = (uint8_t)value;
    242 	data->next += 2;
    243 	return true;
    244 }
    245 
    246 bool
    247 sdp_put_int16(sdp_data_t *data, int16_t value)
    248 {
    249 
    250 	if (data->next + 3 > data->end)
    251 		return false;
    252 
    253 	data->next[0] = SDP_DATA_INT16;
    254 	be16enc(data->next + 1, (uint16_t)value);
    255 	data->next += 3;
    256 	return true;
    257 }
    258 
    259 bool
    260 sdp_put_int32(sdp_data_t *data, int32_t value)
    261 {
    262 
    263 	if (data->next + 5 > data->end)
    264 		return false;
    265 
    266 	data->next[0] = SDP_DATA_INT32;
    267 	be32enc(data->next + 1, (uint32_t)value);
    268 	data->next += 5;
    269 	return true;
    270 }
    271 
    272 bool
    273 sdp_put_int64(sdp_data_t *data, int64_t value)
    274 {
    275 
    276 	if (data->next + 9 > data->end)
    277 		return false;
    278 
    279 	data->next[0] = SDP_DATA_INT64;
    280 	be64enc(data->next + 1, (uint64_t)value);
    281 	data->next += 9;
    282 	return true;
    283 }
    284 
    285 static bool
    286 _sdp_put_ext(uint8_t type, sdp_data_t *data, ssize_t len)
    287 {
    288 	uint8_t *p = data->next;
    289 
    290 	if (len == -1) {
    291 		if (p + 2 > data->end)
    292 			return false;
    293 
    294 		len = data->end - p - 2;
    295 
    296 		if (len > UINT8_MAX)
    297 			len -= 1;
    298 
    299 		if (len > UINT16_MAX)
    300 			len -= 2;
    301 	}
    302 
    303 	if (len > UINT32_MAX)
    304 		return false;
    305 
    306 	if (len > UINT16_MAX) {
    307 		if (p + 5 + len > data->end)
    308 			return false;
    309 
    310 		p[0] = type | SDP_DATA_EXT32;
    311 		be32enc(p + 1, (uint32_t)len);
    312 		p += 5;
    313 	} else if (len > UINT8_MAX) {
    314 		if (p + 3 + len > data->end)
    315 			return false;
    316 
    317 		p[0] = type | SDP_DATA_EXT16;
    318 		be16enc(p + 1, (uint16_t)len);
    319 		p += 3;
    320 	} else {
    321 		if (p + 2 + len > data->end)
    322 			return false;
    323 
    324 		p[0] = type | SDP_DATA_EXT8;
    325 		p[1] = (uint8_t)len;
    326 		p += 2;
    327 	}
    328 
    329 	data->next = p;
    330 	return true;
    331 }
    332 
    333 bool
    334 sdp_put_seq(sdp_data_t *data, ssize_t len)
    335 {
    336 
    337 	return _sdp_put_ext(SDP_DATA_SEQ, data, len);
    338 }
    339 
    340 bool
    341 sdp_put_alt(sdp_data_t *data, ssize_t len)
    342 {
    343 
    344 	return _sdp_put_ext(SDP_DATA_ALT, data, len);
    345 }
    346 
    347 bool
    348 sdp_put_str(sdp_data_t *data, const char *str, ssize_t len)
    349 {
    350 
    351 	if (len == -1)
    352 		len = strlen(str);
    353 
    354 	if (!_sdp_put_ext(SDP_DATA_STR, data, len))
    355 		return false;
    356 
    357 	memcpy(data->next, str, len);
    358 	data->next += len;
    359 	return true;
    360 }
    361 
    362 bool
    363 sdp_put_url(sdp_data_t *data, const char *url, ssize_t len)
    364 {
    365 
    366 	if (len == -1)
    367 		len = strlen(url);
    368 
    369 	if (!_sdp_put_ext(SDP_DATA_URL, data, len))
    370 		return false;
    371 
    372 	memcpy(data->next, url, len);
    373 	data->next += len;
    374 	return true;
    375 }
    376