OSDN Git Service

gobex: Make on-demand header callbacks able to fail cleanly
authorJohan Hedberg <johan.hedberg@intel.com>
Tue, 5 Jul 2011 09:33:57 +0000 (12:33 +0300)
committerMarcel Holtmann <marcel@holtmann.org>
Tue, 4 Dec 2012 21:21:59 +0000 (22:21 +0100)
gobex/gobex-header.c
gobex/gobex-header.h
gobex/gobex-packet.c
unit/test-gobex-header.c
unit/test-gobex-packet.c
unit/test-gobex.c

index 6d0136c..3446bb9 100644 (file)
@@ -83,13 +83,17 @@ static const guint8 *get_bytes(void *to, const guint8 *from, gsize count)
        return (from + count);
 }
 
-static gsize get_data(GObexHeader *header, guint8 *buf, gsize len)
+static gssize get_data(GObexHeader *header, guint8 *buf, gsize len)
 {
        guint16 u16;
+       gssize ret;
 
-       header->vlen = header->get_data(header, buf + 2, len - 2,
+       ret = header->get_data(header, buf + 2, len - 2,
                                                header->get_data_data);
+       if (ret < 0)
+               return ret;
 
+       header->vlen = ret;
        header->hlen = header->vlen + 3;
        u16 = g_htons(header->hlen);
        memcpy(buf, &u16, sizeof(u16));
@@ -97,7 +101,7 @@ static gsize get_data(GObexHeader *header, guint8 *buf, gsize len)
        return header->hlen;
 }
 
-gsize g_obex_header_encode(GObexHeader *header, void *buf, gsize buf_len)
+gssize g_obex_header_encode(GObexHeader *header, void *buf, gsize buf_len)
 {
        guint8 *ptr = buf;
        guint16 u16;
@@ -106,7 +110,7 @@ gsize g_obex_header_encode(GObexHeader *header, void *buf, gsize buf_len)
        glong utf16_len;
 
        if (buf_len < header->hlen)
-               return 0;
+               return -1;
 
        ptr = put_bytes(ptr, &header->id, sizeof(header->id));
 
@@ -114,7 +118,7 @@ gsize g_obex_header_encode(GObexHeader *header, void *buf, gsize buf_len)
        case G_OBEX_HDR_TYPE_UNICODE:
                utf16_len = utf8_to_utf16(&utf16, header->v.string);
                if (utf16_len < 0 || (guint16) utf16_len > buf_len)
-                       return 0;
+                       return -1;
                g_assert_cmpuint(utf16_len + 3, ==, header->hlen);
                u16 = g_htons(utf16_len + 3);
                ptr = put_bytes(ptr, &u16, sizeof(u16));
index 7ea3193..b25051f 100644 (file)
@@ -55,7 +55,7 @@
 
 typedef struct _GObexHeader GObexHeader;
 
-typedef guint16 (*GObexHeaderDataFunc) (GObexHeader *header, void *buf,
+typedef gssize (*GObexHeaderDataFunc) (GObexHeader *header, void *buf,
                                                gsize len, gpointer user_data);
 
 gboolean g_obex_header_get_unicode(GObexHeader *header, const char **str);
@@ -76,7 +76,7 @@ GObexHeader *g_obex_header_new_uint32(guint8 id, guint32 val);
 guint8 g_obex_header_get_id(GObexHeader *header);
 guint16 g_obex_header_get_length(GObexHeader *header);
 
-gsize g_obex_header_encode(GObexHeader *header, void *hdr_ptr, gsize buf_len);
+gssize g_obex_header_encode(GObexHeader *header, void *buf, gsize buf_len);
 GObexHeader *g_obex_header_decode(const void *data, gsize len,
                                GObexDataPolicy data_policy, gsize *parsed,
                                GError **err);
index 29a6aa2..16d4b7a 100644 (file)
@@ -281,9 +281,16 @@ gssize g_obex_packet_encode(GObexPacket *pkt, guint8 *buf, gsize len)
 
        for (l = pkt->headers; l != NULL; l = g_slist_next(l)) {
                GObexHeader *hdr = l->data;
+               gssize ret;
+
                if (count >= len)
                        return -ENOBUFS;
-               count += g_obex_header_encode(hdr, buf + count, len - count);
+
+               ret = g_obex_header_encode(hdr, buf + count, len - count);
+               if (ret < 0)
+                       return ret;
+
+               count += ret;
        }
 
        u16 = g_htons(count);
index 61536e2..bf69abb 100644 (file)
@@ -130,7 +130,7 @@ static void test_header_uint32(void)
        g_obex_header_free(header);
 }
 
-static guint16 get_body_data(GObexHeader *header, void *buf, gsize len,
+static gssize get_body_data(GObexHeader *header, void *buf, gsize len,
                                                        gpointer user_data)
 {
        uint8_t body_data[] = { 1, 2, 3, 4 };
@@ -156,6 +156,27 @@ static void test_header_on_demand(void)
        g_obex_header_free(header);
 }
 
+static gssize get_body_data_fail(GObexHeader *header, void *buf, gsize len,
+                                                       gpointer user_data)
+{
+       return -1;
+}
+
+static void test_header_on_demand_fail(void)
+{
+       GObexHeader *header;
+       uint8_t buf[1024];
+       gssize len;
+
+       header = g_obex_header_new_on_demand(G_OBEX_HDR_ID_BODY,
+                                               get_body_data_fail, NULL);
+
+       len = g_obex_header_encode(header, buf, sizeof(buf));
+       g_assert_cmpint(len, ==, -1);
+
+       g_obex_header_free(header);
+}
+
 static GObexHeader *parse_and_encode(uint8_t *buf, size_t buf_len)
 {
        GObexHeader *header;
@@ -485,6 +506,8 @@ int main(int argc, char *argv[])
        g_test_add_func("/gobex/test_header_uint32", test_header_uint32);
 
        g_test_add_func("/gobex/test_header_on_demand", test_header_on_demand);
+       g_test_add_func("/gobex/test_header_on_demand_fail",
+                                               test_header_on_demand_fail);
 
        g_test_run();
 
index 501d924..33be55d 100644 (file)
@@ -144,7 +144,7 @@ static void test_decode_encode(void)
        g_obex_packet_free(pkt);
 }
 
-static guint16 get_body_data(GObexHeader *header, void *buf, gsize len,
+static gssize get_body_data(GObexHeader *header, void *buf, gsize len,
                                                        gpointer user_data)
 {
        uint8_t data[] = { 1, 2, 3, 4 };
@@ -178,6 +178,32 @@ static void test_encode_on_demand(void)
        g_obex_packet_free(pkt);
 }
 
+static gssize get_body_data_fail(GObexHeader *header, void *buf, gsize len,
+                                                       gpointer user_data)
+{
+       return -1;
+}
+
+static void test_encode_on_demand_fail(void)
+{
+       GObexPacket *pkt;
+       GObexHeader *hdr;
+       uint8_t buf[255];
+       gssize len;
+
+       pkt = g_obex_packet_new(G_OBEX_OP_PUT, FALSE, NULL);
+
+       hdr = g_obex_header_new_on_demand(G_OBEX_HDR_ID_BODY,
+                                               get_body_data_fail, NULL);
+       g_obex_packet_add_header(pkt, hdr);
+
+       len = g_obex_packet_encode(pkt, buf, sizeof(buf));
+
+       g_assert_cmpint(len, ==, -1);
+
+       g_obex_packet_free(pkt);
+}
+
 int main(int argc, char *argv[])
 {
        g_test_init(&argc, &argv, NULL);
@@ -194,6 +220,8 @@ int main(int argc, char *argv[])
        g_test_add_func("/gobex/test_encode_pkt", test_decode_encode);
 
        g_test_add_func("/gobex/test_encode_on_demand", test_encode_on_demand);
+       g_test_add_func("/gobex/test_encode_on_demand_fail",
+                                               test_encode_on_demand_fail);
 
        g_test_run();
 
index 5d65dde..1fb74b5 100644 (file)
@@ -528,7 +528,7 @@ static void test_send_connect(int transport_type)
 
        create_endpoints(&obex, &io, transport_type);
 
-       r.err = NULL;
+       memset(&r, 0, sizeof(r));
        r.buf = pkt_connect_req;
        r.len = sizeof(pkt_connect_req);
 
@@ -570,7 +570,7 @@ static void test_send_connect_pkt(void)
        test_send_connect(SOCK_SEQPACKET);
 }
 
-static guint16 get_body_data(GObexHeader *header, void *buf, gsize len,
+static gssize get_body_data(GObexHeader *header, void *buf, gsize len,
                                                        gpointer user_data)
 {
        uint8_t data[] = { 1, 2, 3, 4 };
@@ -580,7 +580,14 @@ static guint16 get_body_data(GObexHeader *header, void *buf, gsize len,
        return sizeof(data);
 }
 
-static void test_send_on_demand(int transport_type)
+static gssize get_body_data_fail(GObexHeader *header, void *buf, gsize len,
+                                                       gpointer user_data)
+{
+       g_main_loop_quit(mainloop);
+       return -1;
+}
+
+static void test_send_on_demand(int transport_type, GObexHeaderDataFunc func)
 {
        struct rcv_buf_info r;
        GIOChannel *io;
@@ -592,14 +599,13 @@ static void test_send_on_demand(int transport_type)
 
        create_endpoints(&obex, &io, transport_type);
 
-       r.err = NULL;
+       memset(&r, 0, sizeof(r));
        r.buf = pkt_put_body;
        r.len = sizeof(pkt_put_body);
 
        req = g_obex_packet_new(G_OBEX_OP_PUT, FALSE, NULL);
 
-       hdr = g_obex_header_new_on_demand(G_OBEX_HDR_ID_BODY,
-                                               get_body_data, NULL);
+       hdr = g_obex_header_new_on_demand(G_OBEX_HDR_ID_BODY, func, &r);
        g_obex_packet_add_header(req, hdr);
 
        g_obex_send(obex, req, &r.err);
@@ -627,12 +633,22 @@ static void test_send_on_demand(int transport_type)
 
 static void test_send_on_demand_stream(void)
 {
-       test_send_on_demand(SOCK_STREAM);
+       test_send_on_demand(SOCK_STREAM, get_body_data);
 }
 
 static void test_send_on_demand_pkt(void)
 {
-       test_send_on_demand(SOCK_SEQPACKET);
+       test_send_on_demand(SOCK_SEQPACKET, get_body_data);
+}
+
+static void test_send_on_demand_fail_stream(void)
+{
+       test_send_on_demand(SOCK_STREAM, get_body_data_fail);
+}
+
+static void test_send_on_demand_fail_pkt(void)
+{
+       test_send_on_demand(SOCK_SEQPACKET, get_body_data_fail);
 }
 
 static void handle_connect_req(GObex *obex, GObexPacket *req,
@@ -802,6 +818,10 @@ int main(int argc, char *argv[])
                                                test_send_on_demand_stream);
        g_test_add_func("/gobex/test_send_on_demand_pkt",
                                                test_send_on_demand_pkt);
+       g_test_add_func("/gobex/test_send_on_demand_fail_stream",
+                                       test_send_on_demand_fail_stream);
+       g_test_add_func("/gobex/test_send_on_demand_fail_pkt",
+                                       test_send_on_demand_fail_pkt);
        g_test_add_func("/gobex/test_send_connect_req_stream",
                                        test_send_connect_req_stream);
        g_test_add_func("/gobex/test_send_connect_req_pkt",