Diff between 31ebc74e69a833122cdc1c25078e614c7d7895bb and aa1b87b6d8a8d51632ab31b637d85183944ac3a8

Changed Files

File Additions Deletions Status
gobex/gobex-defs.c +29 -0 added
gobex/gobex-defs.h +10 -0 modified
gobex/gobex-header.c +38 -8 modified
gobex/gobex-header.h +2 -1 modified
gobex/gobex-packet.c +27 -13 modified
gobex/gobex-packet.h +2 -1 modified
gobex/gobex.c +20 -15 modified
unit/test-gobex-header.c +31 -22 modified
unit/test-gobex-packet.c +6 -4 modified

Full Patch

diff --git a/gobex/gobex-defs.c b/gobex/gobex-defs.c
new file mode 100644
index 0000000..f1f3b38
--- /dev/null
+++ b/gobex/gobex-defs.c
@@ -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");
+}
diff --git a/gobex/gobex-defs.h b/gobex/gobex-defs.h
index ad8b046..76b274f 100644
--- a/gobex/gobex-defs.h
+++ b/gobex/gobex-defs.h
@@ -22,10 +22,20 @@
 #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 */
diff --git a/gobex/gobex-header.c b/gobex/gobex-header.c
index 949e48a..72ea5de 100644
--- a/gobex/gobex-header.c
+++ b/gobex/gobex-header.c
@@ -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));
diff --git a/gobex/gobex-header.h b/gobex/gobex-header.h
index b5b9100..1df7f14 100644
--- a/gobex/gobex-header.h
+++ b/gobex/gobex-header.h
@@ -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 */
diff --git a/gobex/gobex-packet.c b/gobex/gobex-packet.c
index 12acb70..957e1cc 100644
--- a/gobex/gobex-packet.c
+++ b/gobex/gobex-packet.c
@@ -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;
diff --git a/gobex/gobex-packet.h b/gobex/gobex-packet.h
index 908efac..38a8ff2 100644
--- a/gobex/gobex-packet.h
+++ b/gobex/gobex-packet.h
@@ -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 */
diff --git a/gobex/gobex.c b/gobex/gobex.c
index be65fea..5b77399 100644
--- a/gobex/gobex.c
+++ b/gobex/gobex.c
@@ -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;
 
diff --git a/unit/test-gobex-header.c b/unit/test-gobex-header.c
index 4185a70..2ac0c43 100644
--- a/unit/test-gobex-header.c
+++ b/unit/test-gobex-header.c
@@ -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);
diff --git a/unit/test-gobex-packet.c b/unit/test-gobex-packet.c
index 8792a59..fcbe398 100644
--- a/unit/test-gobex-packet.c
+++ b/unit/test-gobex-packet.c
@@ -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);