From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx> GObexApparam abstract the handling of application parameter tags, it can be used to read/parse application parameter header data using g_obex_apparam_get_* functions or to generate the data using g_obex_apparam_set_*. --- Makefile.am | 3 +- gobex/gobex-apparam.c | 314 ++++++++++++++++++++++++++++++++++++++++++++++++++ gobex/gobex-apparam.h | 59 ++++++++++ 3 files changed, 375 insertions(+), 1 deletion(-) create mode 100644 gobex/gobex-apparam.c create mode 100644 gobex/gobex-apparam.h diff --git a/Makefile.am b/Makefile.am index 97a1553..a1b4da0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -20,7 +20,8 @@ gobex_sources = gobex/gobex.h gobex/gobex.c \ gobex/gobex-defs.h gobex/gobex-defs.c \ gobex/gobex-packet.c gobex/gobex-packet.h \ gobex/gobex-header.c gobex/gobex-header.h \ - gobex/gobex-transfer.c gobex/gobex-debug.h + gobex/gobex-transfer.c gobex/gobex-debug.h \ + gobex/gobex-apparam.h gobex/gobex-apparam.c noinst_PROGRAMS = libexec_PROGRAMS = diff --git a/gobex/gobex-apparam.c b/gobex/gobex-apparam.c new file mode 100644 index 0000000..09bf034 --- /dev/null +++ b/gobex/gobex-apparam.c @@ -0,0 +1,314 @@ +/* + * + * OBEX library with GLib integration + * + * Copyright (C) 2012 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> +#include <unistd.h> +#include <errno.h> + +#include "gobex-apparam.h" + +struct _GObexApparam { + GHashTable *tags; +}; + +struct apparam_tag { + guint8 id; + guint8 len; + union { + /* Data is stored in network order */ + char string[0]; + guint8 data[0]; + guint8 u8; + guint16 u16; + guint32 u32; + guint64 u64; + } value; +} __attribute__ ((packed)); + +static struct apparam_tag *tag_new(guint8 id, guint8 len, const void *data) +{ + struct apparam_tag *tag; + + tag = g_malloc0(2 + len); + tag->id = id; + tag->len = len; + memcpy(tag->value.data, data, len); + + return tag; +} + +static GObexApparam *g_obex_apparam_new(void) +{ + GObexApparam *apparam; + + apparam = g_new0(GObexApparam, 1); + apparam->tags = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, g_free); + + return apparam; +} + +static struct apparam_tag *apparam_tag_decode(const void *data, gsize size, + gsize *parsed) +{ + struct apparam_tag *tag; + const guint8 *ptr = data; + guint8 id; + guint8 len; + + if (size < 2) + return NULL; + + id = ptr[0]; + len = ptr[1]; + + if (len > size - 2) + return NULL; + + tag = tag_new(id, len, ptr + 2); + if (tag == NULL) + return NULL; + + *parsed = 2 + tag->len; + + return tag; +} + +GObexApparam *g_obex_apparam_decode(const void *data, gsize size) +{ + GObexApparam *apparam; + GHashTable *tags; + gsize count = 0; + + if (size < 2) + return NULL; + + apparam = g_obex_apparam_new(); + + tags = apparam->tags; + while (count < size) { + struct apparam_tag *tag; + gsize parsed; + + tag = apparam_tag_decode(data + count, size - count, &parsed); + if (tag == NULL) + break; + + g_hash_table_insert(tags, GUINT_TO_POINTER(tag->id), tag); + + count += parsed; + } + + if (count != size) { + g_obex_apparam_free(apparam); + return NULL; + } + + return apparam; +} + +static gssize tag_encode(struct apparam_tag *tag, void *buf, gsize len) +{ + gsize count = 2 + tag->len; + + if (len < count) + return -ENOBUFS; + + memcpy(buf, tag, count); + + return count; +} + +gssize g_obex_apparam_encode(GObexApparam *apparam, void *buf, gsize len) +{ + gsize count = 0; + gssize ret; + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init(&iter, apparam->tags); + while (g_hash_table_iter_next(&iter, &key, &value)) { + struct apparam_tag *tag = value; + + ret = tag_encode(tag, buf + count, len - count); + if (ret < 0) + return ret; + + count += ret; + } + + return count; +} + +GObexApparam *g_obex_apparam_set_bytes(GObexApparam *apparam, guint8 id, + const void *value, gsize len) +{ + struct apparam_tag *tag; + + if (apparam == NULL) + apparam = g_obex_apparam_new(); + + tag = tag_new(id, len, value); + g_hash_table_replace(apparam->tags, GUINT_TO_POINTER(id), tag); + + return apparam; +} + +GObexApparam *g_obex_apparam_set_uint8(GObexApparam *apparam, guint8 id, + guint8 value) +{ + return g_obex_apparam_set_bytes(apparam, id, &value, 1); +} + +GObexApparam *g_obex_apparam_set_uint16(GObexApparam *apparam, guint8 id, + guint16 value) +{ + guint16 num = g_htons(value); + + return g_obex_apparam_set_bytes(apparam, id, &num, 2); +} + +GObexApparam *g_obex_apparam_set_uint32(GObexApparam *apparam, guint8 id, + guint32 value) +{ + guint32 num = g_htonl(value); + + return g_obex_apparam_set_bytes(apparam, id, &num, 4); +} + +GObexApparam *g_obex_apparam_set_uint64(GObexApparam *apparam, guint8 id, + guint64 value) +{ + guint64 num = GUINT64_TO_BE(value); + + return g_obex_apparam_set_bytes(apparam, id, &num, 8); +} + +GObexApparam *g_obex_apparam_set_string(GObexApparam *apparam, guint8 id, + const char *value) +{ + gsize len; + + len = strlen(value) + 1; + if (len > G_MAXUINT8) { + ((char *) value)[G_MAXUINT8 - 1] = '\0'; + len = G_MAXUINT8; + } + + return g_obex_apparam_set_bytes(apparam, id, value, len); +} + +gboolean g_obex_apparam_get_uint8(GObexApparam *apparam, guint8 id, + guint8 *dest) +{ + struct apparam_tag *tag; + + tag = g_hash_table_lookup(apparam->tags, GUINT_TO_POINTER(id)); + if (tag == NULL) + return FALSE; + + *dest = tag->value.u8; + return TRUE; +} + +gboolean g_obex_apparam_get_uint16(GObexApparam *apparam, guint8 id, + guint16 *dest) +{ + struct apparam_tag *tag; + + tag = g_hash_table_lookup(apparam->tags, GUINT_TO_POINTER(id)); + if (tag == NULL) + return FALSE; + + if (tag->len < sizeof(*dest)) + return FALSE; + + *dest = g_ntohs(tag->value.u16); + return TRUE; +} + +gboolean g_obex_apparam_get_uint32(GObexApparam *apparam, guint8 id, + guint32 *dest) +{ + struct apparam_tag *tag; + + tag = g_hash_table_lookup(apparam->tags, GUINT_TO_POINTER(id)); + if (tag == NULL) + return FALSE; + + if (tag->len < sizeof(*dest)) + return FALSE; + + *dest = g_ntohl(tag->value.u32); + return TRUE; +} + +gboolean g_obex_apparam_get_uint64(GObexApparam *apparam, guint8 id, + guint64 *dest) +{ + struct apparam_tag *tag; + + tag = g_hash_table_lookup(apparam->tags, GUINT_TO_POINTER(id)); + if (tag == NULL) + return FALSE; + + if (tag->len < sizeof(*dest)) + return FALSE; + + *dest = GUINT64_FROM_BE(tag->value.u64); + return TRUE; +} + +char *g_obex_apparam_get_string(GObexApparam *apparam, guint8 id) +{ + struct apparam_tag *tag; + + tag = g_hash_table_lookup(apparam->tags, GUINT_TO_POINTER(id)); + if (tag == NULL) + return NULL; + + return g_strndup(tag->value.string, tag->len); +} + +gboolean g_obex_apparam_get_bytes(GObexApparam *apparam, guint8 id, + const guint8 **val, gsize *len) +{ + struct apparam_tag *tag; + + tag = g_hash_table_lookup(apparam->tags, GUINT_TO_POINTER(id)); + if (tag == NULL) + return FALSE; + + *len = tag->len; + *val = tag->value.data; + + return TRUE; +} + +void g_obex_apparam_free(GObexApparam *apparam) +{ + g_hash_table_unref(apparam->tags); + g_free(apparam); +} diff --git a/gobex/gobex-apparam.h b/gobex/gobex-apparam.h new file mode 100644 index 0000000..46e20d2 --- /dev/null +++ b/gobex/gobex-apparam.h @@ -0,0 +1,59 @@ +/* + * + * OBEX library with GLib integration + * + * Copyright (C) 2012 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __GOBEX_APPARAM_H +#define __GOBEX_APPARAM_H + +#include <glib.h> + +typedef struct _GObexApparam GObexApparam; + +GObexApparam *g_obex_apparam_decode(const void *data, gsize size); +gssize g_obex_apparam_encode(GObexApparam *apparam, void *buf, gsize size); + +GObexApparam *g_obex_apparam_set_bytes(GObexApparam *apparam, guint8 id, + const void *value, gsize size); +GObexApparam *g_obex_apparam_set_uint8(GObexApparam *apparam, guint8 id, + guint8 value); +GObexApparam *g_obex_apparam_set_uint16(GObexApparam *apparam, guint8 id, + guint16 value); +GObexApparam *g_obex_apparam_set_uint32(GObexApparam *apparam, guint8 id, + guint32 value); +GObexApparam *g_obex_apparam_set_uint64(GObexApparam *apparam, guint8 id, + guint64 value); +GObexApparam *g_obex_apparam_set_string(GObexApparam *apparam, guint8 id, + const char *value); + +gboolean g_obex_apparam_get_bytes(GObexApparam *apparam, guint8 id, + const guint8 **val, gsize *len); +gboolean g_obex_apparam_get_uint8(GObexApparam *apparam, guint8 id, + guint8 *value); +gboolean g_obex_apparam_get_uint16(GObexApparam *apparam, guint8 id, + guint16 *value); +gboolean g_obex_apparam_get_uint32(GObexApparam *apparam, guint8 id, + guint32 *value); +gboolean g_obex_apparam_get_uint64(GObexApparam *apparam, guint8 id, + guint64 *value); +char *g_obex_apparam_get_string(GObexApparam *apparam, guint8 id); + +void g_obex_apparam_free(GObexApparam *apparam); + +#endif /* __GOBEX_APPARAM_H */ -- 1.7.11.2 -- To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html