Diff between 6cfe881554ba2f7e5e1dd8cef8277a297ef90dba and 3f41b8b20107bbd3413ee13570f0a2559ebdbb1e

Changed Files

File Additions Deletions Status
gobex/gobex.c +64 -0 modified
gobex/gobex.h +4 -1 modified

Full Patch

diff --git a/gobex/gobex.c b/gobex/gobex.c
index 1b0b67f..1c74ec0 100644
--- a/gobex/gobex.c
+++ b/gobex/gobex.c
@@ -65,6 +65,8 @@ struct _GObex {
 
 	GQueue *tx_queue;
 
+	GSList *req_handlers;
+
 	GObexRequestFunc req_func;
 	gpointer req_func_data;
 
@@ -85,6 +87,12 @@ struct pending_pkt {
 	gboolean cancelled;
 };
 
+struct req_handler {
+	guint8 opcode;
+	GObexRequestFunc func;
+	gpointer user_data;
+};
+
 struct connect_data {
 	guint8 version;
 	guint8 flags;
@@ -481,6 +489,39 @@ void g_obex_set_disconnect_function(GObex *obex, GObexFunc func,
 	obex->disconn_func_data = user_data;
 }
 
+gint g_obex_add_request_function(GObex *obex, guint8 opcode,
+						GObexRequestFunc func,
+						gpointer user_data)
+{
+	struct req_handler *handler;
+
+	handler = g_new0(struct req_handler, 1);
+	handler->opcode = opcode;
+	handler->func = func;
+	handler->user_data = user_data;
+
+	obex->req_handlers = g_slist_prepend(obex->req_handlers, handler);
+
+	return GPOINTER_TO_INT(handler);
+}
+
+gboolean g_obex_remove_request_function(GObex *obex, gint id)
+{
+	struct req_handler *handler;
+	GSList *match;
+
+	match = g_slist_find(obex->req_handlers, GINT_TO_POINTER(id));
+	if (match == NULL)
+		return FALSE;
+
+	handler = match->data;
+
+	obex->req_handlers = g_slist_delete_link(obex->req_handlers, match);
+	g_free(handler);
+
+	return TRUE;
+}
+
 static void parse_connect_data(GObex *obex, GObexPacket *pkt)
 {
 	const struct connect_data *data;
@@ -538,11 +579,32 @@ static void handle_response(GObex *obex, GError *err, GObexPacket *rsp)
 		enable_tx(obex);
 }
 
+static gint req_handler_cmp(gconstpointer a, gconstpointer b)
+{
+	const struct req_handler *handler = a;
+	const guint8 *opcode = b;
+
+	return (gint) handler->opcode - (gint) *opcode;
+}
+
 static void handle_request(GObex *obex, GObexPacket *req)
 {
+	GSList *match;
+	guint8 opcode;
+
 	if (g_obex_packet_get_operation(req, NULL) == G_OBEX_OP_CONNECT)
 		parse_connect_data(obex, req);
 
+	opcode = g_obex_packet_get_operation(req, NULL);
+
+	match = g_slist_find_custom(obex->req_handlers, &opcode,
+							req_handler_cmp);
+	if (match) {
+		struct req_handler *handler = match->data;
+		handler->func(obex, req, handler->user_data);
+		return;
+	}
+
 	if (obex->req_func)
 		obex->req_func(obex, req, obex->req_func_data);
 }
@@ -795,6 +857,8 @@ void g_obex_unref(GObex *obex)
 	if (!last_ref)
 		return;
 
+	g_slist_free_full(obex->req_handlers, g_free);
+
 	g_queue_foreach(obex->tx_queue, (GFunc) pending_pkt_free, NULL);
 	g_queue_free(obex->tx_queue);
 
diff --git a/gobex/gobex.h b/gobex/gobex.h
index 1ca71d7..110231f 100644
--- a/gobex/gobex.h
+++ b/gobex/gobex.h
@@ -51,7 +51,10 @@ void g_obex_set_request_function(GObex *obex, GObexRequestFunc func,
 							gpointer user_data);
 void g_obex_set_disconnect_function(GObex *obex, GObexFunc func,
 							gpointer user_data);
-
+gint g_obex_add_request_function(GObex *obex, guint8 opcode,
+						GObexRequestFunc func,
+						gpointer user_data);
+gboolean g_obex_remove_request_function(GObex *obex, gint id);
 GObex *g_obex_new(GIOChannel *io, GObexTransportType transport_type,
 						gssize rx_mtu, gssize tx_mtu);