OSDN Git Service

gobex: Add initial GError support
authorJohan Hedberg <johan.hedberg@intel.com>
Wed, 29 Jun 2011 10:15:05 +0000 (13:15 +0300)
committerMarcel Holtmann <marcel@holtmann.org>
Tue, 4 Dec 2012 21:21:57 +0000 (22:21 +0100)
gobex/gobex-defs.c [new file with mode: 0644]
gobex/gobex-defs.h
gobex/gobex-header.c
gobex/gobex-header.h
gobex/gobex-packet.c
gobex/gobex-packet.h
gobex/gobex.c
unit/test-gobex-header.c
unit/test-gobex-packet.c

diff --git a/gobex/gobex-defs.c b/gobex/gobex-defs.c
new file mode 100644 (file)
index 0000000..f1f3b38
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ *
+ *  OBEX library with GLib integration
+ *
+ *  Copyright (C) 2011  Intel Corporation. All rights reserved.
+ *
+ *  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
+ *
+ */
+
+#include <glib.h>
+
+#include "gobex-defs.h"
+
+GQuark g_obex_error_quark(void)
+{
+       return g_quark_from_static_string("g-obex-error-quark");
+}
index ad8b046..76b274f 100644 (file)
 #ifndef __GOBEX_DEFS_H
 #define __GOBEX_DEFS_H
 
+#include <glib.h>
+
 typedef enum {
        G_OBEX_DATA_INHERIT,
        G_OBEX_DATA_COPY,
        G_OBEX_DATA_REF,
 } GObexDataPolicy;
 
+typedef enum {
+       G_OBEX_ERROR_PARSE_ERROR,
+       G_OBEX_ERROR_INVALID_ARGS,
+} GObexError;
+
+#define G_OBEX_ERROR g_obex_error_quark()
+GQuark g_obex_error_quark(void);
+
 #endif /* __GOBEX_DEFS_H */
