2 * This file is part of buxton.
4 * Copyright (C) 2013 Intel Corporation
6 * buxton is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation; either version 2.1
9 * of the License, or (at your option) any later version.
26 #include "serialize.h"
31 size_t buxton_serialize(BuxtonData *source, BuxtonString *label,
43 /* DataType + length field */
44 size = sizeof(BuxtonDataType) + (sizeof(uint32_t) * 2) + label->length;
46 /* Total size will be different for string data */
47 switch (source->type) {
49 length = source->store.d_string.length;
52 length = sizeof(source->store);
58 /* Allocate memory big enough to hold all information */
64 /* Write the entire BuxtonDataType to the first block */
65 memcpy(data, &(source->type), sizeof(BuxtonDataType));
66 offset += sizeof(BuxtonDataType);
68 /* Write out the length of the label field */
69 memcpy(data+offset, &(label->length), sizeof(uint32_t));
70 offset += sizeof(uint32_t);
72 /* Write out the length of the data field */
73 memcpy(data+offset, &length, sizeof(uint32_t));
74 offset += sizeof(uint32_t);
76 /* Write out the label field */
77 memcpy(data+offset, label->value, label->length);
78 offset += label->length;
80 /* Write the data itself */
81 switch (source->type) {
83 memcpy(data+offset, source->store.d_string.value, length);
86 memcpy(data+offset, &(source->store.d_int32), sizeof(int32_t));
89 memcpy(data+offset, &(source->store.d_uint32), sizeof(uint32_t));
92 memcpy(data+offset, &(source->store.d_int64), sizeof(int64_t));
95 memcpy(data+offset, &(source->store.d_uint64), sizeof(uint64_t));
98 memcpy(data+offset, &(source->store.d_float), sizeof(float));
101 memcpy(data+offset, &(source->store.d_double), sizeof(double));
104 memcpy(data+offset, &(source->store.d_boolean), sizeof(bool));
113 assert(ret >= BXT_MINIMUM_SIZE);
118 void buxton_deserialize(uint8_t *source, BuxtonData *target,
129 /* Retrieve the BuxtonDataType */
130 type = *(BuxtonDataType*)source;
131 offset += sizeof(BuxtonDataType);
133 /* Retrieve the length of the label */
134 label->length = *(uint32_t*)(source+offset);
135 offset += sizeof(uint32_t);
137 /* Retrieve the length of the value */
138 length = *(uint32_t*)(source+offset);
139 offset += sizeof(uint32_t);
141 /* Retrieve the label */
142 label->value = malloc(label->length);
143 if (label->length > 0 && !label->value) {
146 memcpy(label->value, source+offset, label->length);
147 offset += label->length;
151 /* User must free the string */
152 target->store.d_string.value = malloc(length);
153 if (!target->store.d_string.value) {
156 memcpy(target->store.d_string.value, source+offset, length);
157 target->store.d_string.length = (uint32_t)length;
160 target->store.d_int32 = *(int32_t*)(source+offset);
163 target->store.d_uint32 = *(uint32_t*)(source+offset);
166 target->store.d_int64 = *(int64_t*)(source+offset);
169 target->store.d_uint64 = *(uint64_t*)(source+offset);
172 target->store.d_float = *(float*)(source+offset);
175 memcpy(&target->store.d_double, source + offset, sizeof(double));
178 target->store.d_boolean = *(bool*)(source+offset);
181 buxton_debug("Invalid BuxtonDataType: %lu\n", type);
189 size_t buxton_serialize_message(uint8_t **dest, BuxtonControlMessage message,
190 uint32_t msgid, BuxtonArray *list)
193 uint8_t *data = NULL;
198 uint16_t control, msg;
202 buxton_debug("Serializing message...\n");
204 if (list->len > BUXTON_MESSAGE_MAX_PARAMS) {
209 if (message >= BUXTON_CONTROL_MAX || message < BUXTON_CONTROL_SET) {
216 * control code + control message (uint16_t * 2) +
217 * message size (uint32_t) +
218 * message id (uint32_t) +
219 * param count (uint32_t)
221 data = malloc0(sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t) +
228 control = BUXTON_CONTROL_CODE;
229 memcpy(data, &control, sizeof(uint16_t));
230 offset += sizeof(uint16_t);
232 msg = (uint16_t)message;
233 memcpy(data+offset, &msg, sizeof(uint16_t));
234 offset += sizeof(uint16_t);
236 /* Save room for final size */
237 offset += sizeof(uint32_t);
239 memcpy(data+offset, &msgid, sizeof(uint32_t));
240 offset += sizeof(uint32_t);
242 /* Now write the parameter count */
243 memcpy(data+offset, &(list->len), sizeof(uint32_t));
244 offset += sizeof(uint32_t);
248 /* Deal with parameters */
251 for (i=0; i < list->len; i++) {
252 param = buxton_array_get(list, i);
258 switch (param->type) {
260 p_length = param->store.d_string.length;
263 p_length = sizeof(int32_t);
266 p_length = sizeof(uint32_t);
269 p_length = sizeof(int64_t);
272 p_length = sizeof(uint64_t);
275 p_length = sizeof(float);
278 p_length = sizeof(double);
281 p_length = sizeof(bool);
285 buxton_log("Invalid parameter type %lu\n", param->type);
289 buxton_debug("offset: %lu\n", offset);
290 buxton_debug("value length: %lu\n", p_length);
292 /* Need to allocate enough room to hold this data */
293 size += sizeof(uint16_t) + sizeof(uint32_t) + p_length;
295 if (curSize < size) {
296 if (!(data = greedy_realloc((void**)&data, &curSize, size))) {
300 memzero(data+offset, size - offset);
304 memcpy(data+offset, &(param->type), sizeof(uint16_t));
305 offset += sizeof(uint16_t);
307 /* Write out the length of value */
308 memcpy(data+offset, &p_length, sizeof(uint32_t));
309 offset += sizeof(uint32_t);
311 switch (param->type) {
313 memcpy(data+offset, param->store.d_string.value, p_length);
316 memcpy(data+offset, &(param->store.d_int32), sizeof(int32_t));
319 memcpy(data+offset, &(param->store.d_uint32), sizeof(uint32_t));
322 memcpy(data+offset, &(param->store.d_int64), sizeof(int64_t));
325 memcpy(data+offset, &(param->store.d_uint64), sizeof(uint64_t));
328 memcpy(data+offset, &(param->store.d_float), sizeof(float));
331 memcpy(data+offset, &(param->store.d_double), sizeof(double));
334 memcpy(data+offset, &(param->store.d_boolean), sizeof(bool));
337 /* already tested this above, can't get here
345 memcpy(data+BUXTON_LENGTH_OFFSET, &offset, sizeof(uint32_t));
356 buxton_debug("Serializing returned:%lu\n", ret);
360 ssize_t buxton_deserialize_message(uint8_t *data,
361 BuxtonControlMessage *r_message,
362 size_t size, uint32_t *r_msgid,
367 size_t min_length = BUXTON_MESSAGE_HEADER_LENGTH;
368 uint16_t control, message;
369 size_t n_params, c_param, c_length;
370 BuxtonDataType c_type = 0;
371 BuxtonData *k_list = NULL;
379 buxton_debug("Deserializing message...\n");
380 buxton_debug("size=%lu\n", size);
382 if (size < min_length) {
387 /* Copy the control code */
388 control = *(uint16_t*)data;
389 offset += sizeof(uint16_t);
391 /* Check this is a valid buxton message */
392 if (control != BUXTON_CONTROL_CODE) {
397 /* Obtain the control message */
398 message = *(BuxtonControlMessage*)(data+offset);
399 offset += sizeof(uint16_t);
401 /* Ensure control message is in valid range */
402 if (message <= BUXTON_CONTROL_MIN || message >= BUXTON_CONTROL_MAX) {
407 /* Skip size since our caller got this already */
408 offset += sizeof(uint32_t);
410 /* Obtain the message id */
411 msgid = *(uint32_t*)(data+offset);
412 offset += sizeof(uint32_t);
414 /* Obtain number of parameters */
415 n_params = *(uint32_t*)(data+offset);
416 offset += sizeof(uint32_t);
417 buxton_debug("total params: %d\n", n_params);
419 if (n_params > BUXTON_MESSAGE_MAX_PARAMS) {
424 k_list = malloc0(sizeof(BuxtonData)*n_params);
425 if (n_params && !k_list) {
430 memzero(&c_data, sizeof(BuxtonData));
432 for (c_param = 0; c_param < n_params; c_param++) {
433 buxton_debug("param: %d\n", c_param + 1);
434 buxton_debug("offset=%lu\n", offset);
435 /* Don't read past the end of the buffer */
436 if (offset + sizeof(uint16_t) + sizeof(uint32_t) > size) {
441 /* Now unpack type */
442 memcpy(&c_type, data+offset, sizeof(uint16_t));
443 offset += sizeof(uint16_t);
445 if (c_type >= BUXTON_TYPE_MAX || c_type <= BUXTON_TYPE_MIN) {
450 /* Retrieve the length of the value */
451 c_length = *(uint32_t*)(data+offset);
452 if (c_length == 0 && c_type != STRING) {
456 offset += sizeof(uint32_t);
457 buxton_debug("value length: %lu\n", c_length);
459 /* Don't try to read past the end of our buffer */
460 if (offset + c_length > size) {
468 c_data.store.d_string.value = malloc(c_length);
469 if (!c_data.store.d_string.value) {
473 memcpy(c_data.store.d_string.value, data+offset, c_length);
474 c_data.store.d_string.length = (uint32_t)c_length;
475 if (c_data.store.d_string.value[c_length-1] != 0x00) {
477 buxton_debug("buxton_deserialize_message(): Garbage message\n");
478 free(c_data.store.d_string.value);
482 c_data.store.d_string.value = NULL;
483 c_data.store.d_string.length = 0;
487 c_data.store.d_int32 = *(int32_t*)(data+offset);
490 c_data.store.d_uint32 = *(uint32_t*)(data+offset);
493 c_data.store.d_int64 = *(int64_t*)(data+offset);
496 c_data.store.d_uint64 = *(uint64_t*)(data+offset);
499 c_data.store.d_float = *(float*)(data+offset);
502 memcpy(&c_data.store.d_double, data + offset, sizeof(double));
505 c_data.store.d_boolean = *(bool*)(data+offset);
511 c_data.type = c_type;
512 k_list[c_param] = c_data;
513 memzero(&c_data, sizeof(BuxtonData));
516 *r_message = message;
525 ret = (ssize_t)n_params;
531 buxton_debug("Deserializing returned:%i\n", ret);
535 size_t buxton_get_message_size(uint8_t *data, size_t size)
541 if (size < BUXTON_MESSAGE_HEADER_LENGTH) {
545 r_size = *(uint32_t*)(data + BUXTON_LENGTH_OFFSET);
547 if (r_size < BUXTON_MESSAGE_HEADER_LENGTH) {
554 void include_serialize(void)
560 * Editor modelines - http://www.wireshark.org/tools/modelines.html
565 * indent-tabs-mode: t
568 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
569 * :indentSize=8:tabSize=8:noTabs=false: