OSDN Git Service

gobex: Add header encoding support
authorJohan Hedberg <johan.hedberg@intel.com>
Wed, 22 Jun 2011 10:51:45 +0000 (13:51 +0300)
committerMarcel Holtmann <marcel@holtmann.org>
Tue, 4 Dec 2012 21:21:55 +0000 (22:21 +0100)
gobex/gobex.c
gobex/gobex.h
unit/test-gobex.c

index fcf662d..7e6cf52 100644 (file)
@@ -58,6 +58,74 @@ struct _GObex {
        GQueue *req_queue;
 };
 
+static glong utf8_to_utf16(gunichar2 **utf16, const char *utf8) {
+       glong utf16_len;
+       int i;
+
+       if (*utf8 == '\0') {
+               *utf16 = NULL;
+               return 0;
+       }
+
+       *utf16 = g_utf8_to_utf16(utf8, -1, NULL, &utf16_len, NULL);
+       if (*utf16 == NULL)
+               return -1;
+
+       /* g_utf8_to_utf16 produces host-byteorder UTF-16,
+        * but OBEX requires network byteorder (big endian) */
+       for (i = 0; i < utf16_len; i++)
+               (*utf16)[i] = htobe16((*utf16)[i]);
+
+       utf16_len = (utf16_len + 1) << 1;
+
+       return utf16_len;
+}
+
+size_t g_obex_header_encode(GObexHeader *header, void *hdr_ptr, size_t buf_len)
+{
+       uint8_t *buf = hdr_ptr;
+       uint16_t u16;
+       uint32_t u32;
+       gunichar2 *utf16;
+       glong utf16_len;
+
+       if (buf_len < header->hlen)
+               return 0;
+
+       buf[0] = header->id;
+
+       switch (G_OBEX_HDR_TYPE(header->id)) {
+       case G_OBEX_HDR_TYPE_UNICODE:
+               utf16_len = utf8_to_utf16(&utf16, header->v.string);
+               if (utf16_len < 0 || (uint16_t) utf16_len > buf_len)
+                       return 0;
+               u16 = htobe16(utf16_len + 3);
+               memcpy(&buf[1], &u16, sizeof(u16));
+               memcpy(&buf[3], utf16, utf16_len);
+               g_free(utf16);
+               break;
+       case G_OBEX_HDR_TYPE_BYTES:
+               u16 = htobe16(header->hlen);
+               memcpy(&buf[1], &u16, sizeof(u16));
+               if (header->extdata)
+                       memcpy(&buf[3], header->v.extdata, header->vlen);
+               else
+                       memcpy(&buf[3], header->v.data, header->vlen);
+               break;
+       case G_OBEX_HDR_TYPE_UINT8:
+               buf[1] = header->v.u8;
+               break;
+       case G_OBEX_HDR_TYPE_UINT32:
+               u32 = htobe32(header->v.u32);
+               memcpy(&buf[1], &u32, sizeof(u32));
+               break;
+       default:
+               g_assert_not_reached();
+       }
+
+       return header->hlen;
+}
+
 GObexHeader *g_obex_header_parse(const void *data, size_t len,
                                                gboolean copy, size_t *parsed)
 {
index b49adfe..df95ede 100644 (file)
@@ -66,6 +66,7 @@ typedef struct _GObex GObex;
 typedef struct _GObexRequest GObexRequest;
 typedef struct _GObexHeader GObexHeader;
 
+size_t g_obex_header_encode(GObexHeader *header, void *hdr_ptr, size_t buf_len);
 GObexHeader *g_obex_header_parse(const void *data, size_t len,
                                                gboolean copy, size_t *parsed);
 void g_obex_header_free(GObexHeader *header);
index 480847d..e7c56f2 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include <unistd.h>
+#include <string.h>
 
 #include <gobex/gobex.h>
 
@@ -39,6 +40,66 @@ static GObex *create_gobex(int fd)
        return g_obex_new(io);
 }
 
+static void dump_bytes(uint8_t *buf, size_t buf_len)
+{
+       size_t i;
+
+       for (i = 0; i < buf_len; i++)
+               g_print("%02x ", buf[i]);
+
+       g_print("\n");
+}
+
+static void parse_and_decode(uint8_t *buf, size_t buf_len)
+{
+       GObexHeader *header;
+       uint8_t encoded[1024];
+       size_t len;
+
+       header = g_obex_header_parse(buf, buf_len, FALSE, &len);
+       g_assert(header != NULL);
+       g_assert_cmpuint(len, ==, buf_len);
+
+       len = g_obex_header_encode(header, encoded, sizeof(encoded));
+
+       g_obex_header_free(header);
+
+       if (len != buf_len)
+               goto failed;
+
+       if (memcmp(encoded, buf, len) != 0)
+               goto failed;
+
+       return;
+
+failed:
+       g_print("\nIn:  ");
+       dump_bytes(buf, buf_len);
+       g_print("Out: ");
+       dump_bytes(encoded, len);
+       g_assert(0);
+}
+
+static void test_header_encode_connid(void)
+{
+       parse_and_decode(hdr_connid, sizeof(hdr_connid));
+}
+
+static void test_header_encode_name(void)
+{
+       parse_and_decode(hdr_name, sizeof(hdr_name));
+}
+
+static void test_header_encode_body(void)
+{
+       parse_and_decode(hdr_body, sizeof(hdr_body));
+}
+
+static void test_header_encode_actionid(void)
+{
+       parse_and_decode(hdr_actionid, sizeof(hdr_actionid));
+}
+
 static void test_parse_header_connid(void)
 {
        GObexHeader *header;
@@ -220,6 +281,14 @@ int main(int argc, char *argv[])
        g_test_add_func("/gobex/test_parse_header_multi",
                                                test_parse_header_multi);
 
+       g_test_add_func("/gobex/test_header_encode_connid",
+                                               test_header_encode_connid);
+       g_test_add_func("/gobex/test_header_encode_name",
+                                               test_header_encode_name);
+       g_test_add_func("/gobex/test_header_encode_body",
+                                               test_header_encode_body);
+       g_test_add_func("/gobex/test_header_encode_connid",
+                                               test_header_encode_actionid);
        g_test_run();
 
        return 0;