index 949e48a..72ea5de 100644 (file)
@@ -127,15 +127,20 @@ gsize 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)
+                               GObexDataPolicy data_policy, gsize *parsed,
+                               GError **err)
 {
        GObexHeader *header;
        const guint8 *ptr = data;
        guint16 hdr_len;
        gsize str_len;
+       GError *conv_err = NULL;
 
-       if (len < 2)
+       if (len < 2) {
+               g_set_error(err, G_OBEX_ERROR, G_OBEX_ERROR_PARSE_ERROR,
+                                               "Too short header in packet");
                return NULL;
+       }
 
        header = g_new0(GObexHeader, 1);
 
@@ -147,14 +152,24 @@ GObexHeader *g_obex_header_decode(const void *data, gsize len,
                        goto failed;
                ptr = get_bytes(&hdr_len, ptr, sizeof(hdr_len));
                hdr_len = g_ntohs(hdr_len);
-               if (hdr_len > len || hdr_len < 5)
+               if (hdr_len > len || hdr_len < 5) {
+                       g_set_error(err, G_OBEX_ERROR,
+                                       G_OBEX_ERROR_PARSE_ERROR,
+                                       "Invalid unicode header length");
                        goto failed;
+               }
 
                header->v.string = g_convert((const char *) ptr, hdr_len - 5,
                                                "UTF8", "UTF16BE",
-                                               NULL, &str_len, NULL);
-               if (header->v.string == NULL)
+                                               NULL, &str_len, &conv_err);
+               if (header->v.string == NULL) {
+                       g_set_error(err, G_OBEX_ERROR,
+                                       G_OBEX_ERROR_PARSE_ERROR,
+                                       "Unicode conversion failed: %s",
+                                       conv_err->message);
+                       g_error_free(conv_err);
                        goto failed;
+               }
 
                header->vlen = (gsize) str_len;
                header->hlen = hdr_len;
@@ -163,12 +178,20 @@ GObexHeader *g_obex_header_decode(const void *data, gsize len,
 
                break;
        case G_OBEX_HDR_TYPE_BYTES:
-               if (len < 3)
+               if (len < 3) {
+                       g_set_error(err, G_OBEX_ERROR,
+                                       G_OBEX_ERROR_PARSE_ERROR,
+                                       "Too short byte array header");
                        goto failed;
+               }
                ptr = get_bytes(&hdr_len, ptr, sizeof(hdr_len));
                hdr_len = g_ntohs(hdr_len);
-               if (hdr_len > len)
+               if (hdr_len > len) {
+                       g_set_error(err, G_OBEX_ERROR,
+                                       G_OBEX_ERROR_PARSE_ERROR,
+                                       "Too long byte array header");
                        goto failed;
+               }
 
                header->vlen = hdr_len - 3;
                header->hlen = hdr_len;
@@ -182,6 +205,9 @@ GObexHeader *g_obex_header_decode(const void *data, gsize len,
                        header->v.extdata = ptr;
                        break;
                default:
+                       g_set_error(err, G_OBEX_ERROR,
+                                       G_OBEX_ERROR_INVALID_ARGS,
+                                       "Invalid data policy");
                        goto failed;
                }
 
@@ -195,8 +221,12 @@ GObexHeader *g_obex_header_decode(const void *data, gsize len,
                *parsed = 2;
                break;
        case G_OBEX_HDR_TYPE_UINT32:
-               if (len < 5)
+               if (len < 5) {
+                       g_set_error(err, G_OBEX_ERROR,
+                                       G_OBEX_ERROR_PARSE_ERROR,
+                                       "Too short uint32 header");
                        goto failed;
+               }
                header->vlen = 4;
                header->hlen = 5;
                ptr = get_bytes(&header->v.u32, ptr, sizeof(header->v.u32));
index b5b9100..1df7f14 100644 (file)
@@ -72,7 +72,8 @@ guint16 g_obex_header_get_length(GObexHeader *header);
 
 gsize g_obex_header_encode(GObexHeader *header, void *hdr_ptr, gsize buf_len);
 GObexHeader *g_obex_header_decode(const void *data, gsize len,
-                               GObexDataPolicy data_policy, gsize *parsed);
+                               GObexDataPolicy data_policy, gsize *parsed,
+                               GError **err);
 void g_obex_header_free(GObexHeader *header);
 
 #endif /* __GOBEX_HEADER_H */
index 12acb70..957e1cc 100644 (file)
@@ -145,7 +145,8 @@ void g_obex_packet_free(GObexPacket *pkt)
 }
 
 static gboolean parse_headers(GObexPacket *pkt, const void *data, gsize len,
-                                               GObexDataPolicy data_policy)
+                                               GObexDataPolicy data_policy,
+                                               GError **err)
 {
        const guint8 *buf = data;
 
@@ -153,7 +154,8 @@ static gboolean parse_headers(GObexPacket *pkt, const void *data, gsize len,
                GObexHeader *header;
                gsize parsed;
 
-               header = g_obex_header_decode(buf, len, data_policy, &parsed);
+               header = g_obex_header_decode(buf, len, data_policy, &parsed,
+                                                                       err);
                if (header == NULL)
                        return FALSE;
 
@@ -174,7 +176,8 @@ static const guint8 *get_bytes(void *to, const guint8 *from, gsize count)
 
 GObexPacket *g_obex_packet_decode(const void *data, gsize len,
                                                gsize header_offset,
-                                               GObexDataPolicy data_policy)
+                                               GObexDataPolicy data_policy,
+                                               GError **err)
 {
        const guint8 *buf = data;
        guint16 packet_len;
@@ -182,15 +185,28 @@ GObexPacket *g_obex_packet_decode(const void *data, gsize len,
        GObexPacket *pkt;
        gboolean final;
 
-       if (len < 3)
+       if (data_policy == G_OBEX_DATA_INHERIT) {
+               g_set_error(err, G_OBEX_ERROR, G_OBEX_ERROR_INVALID_ARGS,
+                                                       "Invalid data policy");
+               return NULL;
+       }
+
+       if (len < 3) {
+               g_set_error(err, G_OBEX_ERROR, G_OBEX_ERROR_PARSE_ERROR,
+                                       "Not enough data to decode packet");
                return NULL;
+       }
 
        buf = get_bytes(&opcode, buf, sizeof(opcode));
        buf = get_bytes(&packet_len, buf, sizeof(packet_len));
 
        packet_len = g_ntohs(packet_len);
-       if (packet_len < len)
+       if (packet_len != len) {
+               g_set_error(err, G_OBEX_ERROR, G_OBEX_ERROR_PARSE_ERROR,
+                               "Incorrect packet length (%u != %zu)",
+                               packet_len, len);
                return NULL;
+       }
 
        final = (opcode & G_OBEX_PACKET_FINAL) ? TRUE : FALSE;
        opcode &= ~G_OBEX_PACKET_FINAL;
@@ -200,20 +216,18 @@ GObexPacket *g_obex_packet_decode(const void *data, gsize len,
        if (header_offset == 0)
                goto headers;
 
-       if (3 + header_offset < len)
-               goto failed;
-
-       if (data_policy == G_OBEX_DATA_INHERIT)
-               goto failed;
-
-       if (!g_obex_packet_set_data(pkt, buf, header_offset, data_policy))
+       if (3 + header_offset < len) {
+               g_set_error(err, G_OBEX_ERROR, G_OBEX_ERROR_PARSE_ERROR,
+                                       "Too short packet");
                goto failed;
+       }
 
+       g_obex_packet_set_data(pkt, buf, header_offset, data_policy);
        buf += header_offset;
 
 headers:
        if (!parse_headers(pkt, buf, len - (buf - (guint8 *) data),
-                                                               data_policy))
+                                                       data_policy, err))
                goto failed;
 
        return pkt;
index 908efac..38a8ff2 100644 (file)
@@ -51,7 +51,8 @@ void g_obex_packet_free(GObexPacket *pkt);
 
 GObexPacket *g_obex_packet_decode(const void *data, gsize len,
                                                gsize header_offset,
-                                               GObexDataPolicy data_policy);
+                                               GObexDataPolicy data_policy,
+                                               GError **err);
 gssize g_obex_packet_encode(GObexPacket *pkt, guint8 *buf, gsize len);
 
 #endif /* __GOBEX_PACKET_H */
index be65fea..5b77399 100644 (file)
@@ -273,21 +273,24 @@ static void parse_connect_data(GObex *obex, GObexPacket *pkt)
        obex->tx_buf = g_realloc(obex->tx_buf, obex->tx_mtu);
 }
 
-static void handle_response(GObex *obex, GObexPacket *rsp)
+static void handle_response(GObex *obex, GError *err, GObexPacket *rsp)
 {
        struct pending_pkt *p = obex->pending_req;
 
-       if (g_obex_packet_get_operation(p->pkt, NULL) == G_OBEX_OP_CONNECT)
-               parse_connect_data(obex, rsp);
+       if (rsp != NULL) {
+               guint8 op = g_obex_packet_get_operation(p->pkt, NULL);
+               if (op == G_OBEX_OP_CONNECT)
+                       parse_connect_data(obex, rsp);
+       }
 
        if (p->rsp_func)
-               p->rsp_func(obex, NULL, rsp, p->rsp_data);
+               p->rsp_func(obex, err, rsp, p->rsp_data);
 
        pending_pkt_free(p);
        obex->pending_req = NULL;
 }
 
-static void handle_request(GObex *obex, GObexPacket *req)
+static void handle_request(GObex *obex, GError *err, GObexPacket *req)
 {
        if (g_obex_packet_get_operation(req, NULL) == G_OBEX_OP_CONNECT)
                parse_connect_data(obex, req);
@@ -296,12 +299,14 @@ static void handle_request(GObex *obex, GObexPacket *req)
                obex->req_func(obex, req, obex->req_func_data);
 }
 
-static gboolean g_obex_handle_packet(GObex *obex, GObexPacket *pkt)
+static gboolean g_obex_handle_packet(GObex *obex, GError *err, GObexPacket *pkt)
 {
        if (obex->pending_req)
-               handle_response(obex, pkt);
-       else
-               handle_request(obex, pkt);
+               handle_response(obex, err, pkt);
+       else if (pkt != NULL)
+               handle_request(obex, err, pkt);
+
+       /* FIXME: Application callback needed for err != NULL? */
 
        return TRUE;
 }
@@ -361,6 +366,7 @@ static gboolean incoming_data(GIOChannel *io, GIOCondition cond,
        GObex *obex = user_data;
        GObexPacket *pkt;
        ssize_t header_offset;
+       GError *err = NULL;
 
        if (cond & G_IO_NVAL)
                return FALSE;
@@ -387,13 +393,12 @@ static gboolean incoming_data(GIOChannel *io, GIOCondition cond,
                goto failed;
 
        pkt = g_obex_packet_decode(obex->rx_buf, obex->rx_data, header_offset,
-                                                       G_OBEX_DATA_REF);
-       if (pkt == NULL) {
-               /* FIXME: Handle decoding error */
-       } else {
-               g_obex_handle_packet(obex, pkt);
+                                                       G_OBEX_DATA_REF, &err);
+
+       g_obex_handle_packet(obex, err, pkt);
+
+       if (pkt != NULL)
                g_obex_packet_free(pkt);
-       }
 
        obex->rx_data = 0;
 
index 4185a70..2ac0c43 100644 (file)
@@ -124,9 +124,11 @@ static GObexHeader *parse_and_encode(uint8_t *buf, size_t buf_len)
        GObexHeader *header;
        uint8_t encoded[1024];
        size_t len;
+       GError *err = NULL;
 
-       header = g_obex_header_decode(buf, buf_len, G_OBEX_DATA_REF, &len);
-       g_assert(header != NULL);
+       header = g_obex_header_decode(buf, buf_len, G_OBEX_DATA_REF, &len,
+                                                                       &err);
+       g_assert_no_error(err);
        g_assert_cmpuint(len, ==, buf_len);
 
        len = g_obex_header_encode(header, encoded, sizeof(encoded));
@@ -222,10 +224,11 @@ static void test_decode_header_connid(void)
 {
        GObexHeader *header;
        size_t parsed;
+       GError *err = NULL;
 
        header = g_obex_header_decode(hdr_connid, sizeof(hdr_connid),
-                                               G_OBEX_DATA_REF, &parsed);
-       g_assert(header != NULL);
+                                       G_OBEX_DATA_REF, &parsed, &err);
+       g_assert_no_error(err);
 
        g_assert_cmpuint(parsed, ==, sizeof(hdr_connid));
 
@@ -236,10 +239,11 @@ static void test_decode_header_name_ascii(void)
 {
        GObexHeader *header;
        size_t parsed;
+       GError *err = NULL;
 
        header = g_obex_header_decode(hdr_name_ascii, sizeof(hdr_name_ascii),
-                                               G_OBEX_DATA_REF, &parsed);
-       g_assert(header != NULL);
+                                       G_OBEX_DATA_REF, &parsed, &err);
+       g_assert_no_error(err);
 
        g_assert_cmpuint(parsed, ==, sizeof(hdr_name_ascii));
 
@@ -250,10 +254,11 @@ static void test_decode_header_name_umlaut(void)
 {
        GObexHeader *header;
        size_t parsed;
+       GError *err = NULL;
 
        header = g_obex_header_decode(hdr_name_umlaut, sizeof(hdr_name_umlaut),
-                                               G_OBEX_DATA_REF, &parsed);
-       g_assert(header != NULL);
+                                       G_OBEX_DATA_REF, &parsed, &err);
+       g_assert_no_error(err);
 
        g_assert_cmpuint(parsed, ==, sizeof(hdr_name_umlaut));
 
@@ -264,10 +269,11 @@ static void test_decode_header_body(void)
 {
        GObexHeader *header;
        size_t parsed;
+       GError *err = NULL;
 
        header = g_obex_header_decode(hdr_body, sizeof(hdr_body),
-                                               G_OBEX_DATA_COPY, &parsed);
-       g_assert(header != NULL);
+                                       G_OBEX_DATA_COPY, &parsed, &err);
+       g_assert_no_error(err);
 
        g_assert_cmpuint(parsed, ==, sizeof(hdr_body));
 
@@ -278,10 +284,11 @@ static void test_decode_header_body_extdata(void)
 {
        GObexHeader *header;
        size_t parsed;
+       GError *err = NULL;
 
        header = g_obex_header_decode(hdr_body, sizeof(hdr_body),
-                                               G_OBEX_DATA_REF, &parsed);
-       g_assert(header != NULL);
+                                       G_OBEX_DATA_REF, &parsed, &err);
+       g_assert_no_error(err);
 
        g_assert_cmpuint(parsed, ==, sizeof(hdr_body));
 
@@ -292,10 +299,11 @@ static void test_decode_header_actionid(void)
 {
        GObexHeader *header;
        size_t parsed;
+       GError *err = NULL;
 
        header = g_obex_header_decode(hdr_actionid, sizeof(hdr_actionid),
-                                               G_OBEX_DATA_REF, &parsed);
-       g_assert(header != NULL);
+                                       G_OBEX_DATA_REF, &parsed, &err);
+       g_assert_no_error(err);
 
        g_assert_cmpuint(parsed, ==, sizeof(hdr_actionid));
 
@@ -307,6 +315,7 @@ static void test_decode_header_multi(void)
        GObexHeader *header;
        GByteArray *buf;
        size_t parsed;
+       GError *err = NULL;
 
        buf = g_byte_array_sized_new(sizeof(hdr_connid) +
                                        sizeof(hdr_name_ascii) +
@@ -319,29 +328,29 @@ static void test_decode_header_multi(void)
        g_byte_array_append(buf, hdr_body, sizeof(hdr_body));
 
        header = g_obex_header_decode(buf->data, buf->len, G_OBEX_DATA_REF,
-                                                               &parsed);
-       g_assert(header != NULL);
+                                                               &parsed, &err);
+       g_assert_no_error(err);
        g_assert_cmpuint(parsed, ==, sizeof(hdr_connid));
        g_byte_array_remove_range(buf, 0, parsed);
        g_obex_header_free(header);
 
        header = g_obex_header_decode(buf->data, buf->len, G_OBEX_DATA_REF,
-                                                               &parsed);
-       g_assert(header != NULL);
+                                                               &parsed, &err);
+       g_assert_no_error(err);
        g_assert_cmpuint(parsed, ==, sizeof(hdr_name_ascii));
        g_byte_array_remove_range(buf, 0, parsed);
        g_obex_header_free(header);
 
        header = g_obex_header_decode(buf->data, buf->len, G_OBEX_DATA_REF,
-                                                               &parsed);
-       g_assert(header != NULL);
+                                                               &parsed, &err);
+       g_assert_no_error(err);
        g_assert_cmpuint(parsed, ==, sizeof(hdr_actionid));
        g_byte_array_remove_range(buf, 0, parsed);
        g_obex_header_free(header);
 
        header = g_obex_header_decode(buf->data, buf->len, G_OBEX_DATA_REF,
-                                                               &parsed);
-       g_assert(header != NULL);
+                                                               &parsed, &err);
+       g_assert_no_error(err);
        g_assert_cmpuint(parsed, ==, sizeof(hdr_body));
        g_byte_array_remove_range(buf, 0, parsed);
        g_obex_header_free(header);
index 8792a59..fcbe398 100644 (file)
@@ -40,9 +40,10 @@ static void test_decode_pkt(void)
 {
        GObexPacket *pkt;
        uint8_t buf[] = { G_OBEX_OP_PUT, 0x00, 0x03 };
+       GError *err = NULL;
 
-       pkt = g_obex_packet_decode(buf, sizeof(buf), 0, G_OBEX_DATA_REF);
-       g_assert(pkt != NULL);
+       pkt = g_obex_packet_decode(buf, sizeof(buf), 0, G_OBEX_DATA_REF, &err);
+       g_assert_no_error(err);
 
        g_obex_packet_free(pkt);
 }
@@ -51,13 +52,14 @@ static void test_decode_pkt_header(void)
 {
        GObexPacket *pkt;
        GObexHeader *header;
+       GError *err = NULL;
        gboolean ret;
        uint8_t buf[] = { G_OBEX_OP_PUT, 0x00, 0x05,
                                        G_OBEX_HDR_ID_ACTION, 0xab };
        guint8 val;
 
-       pkt = g_obex_packet_decode(buf, sizeof(buf), 0, G_OBEX_DATA_REF);
-       g_assert(pkt != NULL);
+       pkt = g_obex_packet_decode(buf, sizeof(buf), 0, G_OBEX_DATA_REF, &err);
+       g_assert_no_error(err);
 
        header = g_obex_packet_get_header(pkt, G_OBEX_HDR_ID_ACTION);
        g_assert(header != NULL);