linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH obexd 1/6] client: fix circular dependency of session and transfer
@ 2012-01-20  9:49 Luiz Augusto von Dentz
  2012-01-20  9:49 ` [PATCH obexd 2/6] client: remove unused field Luiz Augusto von Dentz
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2012-01-20  9:49 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Currently the code has to to pass session to transfer via user data
(void *) only to be casted to session.
---
 client/ftp.c      |    7 +--
 client/manager.c  |    6 +--
 client/map.c      |    9 +---
 client/pbap.c     |   42 ++++-------------
 client/session.c  |  129 ++++++++++++++++++++++++++++++++++++++++++++---------
 client/session.h  |    8 +---
 client/sync.c     |    8 +--
 client/transfer.c |   68 ++++++++++++++--------------
 client/transfer.h |   13 +++---
 9 files changed, 168 insertions(+), 122 deletions(-)

diff --git a/client/ftp.c b/client/ftp.c
index 336fc26..fdadf43 100644
--- a/client/ftp.c
+++ b/client/ftp.c
@@ -201,16 +201,15 @@ static void list_folder_callback(struct obc_session *session,
 					GError *err, void *user_data)
 {
 	struct ftp_data *ftp = user_data;
-	struct obc_transfer *transfer = obc_session_get_transfer(session);
 	GMarkupParseContext *ctxt;
 	DBusMessage *reply;
 	DBusMessageIter iter, array;
 	const char *buf;
-	int size;
+	size_t size;
 
 	reply = dbus_message_new_method_return(ftp->msg);
 
-	buf = obc_transfer_get_buffer(transfer, &size);
+	buf = obc_session_get_buffer(session, &size);
 	if (size == 0)
 		goto done;
 
@@ -225,8 +224,6 @@ static void list_folder_callback(struct obc_session *session,
 	g_markup_parse_context_free(ctxt);
 	dbus_message_iter_close_container(&iter, &array);
 
-	obc_transfer_clear_buffer(transfer);
-
 done:
 	g_dbus_send_message(conn, reply);
 	dbus_message_unref(ftp->msg);
diff --git a/client/manager.c b/client/manager.c
index f6628d7..7841753 100644
--- a/client/manager.c
+++ b/client/manager.c
@@ -35,7 +35,6 @@
 #include <gdbus.h>
 
 #include "log.h"
-#include "transfer.h"
 #include "session.h"
 #include "manager.h"
 #include "opp.h"
@@ -441,10 +440,9 @@ static DBusMessage *remove_session(DBusConnection *connection,
 static void capabilities_complete_callback(struct obc_session *session,
 						GError *err, void *user_data)
 {
-	struct obc_transfer *transfer = obc_session_get_transfer(session);
 	struct send_data *data = user_data;
 	const char *capabilities;
-	int size;
+	size_t size;
 
 	if (err != NULL) {
 		DBusMessage *error = g_dbus_create_error(data->message,
@@ -454,7 +452,7 @@ static void capabilities_complete_callback(struct obc_session *session,
 		goto done;
 	}
 
-	capabilities = obc_transfer_get_buffer(transfer, &size);
+	capabilities = obc_session_get_buffer(session, &size);
 	if (size == 0)
 		capabilities = "";
 
diff --git a/client/map.c b/client/map.c
index cdd2725..9a76919 100644
--- a/client/map.c
+++ b/client/map.c
@@ -31,7 +31,6 @@
 #include "log.h"
 
 #include "map.h"
-#include "transfer.h"
 #include "session.h"
 #include "driver.h"
 
@@ -107,11 +106,10 @@ static DBusMessage *map_setpath(DBusConnection *connection,
 static void buffer_cb(struct obc_session *session, GError *err,
 							void *user_data)
 {
-	struct obc_transfer *transfer = obc_session_get_transfer(session);
 	struct map_data *map = user_data;
 	DBusMessage *reply;
 	const char *buf;
-	int size;
+	size_t size;
 
 	if (err != NULL) {
 		reply = g_dbus_create_error(map->msg,
@@ -120,19 +118,16 @@ static void buffer_cb(struct obc_session *session, GError *err,
 		goto done;
 	}
 
-	buf = obc_transfer_get_buffer(transfer, &size);
+	buf = obc_session_get_buffer(session, &size);
 	if (size == 0)
 		buf = "";
 
 	reply = g_dbus_create_reply(map->msg, DBUS_TYPE_STRING, &buf,
 							DBUS_TYPE_INVALID);
 
-	obc_transfer_clear_buffer(transfer);
-
 done:
 	g_dbus_send_message(conn, reply);
 	dbus_message_unref(map->msg);
-	obc_transfer_unregister(transfer);
 }
 
 static DBusMessage *map_get_folder_listing(DBusConnection *connection,
diff --git a/client/pbap.c b/client/pbap.c
index 8efa568..4a93fd5 100644
--- a/client/pbap.c
+++ b/client/pbap.c
@@ -36,7 +36,6 @@
 
 #include "log.h"
 
-#include "transfer.h"
 #include "session.h"
 #include "driver.h"
 #include "pbap.h"
@@ -362,23 +361,19 @@ static int pbap_set_path(struct pbap_data *pbap, const char *path)
 static void read_return_apparam(struct obc_session *session,
 				guint16 *phone_book_size, guint8 *new_missed_calls)
 {
-	struct obc_transfer *transfer = obc_session_get_transfer(session);
-	struct obc_transfer_params params;
 	struct apparam_hdr *hdr;
 	size_t size;
 
 	*phone_book_size = 0;
 	*new_missed_calls = 0;
 
-	if (obc_transfer_get_params(transfer, &params) < 0)
+	hdr = obc_session_get_params(session, &size);
+	if (hdr == NULL)
 		return;
 
-	if (params.size < APPARAM_HDR_SIZE)
+	if (size < APPARAM_HDR_SIZE)
 		return;
 
-	hdr = (struct apparam_hdr *) params.data;
-	size = params.size;
-
 	while (size > APPARAM_HDR_SIZE) {
 		if (hdr->len > size - APPARAM_HDR_SIZE) {
 			error("Unexpected PBAP pullphonebook app"
@@ -413,14 +408,13 @@ static void read_return_apparam(struct obc_session *session,
 static void pull_phonebook_callback(struct obc_session *session,
 					GError *err, void *user_data)
 {
-	struct obc_transfer *transfer = obc_session_get_transfer(session);
 	struct pbap_data *pbap = user_data;
 	DBusMessage *reply;
 	const char *buf;
-	int size;
+	size_t size;
 
 	if (pbap->msg == NULL)
-		goto done;
+		return;
 
 	if (err) {
 		reply = g_dbus_create_error(pbap->msg,
@@ -431,7 +425,7 @@ static void pull_phonebook_callback(struct obc_session *session,
 
 	reply = dbus_message_new_method_return(pbap->msg);
 
-	buf = obc_transfer_get_buffer(transfer, &size);
+	buf = obc_session_get_buffer(session, &size);
 	if (size == 0)
 		buf = "";
 
@@ -439,28 +433,22 @@ static void pull_phonebook_callback(struct obc_session *session,
 			DBUS_TYPE_STRING, &buf,
 			DBUS_TYPE_INVALID);
 
-	obc_transfer_clear_buffer(transfer);
-
 send:
 	g_dbus_send_message(conn, reply);
 	dbus_message_unref(pbap->msg);
 	pbap->msg = NULL;
-
-done:
-	obc_transfer_unregister(transfer);
 }
 
 static void phonebook_size_callback(struct obc_session *session,
 					GError *err, void *user_data)
 {
-	struct obc_transfer *transfer = obc_session_get_transfer(session);
 	struct pbap_data *pbap = user_data;
 	DBusMessage *reply;
 	guint16 phone_book_size;
 	guint8 new_missed_calls;
 
 	if (pbap->msg == NULL)
-		goto done;
+		return;
 
 	if (err) {
 		reply = g_dbus_create_error(pbap->msg,
@@ -477,30 +465,24 @@ static void phonebook_size_callback(struct obc_session *session,
 			DBUS_TYPE_UINT16, &phone_book_size,
 			DBUS_TYPE_INVALID);
 
-	obc_transfer_clear_buffer(transfer);
-
 send:
 	g_dbus_send_message(conn, reply);
 	dbus_message_unref(pbap->msg);
 	pbap->msg = NULL;
-
-done:
-	obc_transfer_unregister(transfer);
 }
 
 static void pull_vcard_listing_callback(struct obc_session *session,
 					GError *err, void *user_data)
 {
-	struct obc_transfer *transfer = obc_session_get_transfer(session);
 	struct pbap_data *pbap = user_data;
 	GMarkupParseContext *ctxt;
 	DBusMessage *reply;
 	DBusMessageIter iter, array;
 	const char *buf;
-	int size;
+	size_t size;
 
 	if (pbap->msg == NULL)
-		goto complete;
+		return;
 
 	if (err) {
 		reply = g_dbus_create_error(pbap->msg,
@@ -511,7 +493,7 @@ static void pull_vcard_listing_callback(struct obc_session *session,
 
 	reply = dbus_message_new_method_return(pbap->msg);
 
-	buf = obc_transfer_get_buffer(transfer, &size);
+	buf = obc_session_get_buffer(session, &size);
 	if (size == 0)
 		buf = "";
 
@@ -525,14 +507,10 @@ static void pull_vcard_listing_callback(struct obc_session *session,
 	g_markup_parse_context_free(ctxt);
 	dbus_message_iter_close_container(&iter, &array);
 
-	obc_transfer_clear_buffer(transfer);
-
 send:
 	g_dbus_send_message(conn, reply);
 	dbus_message_unref(pbap->msg);
 	pbap->msg = NULL;
-complete:
-	obc_transfer_unregister(transfer);
 }
 
 static DBusMessage *pull_phonebook(struct pbap_data *pbap,
diff --git a/client/session.c b/client/session.c
index 9f02512..5dfbd47 100644
--- a/client/session.c
+++ b/client/session.c
@@ -869,15 +869,38 @@ proceed:
 	return session;
 }
 
+static void obc_session_add_transfer(struct obc_session *session,
+						struct obc_transfer *transfer)
+{
+	session->pending = g_slist_append(session->pending, transfer);
+	obc_session_ref(session);
+}
+
+static void obc_session_remove_transfer(struct obc_session *session,
+						struct obc_transfer *transfer)
+{
+	session->pending = g_slist_remove(session->pending, transfer);
+	obc_transfer_unregister(transfer);
+	obc_session_unref(session);
+}
+
 void obc_session_shutdown(struct obc_session *session)
 {
+	GSList *l = session->pending;
+
 	DBG("%p", session);
 
 	obc_session_ref(session);
 
 	/* Unregister any pending transfer */
-	g_slist_foreach(session->pending, (GFunc) obc_transfer_unregister,
-									NULL);
+	while (l) {
+		struct obc_transfer *transfer = l->data;
+
+		l = l->next;
+
+		obc_session_remove_transfer(session, transfer);
+	}
+
 
 	/* Unregister interfaces */
 	if (session->path)
@@ -1108,13 +1131,17 @@ static void session_terminate_transfer(struct obc_session *session,
 	struct session_callback *callback = session->callback;
 
 	if (callback) {
+		obc_session_ref(session);
 		callback->func(session, gerr, callback->data);
+		if (g_slist_find(session->pending, transfer))
+			obc_session_remove_transfer(session, transfer);
+		obc_session_unref(session);
 		return;
 	}
 
 	obc_session_ref(session);
 
-	obc_transfer_unregister(transfer);
+	obc_session_remove_transfer(session, transfer);
 
 	if (session->pending)
 		session_request(session, session_prepare_put,
@@ -1226,6 +1253,7 @@ int obc_session_get(struct obc_session *session, const char *type,
 {
 	struct obc_transfer *transfer;
 	struct obc_transfer_params *params = NULL;
+	const char *agent;
 	int err;
 
 	if (session->obex == NULL)
@@ -1238,8 +1266,15 @@ int obc_session_get(struct obc_session *session, const char *type,
 		params->size = apparam_size;
 	}
 
-	transfer = obc_transfer_register(session->conn, filename, targetname,
-							type, params, session);
+	if (session->agent)
+		agent = obc_agent_get_name(session->agent);
+	else
+		agent = NULL;
+
+	transfer = obc_transfer_register(session->conn, session->obex,
+							agent, filename,
+							targetname, type,
+							params);
 	if (transfer == NULL) {
 		if (params != NULL) {
 			g_free(params->data);
@@ -1257,8 +1292,12 @@ int obc_session_get(struct obc_session *session, const char *type,
 	}
 
 	err = session_request(session, session_prepare_get, transfer);
-	if (err < 0)
+	if (err < 0) {
+		obc_transfer_unregister(transfer);
 		return err;
+	}
+
+	obc_session_add_transfer(session, transfer);
 
 	return 0;
 }
@@ -1267,13 +1306,18 @@ int obc_session_send(struct obc_session *session, const char *filename,
 				const char *targetname)
 {
 	struct obc_transfer *transfer;
+	const char *agent;
 	int err;
 
 	if (session->obex == NULL)
 		return -ENOTCONN;
 
-	transfer = obc_transfer_register(session->conn, filename, targetname,
-							NULL, NULL, session);
+	agent = obc_agent_get_name(session->agent);
+
+	transfer = obc_transfer_register(session->conn, session->obex,
+							agent, filename,
+							targetname, NULL,
+							NULL);
 	if (transfer == NULL)
 		return -EINVAL;
 
@@ -1282,13 +1326,16 @@ int obc_session_send(struct obc_session *session, const char *filename,
 		goto fail;
 
 	/* Transfer should start if it is the first in the pending list */
-	if (transfer != session->pending->data)
-		return 0;
+	if (session->pending != NULL)
+		goto done;
 
 	err = session_request(session, session_prepare_put, transfer);
 	if (err < 0)
 		goto fail;
 
+done:
+	obc_session_add_transfer(session, transfer);
+
 	return 0;
 
 fail:
@@ -1302,13 +1349,21 @@ int obc_session_pull(struct obc_session *session,
 				session_callback_t function, void *user_data)
 {
 	struct obc_transfer *transfer;
+	const char *agent;
 	int err;
 
 	if (session->obex == NULL)
 		return -ENOTCONN;
 
-	transfer = obc_transfer_register(session->conn, NULL, filename, type,
-								NULL, session);
+	if (session->agent != NULL)
+		agent = obc_agent_get_name(session->agent);
+	else
+		agent = NULL;
+
+	transfer = obc_transfer_register(session->conn, session->obex,
+								agent, NULL,
+								filename, type,
+								NULL);
 	if (transfer == NULL) {
 		return -EIO;
 	}
@@ -1322,8 +1377,10 @@ int obc_session_pull(struct obc_session *session,
 	}
 
 	err = session_request(session, session_prepare_get, transfer);
-	if (err == 0)
+	if (err == 0) {
+		obc_session_add_transfer(session, transfer);
 		return 0;
+	}
 
 	obc_transfer_unregister(transfer);
 	return err;
@@ -1382,6 +1439,7 @@ static void session_prepare_put(struct obc_session *session,
 int obc_session_put(struct obc_session *session, char *buf, const char *targetname)
 {
 	struct obc_transfer *transfer;
+	const char *agent;
 	int err;
 
 	if (session->obex == NULL)
@@ -1390,8 +1448,12 @@ int obc_session_put(struct obc_session *session, char *buf, const char *targetna
 	if (session->pending != NULL)
 		return -EISCONN;
 
-	transfer = obc_transfer_register(session->conn, NULL, targetname, NULL,
-								NULL, session);
+	agent = obc_agent_get_name(session->agent);
+
+	transfer = obc_transfer_register(session->conn, session->obex,
+							agent, NULL,
+							targetname, NULL,
+							NULL);
 	if (transfer == NULL)
 		return -EIO;
 
@@ -1470,19 +1532,42 @@ GObex *obc_session_get_obex(struct obc_session *session)
 	return session->obex;
 }
 
-struct obc_transfer *obc_session_get_transfer(struct obc_session *session)
+static struct obc_transfer *obc_session_get_transfer(
+						struct obc_session *session)
 {
 	return session->pending ? session->pending->data : NULL;
 }
 
-void obc_session_add_transfer(struct obc_session *session,
-					struct obc_transfer *transfer)
+const char *obc_session_get_buffer(struct obc_session *session, size_t *size)
 {
-	session->pending = g_slist_append(session->pending, transfer);
+	struct obc_transfer *transfer;
+	const char *buf;
+
+	transfer = obc_session_get_transfer(session);
+	if (transfer == NULL)
+		return NULL;
+
+	buf = obc_transfer_get_buffer(transfer, size);
+
+	obc_transfer_clear_buffer(transfer);
+
+	return buf;
 }
 
-void obc_session_remove_transfer(struct obc_session *session,
-					struct obc_transfer *transfer)
+void *obc_session_get_params(struct obc_session *session, size_t *size)
 {
-	session->pending = g_slist_remove(session->pending, transfer);
+	struct obc_transfer *transfer;
+	struct obc_transfer_params params;
+
+	transfer= obc_session_get_transfer(session);
+	if (transfer == NULL)
+		return NULL;
+
+	if (obc_transfer_get_params(transfer, &params) < 0)
+		return NULL;
+
+	if (size)
+		*size = params.size;
+
+	return params.data;
 }
diff --git a/client/session.h b/client/session.h
index b2a83d9..511f084 100644
--- a/client/session.h
+++ b/client/session.h
@@ -57,12 +57,8 @@ const char *obc_session_get_agent(struct obc_session *session);
 const char *obc_session_get_path(struct obc_session *session);
 const char *obc_session_get_target(struct obc_session *session);
 GObex *obc_session_get_obex(struct obc_session *session);
-
-struct obc_transfer *obc_session_get_transfer(struct obc_session *session);
-void obc_session_add_transfer(struct obc_session *session,
-					struct obc_transfer *transfer);
-void obc_session_remove_transfer(struct obc_session *session,
-					struct obc_transfer *transfer);
+const char *obc_session_get_buffer(struct obc_session *session, size_t *size);
+void *obc_session_get_params(struct obc_session *session, size_t *size);
 
 int obc_session_send(struct obc_session *session, const char *filename,
 				const char *remotename);
diff --git a/client/sync.c b/client/sync.c
index 7675b23..7d713a8 100644
--- a/client/sync.c
+++ b/client/sync.c
@@ -33,7 +33,6 @@
 
 #include "log.h"
 
-#include "transfer.h"
 #include "session.h"
 #include "driver.h"
 #include "sync.h"
@@ -86,16 +85,15 @@ static DBusMessage *sync_setlocation(DBusConnection *connection,
 static void sync_getphonebook_callback(struct obc_session *session,
 					GError *err, void *user_data)
 {
-	struct obc_transfer *transfer = obc_session_get_transfer(session);
 	struct sync_data *sync = user_data;
 	DBusMessage *reply;
 	const char *buf;
-	int size;
+	size_t size;
 
 	reply = dbus_message_new_method_return(sync->msg);
 
-	buf = obc_transfer_get_buffer(transfer, &size);
-	if (size == 0)
+	buf = obc_session_get_buffer(session, &size);
+	if (buf == NULL)
 		buf = "";
 
 	dbus_message_append_args(reply,
diff --git a/client/transfer.c b/client/transfer.c
index 2532294..8677b07 100644
--- a/client/transfer.c
+++ b/client/transfer.c
@@ -30,19 +30,22 @@
 #include <unistd.h>
 #include <string.h>
 #include <sys/stat.h>
+#include <inttypes.h>
 
 #include <glib.h>
 #include <gdbus.h>
+#include <gobex.h>
 
 #include "log.h"
 #include "transfer.h"
-#include "session.h"
 
 #define TRANSFER_INTERFACE  "org.openobex.Transfer"
 #define TRANSFER_BASEPATH   "/org/openobex"
 
 #define DEFAULT_BUFFER_SIZE 4096
 
+#define OBC_TRANSFER_ERROR obc_transfer_error_quark()
+
 static guint64 counter = 0;
 
 struct transfer_callback {
@@ -51,10 +54,11 @@ struct transfer_callback {
 };
 
 struct obc_transfer {
-	struct obc_session *session;
+	GObex *obex;
 	struct obc_transfer_params *params;
 	struct transfer_callback *callback;
 	DBusConnection *conn;
+	char *agent;		/* Transfer agent */
 	char *path;		/* Transfer path */
 	gchar *filename;	/* Transfer file location */
 	char *name;		/* Transfer object name */
@@ -69,6 +73,11 @@ struct obc_transfer {
 	int err;
 };
 
+static GQuark obc_transfer_error_quark(void)
+{
+	return g_quark_from_static_string("obc-transfer-error-quark");
+}
+
 static void append_entry(DBusMessageIter *dict,
 				const char *key, int type, void *val)
 {
@@ -143,7 +152,7 @@ static void obc_transfer_abort(struct obc_transfer *transfer)
 	if (callback) {
 		GError *err;
 
-		err = g_error_new(OBEX_IO_ERROR, -ECANCELED, "%s",
+		err = g_error_new(OBC_TRANSFER_ERROR, -ECANCELED, "%s",
 							strerror(ECANCELED));
 		callback->func(transfer, transfer->transferred, err,
 							callback->data);
@@ -155,13 +164,11 @@ static DBusMessage *obc_transfer_cancel(DBusConnection *connection,
 					DBusMessage *message, void *user_data)
 {
 	struct obc_transfer *transfer = user_data;
-	struct obc_session *session = transfer->session;
-	const gchar *sender, *agent;
+	const gchar *sender;
 	DBusMessage *reply;
 
 	sender = dbus_message_get_sender(message);
-	agent = obc_session_get_agent(session);
-	if (g_str_equal(sender, agent) == FALSE)
+	if (g_str_equal(transfer->agent, sender) == FALSE)
 		return g_dbus_create_error(message,
 				"org.openobex.Error.NotAuthorized",
 				"Not Authorized");
@@ -183,8 +190,6 @@ static GDBusMethodTable obc_transfer_methods[] = {
 
 static void obc_transfer_free(struct obc_transfer *transfer)
 {
-	struct obc_session *session = transfer->session;
-
 	DBG("%p", transfer);
 
 	if (transfer->xfer)
@@ -193,10 +198,6 @@ static void obc_transfer_free(struct obc_transfer *transfer)
 	if (transfer->fd > 0)
 		close(transfer->fd);
 
-	obc_session_remove_transfer(session, transfer);
-
-	obc_session_unref(session);
-
 	if (transfer->params != NULL) {
 		g_free(transfer->params->data);
 		g_free(transfer->params);
@@ -205,7 +206,11 @@ static void obc_transfer_free(struct obc_transfer *transfer)
 	if (transfer->conn)
 		dbus_connection_unref(transfer->conn);
 
+	if (transfer->obex)
+		g_obex_unref(transfer->obex);
+
 	g_free(transfer->callback);
+	g_free(transfer->agent);
 	g_free(transfer->filename);
 	g_free(transfer->name);
 	g_free(transfer->type);
@@ -215,17 +220,18 @@ static void obc_transfer_free(struct obc_transfer *transfer)
 }
 
 struct obc_transfer *obc_transfer_register(DBusConnection *conn,
+						GObex *obex,
+						const char *agent,
 						const char *filename,
 						const char *name,
 						const char *type,
-						struct obc_transfer_params *params,
-						void *user_data)
+						struct obc_transfer_params *params)
 {
-	struct obc_session *session = user_data;
 	struct obc_transfer *transfer;
 
 	transfer = g_new0(struct obc_transfer, 1);
-	transfer->session = obc_session_ref(session);
+	transfer->obex = g_obex_ref(obex);
+	transfer->agent = g_strdup(agent);
 	transfer->filename = g_strdup(filename);
 	transfer->name = g_strdup(name);
 	transfer->type = g_strdup(type);
@@ -257,8 +263,6 @@ struct obc_transfer *obc_transfer_register(DBusConnection *conn,
 done:
 	DBG("%p registered %s", transfer, transfer->path);
 
-	obc_session_add_transfer(session, transfer);
-
 	return transfer;
 }
 
@@ -345,7 +349,7 @@ static void get_buf_xfer_progress(GObex *obex, GError *err, GObexPacket *rsp,
 
 	rspcode = g_obex_packet_get_operation(rsp, &final);
 	if (rspcode != G_OBEX_RSP_SUCCESS && rspcode != G_OBEX_RSP_CONTINUE) {
-		err = g_error_new(OBEX_IO_ERROR, rspcode,
+		err = g_error_new(OBC_TRANSFER_ERROR, rspcode,
 					"Transfer failed (0x%02x)", rspcode);
 		get_buf_xfer_complete(obex, err, transfer);
 		g_error_free(err);
@@ -499,9 +503,7 @@ static void obc_transfer_set_callback(struct obc_transfer *transfer,
 int obc_transfer_get(struct obc_transfer *transfer, transfer_callback_t func,
 			void *user_data)
 {
-	struct obc_session *session = transfer->session;
 	GError *err = NULL;
-	GObex *obex;
 	GObexPacket *req;
 	GObexDataConsumer data_cb;
 	GObexFunc complete_cb;
@@ -527,8 +529,6 @@ int obc_transfer_get(struct obc_transfer *transfer, transfer_callback_t func,
 		complete_cb = xfer_complete;
 	}
 
-	obex = obc_session_get_obex(session);
-
 	req = g_obex_packet_new(G_OBEX_OP_GET, TRUE, G_OBEX_HDR_INVALID);
 
 	if (transfer->filename != NULL)
@@ -545,12 +545,12 @@ int obc_transfer_get(struct obc_transfer *transfer, transfer_callback_t func,
 						transfer->params->size);
 
 	if (rsp_cb)
-		transfer->xfer = g_obex_send_req(obex, req, -1, rsp_cb,
-							transfer, &err);
+		transfer->xfer = g_obex_send_req(transfer->obex, req, -1,
+						rsp_cb, transfer, &err);
 	else
-		transfer->xfer = g_obex_get_req_pkt(obex, req, data_cb,
-							complete_cb, transfer,
-							&err);
+		transfer->xfer = g_obex_get_req_pkt(transfer->obex, req,
+						data_cb, complete_cb, transfer,
+						&err);
 
 	if (transfer->xfer == 0)
 		return -ENOTCONN;
@@ -564,9 +564,7 @@ int obc_transfer_get(struct obc_transfer *transfer, transfer_callback_t func,
 int obc_transfer_put(struct obc_transfer *transfer, transfer_callback_t func,
 			void *user_data)
 {
-	struct obc_session *session = transfer->session;
 	GError *err = NULL;
-	GObex *obex;
 	GObexPacket *req;
 	GObexDataProducer data_cb;
 
@@ -581,7 +579,6 @@ int obc_transfer_put(struct obc_transfer *transfer, transfer_callback_t func,
 	data_cb = put_xfer_progress;
 
 done:
-	obex = obc_session_get_obex(session);
 	req = g_obex_packet_new(G_OBEX_OP_PUT, FALSE, G_OBEX_HDR_INVALID);
 
 	if (transfer->name != NULL)
@@ -600,8 +597,9 @@ done:
 						transfer->params->data,
 						transfer->params->size);
 
-	transfer->xfer = g_obex_put_req_pkt(obex, req, data_cb, xfer_complete,
-							transfer, &err);
+	transfer->xfer = g_obex_put_req_pkt(transfer->obex, req, data_cb,
+						xfer_complete, transfer,
+						&err);
 	if (transfer->xfer == 0)
 		return -ENOTCONN;
 
@@ -625,7 +623,7 @@ void obc_transfer_clear_buffer(struct obc_transfer *transfer)
 	transfer->filled = 0;
 }
 
-const char *obc_transfer_get_buffer(struct obc_transfer *transfer, int *size)
+const char *obc_transfer_get_buffer(struct obc_transfer *transfer, size_t *size)
 {
 	if (size)
 		*size = transfer->filled;
diff --git a/client/transfer.h b/client/transfer.h
index c051cbd..e5387fc 100644
--- a/client/transfer.h
+++ b/client/transfer.h
@@ -33,11 +33,12 @@ typedef void (*transfer_callback_t) (struct obc_transfer *transfer,
 					void *user_data);
 
 struct obc_transfer *obc_transfer_register(DBusConnection *conn,
-						const char *filename,
-						const char *name,
-						const char *type,
-						struct obc_transfer_params *params,
-						void *user_data);
+					GObex *obex,
+					const char *agent,
+					const char *filename,
+					const char *name,
+					const char *type,
+					struct obc_transfer_params *params);
 
 void obc_transfer_unregister(struct obc_transfer *transfer);
 
@@ -48,7 +49,7 @@ int obc_transfer_put(struct obc_transfer *transfer, transfer_callback_t func,
 
 int obc_transfer_get_params(struct obc_transfer *transfer,
 					struct obc_transfer_params *params);
-const char *obc_transfer_get_buffer(struct obc_transfer *transfer, int *size);
+const char *obc_transfer_get_buffer(struct obc_transfer *transfer, size_t *size);
 void obc_transfer_set_buffer(struct obc_transfer *transfer, char *buffer);
 void obc_transfer_clear_buffer(struct obc_transfer *transfer);
 
-- 
1.7.7.5


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH obexd 2/6] client: remove unused field
  2012-01-20  9:49 [PATCH obexd 1/6] client: fix circular dependency of session and transfer Luiz Augusto von Dentz
@ 2012-01-20  9:49 ` Luiz Augusto von Dentz
  2012-01-20  9:49 ` [PATCH obexd 3/6] client: add support for transport drivers Luiz Augusto von Dentz
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2012-01-20  9:49 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

---
 client/session.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/client/session.c b/client/session.c
index 5dfbd47..7de1492 100644
--- a/client/session.c
+++ b/client/session.c
@@ -100,7 +100,6 @@ struct obc_session {
 	guint watch;
 	GSList *pending;
 	GSList *pending_calls;
-	void *priv;
 	char *adapter;
 };
 
-- 
1.7.7.5


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH obexd 3/6] client: add support for transport drivers
  2012-01-20  9:49 [PATCH obexd 1/6] client: fix circular dependency of session and transfer Luiz Augusto von Dentz
  2012-01-20  9:49 ` [PATCH obexd 2/6] client: remove unused field Luiz Augusto von Dentz
@ 2012-01-20  9:49 ` Luiz Augusto von Dentz
  2012-01-20  9:49 ` [PATCH obexd 4/6] client: add bluetooth transport driver Luiz Augusto von Dentz
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2012-01-20  9:49 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

---
 Makefile.am        |    1 +
 client/transport.c |   82 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 client/transport.h |   37 +++++++++++++++++++++++
 3 files changed, 120 insertions(+), 0 deletions(-)
 create mode 100644 client/transport.c
 create mode 100644 client/transport.h

diff --git a/Makefile.am b/Makefile.am
index f65a3dc..32ccc89 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -124,6 +124,7 @@ client_obex_client_SOURCES = $(gdbus_sources) $(gobex_sources) \
 				client/map.h client/map.c \
 				client/transfer.h client/transfer.c \
 				client/agent.h client/agent.c \
+				client/transport.h client/transport.c \
 				client/driver.h client/driver.c \
 				src/map_ap.h src/map_ap.c
 
diff --git a/client/transport.c b/client/transport.c
new file mode 100644
index 0000000..77e52f7
--- /dev/null
+++ b/client/transport.c
@@ -0,0 +1,82 @@
+/*
+ *
+ *  OBEX Server
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <errno.h>
+#include <glib.h>
+#include <inttypes.h>
+
+#include "transport.h"
+#include "log.h"
+
+static GSList *transports = NULL;
+
+struct obc_transport *obc_transport_find(const char *name)
+{
+	GSList *l;
+
+	for (l = transports; l; l = l->next) {
+		struct obc_transport *transport = l->data;
+
+		if (strcasecmp(name, transport->name) == 0)
+			return transport;
+	}
+
+	return NULL;
+}
+
+int obc_transport_register(struct obc_transport *transport)
+{
+	if (!transport) {
+		error("Invalid transport");
+		return -EINVAL;
+	}
+
+	if (obc_transport_find(transport->name)) {
+		error("Permission denied: transport %s already registered",
+							transport->name);
+		return -EPERM;
+	}
+
+	DBG("transport %p name %s registered", transport, transport->name);
+
+	transports = g_slist_append(transports, transport);
+
+	return 0;
+}
+
+void obc_transport_unregister(struct obc_transport *transport)
+{
+	if (!g_slist_find(transports, transport)) {
+		error("Unable to unregister: No such transport %p", transport);
+		return;
+	}
+
+	DBG("transport %p name %s unregistered", transport, transport->name);
+
+	transports = g_slist_remove(transports, transport);
+}
diff --git a/client/transport.h b/client/transport.h
new file mode 100644
index 0000000..4c9bf2d
--- /dev/null
+++ b/client/transport.h
@@ -0,0 +1,37 @@
+/*
+ *
+ *  OBEX Server
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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
+ *
+ */
+
+typedef void (*obc_transport_func)(GIOChannel *io, GError *err,
+							gpointer user_data);
+
+struct obc_transport {
+	const char *name;
+	guint (*connect) (const char *source, const char *destination,
+				const char *service, uint16_t port,
+				obc_transport_func func, void *user_data);
+	void (*disconnect) (guint id);
+};
+
+int obc_transport_register(struct obc_transport *transport);
+void obc_transport_unregister(struct obc_transport *transport);
+struct obc_transport *obc_transport_find(const char *name);
-- 
1.7.7.5


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH obexd 4/6] client: add bluetooth transport driver
  2012-01-20  9:49 [PATCH obexd 1/6] client: fix circular dependency of session and transfer Luiz Augusto von Dentz
  2012-01-20  9:49 ` [PATCH obexd 2/6] client: remove unused field Luiz Augusto von Dentz
  2012-01-20  9:49 ` [PATCH obexd 3/6] client: add support for transport drivers Luiz Augusto von Dentz
@ 2012-01-20  9:49 ` Luiz Augusto von Dentz
  2012-01-20  9:50 ` [PATCH obexd 5/6] client: move bluetooth specific code from session.c to bluetooth.c Luiz Augusto von Dentz
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2012-01-20  9:49 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

---
 Makefile.am        |    1 +
 client/bluetooth.c |   69 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 client/bluetooth.h |   25 +++++++++++++++++++
 client/manager.c   |   20 ++++++++-------
 4 files changed, 106 insertions(+), 9 deletions(-)
 create mode 100644 client/bluetooth.c
 create mode 100644 client/bluetooth.h

diff --git a/Makefile.am b/Makefile.am
index 32ccc89..6697fa1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -117,6 +117,7 @@ client_obex_client_SOURCES = $(gdbus_sources) $(gobex_sources) \
 				client/main.c src/log.h src/log.c \
 				client/manager.h client/manager.c \
 				client/session.h client/session.c \
+				client/bluetooth.h client/bluetooth.c \
 				client/sync.h client/sync.c \
 				client/pbap.h client/pbap.c \
 				client/ftp.h client/ftp.c \
diff --git a/client/bluetooth.c b/client/bluetooth.c
new file mode 100644
index 0000000..5bde9be
--- /dev/null
+++ b/client/bluetooth.c
@@ -0,0 +1,69 @@
+/*
+ *
+ *  OBEX Client
+ *
+ *  Copyright (C) 2012 Intel Corporation
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <inttypes.h>
+
+#include <glib.h>
+
+#include "log.h"
+#include "transport.h"
+#include "bluetooth.h"
+
+static guint bluetooth_connect(const char *source, const char *destination,
+				const char *service, uint16_t port,
+				obc_transport_func func, void *user_data)
+{
+	DBG("");
+
+	return 0;
+}
+
+static void bluetooth_disconnect(guint id)
+{
+	DBG("");
+}
+
+static struct obc_transport bluetooth = {
+	.name = "Bluetooth",
+	.connect = bluetooth_connect,
+	.disconnect = bluetooth_disconnect,
+};
+
+int bluetooth_init(void)
+{
+	DBG("");
+
+	return obc_transport_register(&bluetooth);
+}
+
+void bluetooth_exit(void)
+{
+	DBG("");
+
+	obc_transport_unregister(&bluetooth);
+}
diff --git a/client/bluetooth.h b/client/bluetooth.h
new file mode 100644
index 0000000..968e131
--- /dev/null
+++ b/client/bluetooth.h
@@ -0,0 +1,25 @@
+/*
+ *
+ *  OBEX Client
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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
+ *
+ */
+
+int bluetooth_init(void);
+void bluetooth_exit(void);
diff --git a/client/manager.c b/client/manager.c
index 7841753..2e01e54 100644
--- a/client/manager.c
+++ b/client/manager.c
@@ -37,6 +37,7 @@
 #include "log.h"
 #include "session.h"
 #include "manager.h"
+#include "bluetooth.h"
 #include "opp.h"
 #include "ftp.h"
 #include "pbap.h"
@@ -557,11 +558,12 @@ static GDBusMethodTable client_methods[] = {
 
 static DBusConnection *conn = NULL;
 
-static struct target_module {
+static struct obc_module {
 	const char *name;
 	int (*init) (void);
 	void (*exit) (void);
-} targets[] = {
+} modules[] = {
+	{ "bluetooth", bluetooth_init, bluetooth_exit },
 	{ "opp", opp_init, opp_exit },
 	{ "ftp", ftp_init, ftp_exit },
 	{ "pbap", pbap_init, pbap_exit },
@@ -573,7 +575,7 @@ static struct target_module {
 int manager_init(void)
 {
 	DBusError derr;
-	struct target_module *target;
+	struct obc_module *module;
 
 	dbus_error_init(&derr);
 
@@ -593,11 +595,11 @@ int manager_init(void)
 		return -1;
 	}
 
-	for (target = targets; target && target->init; target++) {
-		if (target->init() < 0)
+	for (module = modules; module && module->init; module++) {
+		if (module->init() < 0)
 			continue;
 
-		DBG("Target %s loaded", target->name);
+		DBG("Module %s loaded", module->name);
 	}
 
 	return 0;
@@ -605,13 +607,13 @@ int manager_init(void)
 
 void manager_exit(void)
 {
-	struct target_module *target;
+	struct obc_module *module;
 
 	if (conn == NULL)
 		return;
 
-	for (target = targets; target && target->exit; target++)
-		target->exit();
+	for (module = modules; module && module->exit; module++)
+		module->exit();
 
 	g_dbus_unregister_interface(conn, CLIENT_PATH, CLIENT_INTERFACE);
 	dbus_connection_unref(conn);
-- 
1.7.7.5


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH obexd 5/6] client: move bluetooth specific code from session.c to bluetooth.c
  2012-01-20  9:49 [PATCH obexd 1/6] client: fix circular dependency of session and transfer Luiz Augusto von Dentz
                   ` (2 preceding siblings ...)
  2012-01-20  9:49 ` [PATCH obexd 4/6] client: add bluetooth transport driver Luiz Augusto von Dentz
@ 2012-01-20  9:50 ` Luiz Augusto von Dentz
  2012-01-20  9:50 ` [PATCH obexd 6/6] client: simplify handling of D-Bus pending calls in bluetooth.c Luiz Augusto von Dentz
  2012-01-20 15:05 ` [PATCH obexd 1/6] client: fix circular dependency of session and transfer Johan Hedberg
  5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2012-01-20  9:50 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This simplifies session.c code quite a bit and enables supporting other
transports in the future.
---
 client/bluetooth.c |  576 ++++++++++++++++++++++++++++++++++++++++++++++++-
 client/session.c   |  621 +++++++---------------------------------------------
 2 files changed, 658 insertions(+), 539 deletions(-)

diff --git a/client/bluetooth.c b/client/bluetooth.c
index 5bde9be..563124d 100644
--- a/client/bluetooth.c
+++ b/client/bluetooth.c
@@ -29,23 +29,597 @@
 #include <inttypes.h>
 
 #include <glib.h>
+#include <gdbus.h>
+#include <btio.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/rfcomm.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
 
 #include "log.h"
 #include "transport.h"
 #include "bluetooth.h"
 
+#define BT_BUS_NAME		"org.bluez"
+#define BT_PATH			"/"
+#define BT_ADAPTER_IFACE	"org.bluez.Adapter"
+#define BT_MANAGER_IFACE	"org.bluez.Manager"
+
+#define OBC_BT_ERROR obc_bt_error_quark()
+
+struct bluetooth_session {
+	guint id;
+	bdaddr_t src;
+	bdaddr_t dst;
+	uint16_t port;
+	DBusConnection *conn_system; /* system bus connection */
+	sdp_session_t *sdp;
+	GIOChannel *io;
+	GSList *pending_calls;
+	char *adapter;
+	char *service;
+	obc_transport_func func;
+	void *user_data;
+};
+
+struct pending_req {
+	DBusPendingCall *call;
+	void *user_data;
+};
+
+static GSList *sessions = NULL;
+
+static GQuark obc_bt_error_quark(void)
+{
+	return g_quark_from_static_string("obc-bluetooth-error-quark");
+}
+
+static struct pending_req *send_method_call(DBusConnection *connection,
+				const char *dest, const char *path,
+				const char *interface, const char *method,
+				DBusPendingCallNotifyFunction cb,
+				void *user_data, int type, ...)
+{
+	DBusMessage *msg;
+	DBusPendingCall *call;
+	va_list args;
+	struct pending_req *req;
+
+	msg = dbus_message_new_method_call(dest, path, interface, method);
+	if (!msg) {
+		error("Unable to allocate new D-Bus %s message", method);
+		return NULL;
+	}
+
+	va_start(args, type);
+
+	if (!dbus_message_append_args_valist(msg, type, args)) {
+		dbus_message_unref(msg);
+		va_end(args);
+		return NULL;
+	}
+
+	va_end(args);
+
+	if (!cb) {
+		g_dbus_send_message(connection, msg);
+		return 0;
+	}
+
+	if (!dbus_connection_send_with_reply(connection, msg, &call, -1)) {
+		error("Sending %s failed", method);
+		dbus_message_unref(msg);
+		return NULL;
+	}
+
+	dbus_pending_call_set_notify(call, cb, user_data, NULL);
+
+	req = g_new0(struct pending_req, 1);
+	req->call = call;
+	req->user_data = user_data;
+
+	dbus_message_unref(msg);
+
+	return req;
+}
+
+static void pending_req_finalize(struct pending_req *req)
+{
+	if (!dbus_pending_call_get_completed(req->call))
+		dbus_pending_call_cancel(req->call);
+
+	dbus_pending_call_unref(req->call);
+	g_free(req);
+}
+
+static void session_destroy(struct bluetooth_session *session)
+{
+	GSList *l;
+
+	DBG("%p", session);
+
+	if (g_slist_find(sessions, session) == NULL)
+		return;
+
+	sessions = g_slist_remove(sessions, session);
+
+	if (session->adapter)
+		send_method_call(session->conn_system,
+				BT_BUS_NAME, session->adapter,
+				BT_ADAPTER_IFACE, "ReleaseSession",
+				NULL, NULL,
+				DBUS_TYPE_INVALID);
+
+	l = session->pending_calls;
+
+	while (l) {
+		struct pending_req *req = l->data;
+		l = l->next;
+
+		session->pending_calls = g_slist_remove(session->pending_calls, req);
+		pending_req_finalize(req);
+	}
+
+	if (session->io != NULL) {
+		g_io_channel_shutdown(session->io, TRUE, NULL);
+		g_io_channel_unref(session->io);
+	}
+
+	if (session->conn_system)
+		dbus_connection_unref(session->conn_system);
+
+	g_free(session->service);
+	g_free(session->adapter);
+	g_free(session);
+}
+
+static void rfcomm_callback(GIOChannel *io, GError *err, gpointer user_data)
+{
+	struct bluetooth_session *session = user_data;
+
+	DBG("");
+
+	if (session->func)
+		session->func(io, err, session->user_data);
+
+	if (err != NULL)
+		session_destroy(session);
+}
+
+static GIOChannel *rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst,
+					uint8_t channel, BtIOConnect function,
+					gpointer user_data)
+{
+	GIOChannel *io;
+	GError *err = NULL;
+
+	DBG("");
+
+	io = bt_io_connect(BT_IO_RFCOMM, function, user_data, NULL, &err,
+				BT_IO_OPT_SOURCE_BDADDR, src,
+				BT_IO_OPT_DEST_BDADDR, dst,
+				BT_IO_OPT_CHANNEL, channel,
+				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+				BT_IO_OPT_INVALID);
+	if (io != NULL)
+		return io;
+
+	error("%s", err->message);
+	g_error_free(err);
+	return NULL;
+}
+
+static void search_callback(uint8_t type, uint16_t status,
+			uint8_t *rsp, size_t size, void *user_data)
+{
+	struct bluetooth_session *session = user_data;
+	unsigned int scanned, bytesleft = size;
+	int seqlen = 0;
+	uint8_t dataType, channel = 0;
+	GError *gerr = NULL;
+
+	if (status || type != SDP_SVC_SEARCH_ATTR_RSP)
+		goto failed;
+
+	scanned = sdp_extract_seqtype(rsp, bytesleft, &dataType, &seqlen);
+	if (!scanned || !seqlen)
+		goto failed;
+
+	rsp += scanned;
+	bytesleft -= scanned;
+	do {
+		sdp_record_t *rec;
+		sdp_list_t *protos;
+		int recsize, ch = -1;
+
+		recsize = 0;
+		rec = sdp_extract_pdu(rsp, bytesleft, &recsize);
+		if (!rec)
+			break;
+
+		if (!recsize) {
+			sdp_record_free(rec);
+			break;
+		}
+
+		if (!sdp_get_access_protos(rec, &protos)) {
+			ch = sdp_get_proto_port(protos, RFCOMM_UUID);
+			sdp_list_foreach(protos,
+					(sdp_list_func_t) sdp_list_free, NULL);
+			sdp_list_free(protos, NULL);
+			protos = NULL;
+		}
+
+		sdp_record_free(rec);
+
+		if (ch > 0) {
+			channel = ch;
+			break;
+		}
+
+		scanned += recsize;
+		rsp += recsize;
+		bytesleft -= recsize;
+	} while (scanned < size && bytesleft > 0);
+
+	if (channel == 0)
+		goto failed;
+
+	session->port = channel;
+
+	g_io_channel_set_close_on_unref(session->io, FALSE);
+	g_io_channel_unref(session->io);
+
+	session->io = rfcomm_connect(&session->src, &session->dst, channel,
+					rfcomm_callback, session);
+	if (session->io != NULL) {
+		sdp_close(session->sdp);
+		session->sdp = NULL;
+		return;
+	}
+
+failed:
+	g_io_channel_shutdown(session->io, TRUE, NULL);
+	g_io_channel_unref(session->io);
+	session->io = NULL;
+
+	g_set_error(&gerr, OBC_BT_ERROR, -EIO,
+					"Unable to find service record");
+	if (session->func)
+		session->func(session->io, gerr, session->user_data);
+	g_clear_error(&gerr);
+
+	session_destroy(session);
+}
+
+static gboolean process_callback(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	struct bluetooth_session *session = user_data;
+
+	if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL))
+		return FALSE;
+
+	if (sdp_process(session->sdp) < 0)
+		return FALSE;
+
+	return TRUE;
+}
+
+static int bt_string2uuid(uuid_t *uuid, const char *string)
+{
+	uint32_t data0, data4;
+	uint16_t data1, data2, data3, data5;
+
+	if (sscanf(string, "%08x-%04hx-%04hx-%04hx-%08x%04hx",
+				&data0, &data1, &data2, &data3, &data4, &data5) == 6) {
+		uint8_t val[16];
+
+		data0 = g_htonl(data0);
+		data1 = g_htons(data1);
+		data2 = g_htons(data2);
+		data3 = g_htons(data3);
+		data4 = g_htonl(data4);
+		data5 = g_htons(data5);
+
+		memcpy(&val[0], &data0, 4);
+		memcpy(&val[4], &data1, 2);
+		memcpy(&val[6], &data2, 2);
+		memcpy(&val[8], &data3, 2);
+		memcpy(&val[10], &data4, 4);
+		memcpy(&val[14], &data5, 2);
+
+		sdp_uuid128_create(uuid, val);
+
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static gboolean service_callback(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	struct bluetooth_session *session = user_data;
+	sdp_list_t *search, *attrid;
+	uint32_t range = 0x0000ffff;
+	GError *gerr = NULL;
+	uuid_t uuid;
+
+	if (cond & G_IO_NVAL)
+		return FALSE;
+
+	if (cond & G_IO_ERR)
+		goto failed;
+
+	if (sdp_set_notify(session->sdp, search_callback, session) < 0)
+		goto failed;
+
+	if (bt_string2uuid(&uuid, session->service) < 0)
+		goto failed;
+
+	search = sdp_list_append(NULL, &uuid);
+	attrid = sdp_list_append(NULL, &range);
+
+	if (sdp_service_search_attr_async(session->sdp,
+				search, SDP_ATTR_REQ_RANGE, attrid) < 0) {
+		sdp_list_free(attrid, NULL);
+		sdp_list_free(search, NULL);
+		goto failed;
+	}
+
+	sdp_list_free(attrid, NULL);
+	sdp_list_free(search, NULL);
+
+	g_io_add_watch(io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+						process_callback, session);
+
+	return FALSE;
+
+failed:
+	g_io_channel_shutdown(session->io, TRUE, NULL);
+	g_io_channel_unref(session->io);
+	session->io = NULL;
+
+	g_set_error(&gerr, OBC_BT_ERROR, -EIO,
+					"Unable to find service record");
+	if (session->func)
+		session->func(session->io, gerr, session->user_data);
+	g_clear_error(&gerr);
+
+	session_destroy(session);
+	return FALSE;
+}
+
+static sdp_session_t *service_connect(const bdaddr_t *src, const bdaddr_t *dst,
+					GIOFunc function, gpointer user_data)
+{
+	struct bluetooth_session *session = user_data;
+	sdp_session_t *sdp;
+	GIOChannel *io;
+
+	sdp = sdp_connect(src, dst, SDP_NON_BLOCKING);
+	if (sdp == NULL)
+		return NULL;
+
+	io = g_io_channel_unix_new(sdp_get_socket(sdp));
+	if (io == NULL) {
+		sdp_close(sdp);
+		return NULL;
+	}
+
+	g_io_add_watch(io, G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+							function, user_data);
+
+	session->io = io;
+
+	return sdp;
+}
+
+static int session_connect(struct bluetooth_session *session)
+{
+	int err;
+
+	if (session->port > 0) {
+		session->io = rfcomm_connect(&session->src, &session->dst,
+							session->port,
+							rfcomm_callback,
+							session);
+		err = (session->io == NULL) ? -EINVAL : 0;
+	} else {
+		session->sdp = service_connect(&session->src, &session->dst,
+						service_callback, session);
+		err = (session->sdp == NULL) ? -ENOMEM : 0;
+	}
+
+	return err;
+}
+
+static struct pending_req *find_session_request(
+				const struct bluetooth_session *session,
+				const DBusPendingCall *call)
+{
+	GSList *l;
+
+	for (l = session->pending_calls; l; l = l->next) {
+		struct pending_req *req = l->data;
+
+		if (req->call == call)
+			return req;
+	}
+
+	return NULL;
+}
+
+static void adapter_reply(DBusPendingCall *call, void *user_data)
+{
+	DBusError err;
+	DBusMessage *reply;
+	struct bluetooth_session *session = user_data;
+	struct pending_req *req = find_session_request(session, call);
+	GError *gerr = NULL;
+
+	reply = dbus_pending_call_steal_reply(call);
+
+	session->pending_calls = g_slist_remove(session->pending_calls, req);
+	pending_req_finalize(req);
+
+	dbus_error_init(&err);
+	if (dbus_set_error_from_message(&err, reply)) {
+		error("manager replied with an error: %s, %s",
+				err.name, err.message);
+		dbus_error_free(&err);
+
+		goto failed;
+	}
+
+	if (session_connect(session) < 0)
+		goto failed;
+
+	goto proceed;
+
+failed:
+	g_set_error(&gerr, OBC_BT_ERROR, -EINVAL,
+					"Unable to request session");
+	if (session->func)
+		session->func(session->io, gerr, session->user_data);
+	g_clear_error(&gerr);
+
+	session_destroy(session);
+
+proceed:
+	dbus_message_unref(reply);
+}
+
+static void manager_reply(DBusPendingCall *call, void *user_data)
+{
+	DBusError err;
+	DBusMessage *reply;
+	char *adapter;
+	struct bluetooth_session *session = user_data;
+	struct pending_req *req = find_session_request(session, call);
+	GError *gerr = NULL;
+
+	reply = dbus_pending_call_steal_reply(call);
+
+	session->pending_calls = g_slist_remove(session->pending_calls, req);
+	pending_req_finalize(req);
+
+	dbus_error_init(&err);
+	if (dbus_set_error_from_message(&err, reply)) {
+		error("manager replied with an error: %s, %s",
+				err.name, err.message);
+		dbus_error_free(&err);
+
+		goto failed;
+	}
+
+	if (dbus_message_get_args(reply, NULL,
+				DBUS_TYPE_OBJECT_PATH, &adapter,
+				DBUS_TYPE_INVALID)) {
+		DBG("adapter path %s", adapter);
+
+		session->adapter = g_strdup(adapter);
+		req = send_method_call(session->conn_system,
+					BT_BUS_NAME, adapter,
+					BT_ADAPTER_IFACE, "RequestSession",
+					adapter_reply, session,
+					DBUS_TYPE_INVALID);
+		if (!req)
+			goto failed;
+
+		session->pending_calls = g_slist_prepend(session->pending_calls,
+									req);
+	} else
+		goto failed;
+
+	goto proceed;
+
+failed:
+	g_set_error(&gerr, OBC_BT_ERROR, -EINVAL, "No adapter found");
+	if (session->func)
+		session->func(session->io, gerr, session->user_data);
+	g_clear_error(&gerr);
+
+	session_destroy(session);
+
+proceed:
+	dbus_message_unref(reply);
+}
+
 static guint bluetooth_connect(const char *source, const char *destination,
 				const char *service, uint16_t port,
 				obc_transport_func func, void *user_data)
 {
+	struct bluetooth_session *session;
+	struct pending_req *req;
+	static guint id = 0;
+
 	DBG("");
 
-	return 0;
+	if (destination == NULL)
+		return 0;
+
+	session = g_try_malloc0(sizeof(*session));
+	if (session == NULL)
+		return 0;
+
+	session->id = ++id;
+	session->func = func;
+	session->user_data = user_data;
+
+	session->conn_system = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
+	if (session->conn_system == NULL) {
+		g_free(session);
+		return 0;
+	}
+
+	session->service = g_strdup(service);
+	str2ba(destination, &session->dst);
+
+	if (source == NULL) {
+		bacpy(&session->src, BDADDR_ANY);
+		req = send_method_call(session->conn_system,
+				BT_BUS_NAME, BT_PATH,
+				BT_MANAGER_IFACE, "DefaultAdapter",
+				manager_reply, session,
+				DBUS_TYPE_INVALID);
+	} else {
+		str2ba(source, &session->src);
+		req = send_method_call(session->conn_system,
+				BT_BUS_NAME, BT_PATH,
+				BT_MANAGER_IFACE, "FindAdapter",
+				manager_reply, session,
+				DBUS_TYPE_STRING, &source,
+				DBUS_TYPE_INVALID);
+	}
+
+	if (req == NULL) {
+		g_free(session);
+		return 0;
+	}
+
+	session->pending_calls = g_slist_prepend(session->pending_calls, req);
+	sessions = g_slist_prepend(sessions, session);
+
+	return session->id;
 }
 
 static void bluetooth_disconnect(guint id)
 {
+	GSList *l;
+
 	DBG("");
+
+	for (l = sessions; l; l = l->next) {
+		struct bluetooth_session *session = l->data;
+
+		if (session->id == id) {
+			session_destroy(session);
+			return;
+		}
+	}
 }
 
 static struct obc_transport bluetooth = {
diff --git a/client/session.c b/client/session.c
index 7de1492..c127974 100644
--- a/client/session.c
+++ b/client/session.c
@@ -35,33 +35,22 @@
 #include <gdbus.h>
 #include <gobex.h>
 
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/rfcomm.h>
-#include <bluetooth/sdp.h>
-#include <bluetooth/sdp_lib.h>
-
 #include "log.h"
 #include "transfer.h"
 #include "session.h"
-#include "btio.h"
 #include "agent.h"
 #include "driver.h"
+#include "transport.h"
 
 #define SESSION_INTERFACE  "org.openobex.Session"
 #define SESSION_BASEPATH   "/org/openobex"
 
 #define OBEX_IO_ERROR obex_io_error_quark()
 
-#define BT_BUS_NAME		"org.bluez"
-#define BT_PATH			"/"
-#define BT_ADAPTER_IFACE	"org.bluez.Adapter"
-#define BT_MANAGER_IFACE	"org.bluez.Manager"
-
 static guint64 counter = 0;
 
 struct callback_data {
 	struct obc_session *session;
-	sdp_session_t *sdp;
 	session_callback_t func;
 	void *data;
 };
@@ -77,30 +66,23 @@ struct pending_data {
 	struct obc_transfer *transfer;
 };
 
-struct pending_req {
-	DBusPendingCall *call;
-	void *user_data;
-};
-
 struct obc_session {
+	guint id;
 	gint refcount;
-	bdaddr_t src;
-	bdaddr_t dst;
+	char *source;
+	char *destination;
 	uint8_t channel;
+	struct obc_transport *transport;
 	struct obc_driver *driver;
 	gchar *path;		/* Session path */
 	DBusConnection *conn;
-	DBusConnection *conn_system; /* system bus connection */
 	DBusMessage *msg;
 	GObex *obex;
-	GIOChannel *io;
 	struct obc_agent *agent;
 	struct session_callback *callback;
 	gchar *owner;		/* Session owner */
 	guint watch;
 	GSList *pending;
-	GSList *pending_calls;
-	char *adapter;
 };
 
 static GSList *sessions = NULL;
@@ -142,45 +124,10 @@ static void session_unregistered(struct obc_session *session)
 	g_free(path);
 }
 
-static struct pending_req *find_session_request(
-				const struct obc_session *session,
-				const DBusPendingCall *call)
-{
-	GSList *l;
-
-	for (l = session->pending_calls; l; l = l->next) {
-		struct pending_req *req = l->data;
-
-		if (req->call == call)
-			return req;
-	}
-
-	return NULL;
-}
-
-static void pending_req_finalize(struct pending_req *req)
-{
-	if (!dbus_pending_call_get_completed(req->call))
-		dbus_pending_call_cancel(req->call);
-
-	dbus_pending_call_unref(req->call);
-	g_free(req);
-}
-
 static void session_free(struct obc_session *session)
 {
-	GSList *l = session->pending_calls;
-
 	DBG("%p", session);
 
-	while (l) {
-		struct pending_req *req = l->data;
-		l = l->next;
-
-		session->pending_calls = g_slist_remove(session->pending_calls, req);
-		pending_req_finalize(req);
-	}
-
 	if (session->agent) {
 		obc_agent_release(session->agent);
 		obc_agent_free(session->agent);
@@ -192,10 +139,8 @@ static void session_free(struct obc_session *session)
 	if (session->obex != NULL)
 		g_obex_unref(session->obex);
 
-	if (session->io != NULL) {
-		g_io_channel_shutdown(session->io, TRUE, NULL);
-		g_io_channel_unref(session->io);
-	}
+	if (session->id > 0 && session->transport != NULL)
+		session->transport->disconnect(session->id);
 
 	if (session->path)
 		session_unregistered(session);
@@ -203,67 +148,16 @@ static void session_free(struct obc_session *session)
 	if (session->conn)
 		dbus_connection_unref(session->conn);
 
-	if (session->conn_system)
-		dbus_connection_unref(session->conn_system);
-
 	sessions = g_slist_remove(sessions, session);
 
-	g_free(session->adapter);
 	g_free(session->callback);
 	g_free(session->path);
 	g_free(session->owner);
+	g_free(session->source);
+	g_free(session->destination);
 	g_free(session);
 }
 
-static struct pending_req *send_method_call(DBusConnection *connection,
-				const char *dest, const char *path,
-				const char *interface, const char *method,
-				DBusPendingCallNotifyFunction cb,
-				void *user_data, int type, ...)
-{
-	DBusMessage *msg;
-	DBusPendingCall *call;
-	va_list args;
-	struct pending_req *req;
-
-	msg = dbus_message_new_method_call(dest, path, interface, method);
-	if (!msg) {
-		error("Unable to allocate new D-Bus %s message", method);
-		return NULL;
-	}
-
-	va_start(args, type);
-
-	if (!dbus_message_append_args_valist(msg, type, args)) {
-		dbus_message_unref(msg);
-		va_end(args);
-		return NULL;
-	}
-
-	va_end(args);
-
-	if (!cb) {
-		g_dbus_send_message(connection, msg);
-		return 0;
-	}
-
-	if (!dbus_connection_send_with_reply(connection, msg, &call, -1)) {
-		error("Sending %s failed", method);
-		dbus_message_unref(msg);
-		return NULL;
-	}
-
-	dbus_pending_call_set_notify(call, cb, user_data, NULL);
-
-	req = g_new0(struct pending_req, 1);
-	req->call = call;
-	req->user_data = user_data;
-
-	dbus_message_unref(msg);
-
-	return req;
-}
-
 void obc_session_unref(struct obc_session *session)
 {
 	gboolean ret;
@@ -275,11 +169,6 @@ void obc_session_unref(struct obc_session *session)
 	if (ret == FALSE)
 		return;
 
-	send_method_call(session->conn_system,
-				BT_BUS_NAME, session->adapter,
-				BT_ADAPTER_IFACE, "ReleaseSession",
-				NULL, NULL,
-				DBUS_TYPE_INVALID);
 	session_free(session);
 }
 
@@ -309,7 +198,7 @@ done:
 	g_free(callback);
 }
 
-static void rfcomm_callback(GIOChannel *io, GError *err, gpointer user_data)
+static void transport_func(GIOChannel *io, GError *err, gpointer user_data)
 {
 	struct callback_data *callback = user_data;
 	struct obc_session *session = callback->session;
@@ -323,15 +212,13 @@ static void rfcomm_callback(GIOChannel *io, GError *err, gpointer user_data)
 		goto done;
 	}
 
-	g_io_channel_set_close_on_unref(session->io, FALSE);
+	g_io_channel_set_close_on_unref(io, FALSE);
 
-	obex = g_obex_new(session->io, G_OBEX_TRANSPORT_STREAM, -1, -1);
+	obex = g_obex_new(io, G_OBEX_TRANSPORT_STREAM, -1, -1);
 	if (obex == NULL)
 		goto done;
 
-	g_io_channel_set_close_on_unref(session->io, TRUE);
-	g_io_channel_unref(session->io);
-	session->io = NULL;
+	g_io_channel_set_close_on_unref(io, TRUE);
 
 	if (driver->target != NULL)
 		g_obex_connect(obex, connect_cb, callback, &err,
@@ -357,247 +244,6 @@ done:
 	g_free(callback);
 }
 
-static GIOChannel *rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst,
-					uint8_t channel, BtIOConnect function,
-					gpointer user_data)
-{
-	GIOChannel *io;
-	GError *err = NULL;
-
-	DBG("");
-
-	io = bt_io_connect(BT_IO_RFCOMM, function, user_data, NULL, &err,
-				BT_IO_OPT_SOURCE_BDADDR, src,
-				BT_IO_OPT_DEST_BDADDR, dst,
-				BT_IO_OPT_CHANNEL, channel,
-				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
-				BT_IO_OPT_INVALID);
-	if (io != NULL)
-		return io;
-
-	error("%s", err->message);
-	g_error_free(err);
-	return NULL;
-}
-
-static void search_callback(uint8_t type, uint16_t status,
-			uint8_t *rsp, size_t size, void *user_data)
-{
-	struct callback_data *callback = user_data;
-	struct obc_session *session = callback->session;
-	unsigned int scanned, bytesleft = size;
-	int seqlen = 0;
-	uint8_t dataType, channel = 0;
-	GError *gerr = NULL;
-
-	if (status || type != SDP_SVC_SEARCH_ATTR_RSP)
-		goto failed;
-
-	scanned = sdp_extract_seqtype(rsp, bytesleft, &dataType, &seqlen);
-	if (!scanned || !seqlen)
-		goto failed;
-
-	rsp += scanned;
-	bytesleft -= scanned;
-	do {
-		sdp_record_t *rec;
-		sdp_list_t *protos;
-		int recsize, ch = -1;
-
-		recsize = 0;
-		rec = sdp_extract_pdu(rsp, bytesleft, &recsize);
-		if (!rec)
-			break;
-
-		if (!recsize) {
-			sdp_record_free(rec);
-			break;
-		}
-
-		if (!sdp_get_access_protos(rec, &protos)) {
-			ch = sdp_get_proto_port(protos, RFCOMM_UUID);
-			sdp_list_foreach(protos,
-					(sdp_list_func_t) sdp_list_free, NULL);
-			sdp_list_free(protos, NULL);
-			protos = NULL;
-		}
-
-		sdp_record_free(rec);
-
-		if (ch > 0) {
-			channel = ch;
-			break;
-		}
-
-		scanned += recsize;
-		rsp += recsize;
-		bytesleft -= recsize;
-	} while (scanned < size && bytesleft > 0);
-
-	if (channel == 0)
-		goto failed;
-
-	session->channel = channel;
-
-	g_io_channel_set_close_on_unref(session->io, FALSE);
-	g_io_channel_unref(session->io);
-
-	session->io = rfcomm_connect(&session->src, &session->dst, channel,
-					rfcomm_callback, callback);
-	if (session->io != NULL) {
-		sdp_close(callback->sdp);
-		return;
-	}
-
-failed:
-	g_io_channel_shutdown(session->io, TRUE, NULL);
-	g_io_channel_unref(session->io);
-	session->io = NULL;
-
-	g_set_error(&gerr, OBEX_IO_ERROR, -EIO,
-					"Unable to find service record");
-	callback->func(session, gerr, callback->data);
-	g_clear_error(&gerr);
-
-	obc_session_unref(callback->session);
-	g_free(callback);
-}
-
-static gboolean process_callback(GIOChannel *io, GIOCondition cond,
-							gpointer user_data)
-{
-	struct callback_data *callback = user_data;
-
-	if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL))
-		return FALSE;
-
-	if (sdp_process(callback->sdp) < 0)
-		return FALSE;
-
-	return TRUE;
-}
-
-static int bt_string2uuid(uuid_t *uuid, const char *string)
-{
-	uint32_t data0, data4;
-	uint16_t data1, data2, data3, data5;
-
-	if (sscanf(string, "%08x-%04hx-%04hx-%04hx-%08x%04hx",
-				&data0, &data1, &data2, &data3, &data4, &data5) == 6) {
-		uint8_t val[16];
-
-		data0 = g_htonl(data0);
-		data1 = g_htons(data1);
-		data2 = g_htons(data2);
-		data3 = g_htons(data3);
-		data4 = g_htonl(data4);
-		data5 = g_htons(data5);
-
-		memcpy(&val[0], &data0, 4);
-		memcpy(&val[4], &data1, 2);
-		memcpy(&val[6], &data2, 2);
-		memcpy(&val[8], &data3, 2);
-		memcpy(&val[10], &data4, 4);
-		memcpy(&val[14], &data5, 2);
-
-		sdp_uuid128_create(uuid, val);
-
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-static gboolean service_callback(GIOChannel *io, GIOCondition cond,
-							gpointer user_data)
-{
-	struct callback_data *callback = user_data;
-	struct obc_session *session = callback->session;
-	sdp_list_t *search, *attrid;
-	uint32_t range = 0x0000ffff;
-	GError *gerr = NULL;
-	uuid_t uuid;
-
-	if (cond & (G_IO_NVAL | G_IO_ERR))
-		goto failed;
-
-	if (sdp_set_notify(callback->sdp, search_callback, callback) < 0)
-		goto failed;
-
-	if (bt_string2uuid(&uuid, session->driver->uuid) < 0)
-		goto failed;
-
-	search = sdp_list_append(NULL, &uuid);
-	attrid = sdp_list_append(NULL, &range);
-
-	if (sdp_service_search_attr_async(callback->sdp,
-				search, SDP_ATTR_REQ_RANGE, attrid) < 0) {
-		sdp_list_free(attrid, NULL);
-		sdp_list_free(search, NULL);
-		goto failed;
-	}
-
-	sdp_list_free(attrid, NULL);
-	sdp_list_free(search, NULL);
-
-	g_io_add_watch(io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
-						process_callback, callback);
-
-	return FALSE;
-
-failed:
-	g_io_channel_shutdown(session->io, TRUE, NULL);
-	g_io_channel_unref(session->io);
-	session->io = NULL;
-
-	g_set_error(&gerr, OBEX_IO_ERROR, -EIO,
-					"Unable to find service record");
-	callback->func(callback->session, gerr, callback->data);
-	g_clear_error(&gerr);
-
-	obc_session_unref(callback->session);
-	g_free(callback);
-	return FALSE;
-}
-
-static sdp_session_t *service_connect(const bdaddr_t *src, const bdaddr_t *dst,
-					GIOFunc function, gpointer user_data)
-{
-	struct callback_data *cb = user_data;
-	sdp_session_t *sdp;
-	GIOChannel *io;
-
-	sdp = sdp_connect(src, dst, SDP_NON_BLOCKING);
-	if (sdp == NULL)
-		return NULL;
-
-	io = g_io_channel_unix_new(sdp_get_socket(sdp));
-	if (io == NULL) {
-		sdp_close(sdp);
-		return NULL;
-	}
-
-	g_io_add_watch(io, G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
-							function, user_data);
-
-	cb->session->io = io;
-
-	return sdp;
-}
-
-static gboolean connection_complete(gpointer data)
-{
-	struct callback_data *cb = data;
-
-	cb->func(cb->session, 0, cb->data);
-
-	obc_session_unref(cb->session);
-
-	g_free(cb);
-
-	return FALSE;
-}
-
 static void owner_disconnected(DBusConnection *connection, void *user_data)
 {
 	struct obc_session *session = user_data;
@@ -626,6 +272,7 @@ int obc_session_set_owner(struct obc_session *session, const char *name,
 	return 0;
 }
 
+
 static struct obc_session *session_find(const char *source,
 						const char *destination,
 						const char *service,
@@ -636,21 +283,16 @@ static struct obc_session *session_find(const char *source,
 
 	for (l = sessions; l; l = l->next) {
 		struct obc_session *session = l->data;
-		bdaddr_t adr;
 
-		if (source) {
-			str2ba(source, &adr);
-			if (bacmp(&session->src, &adr))
-				continue;
-		}
-
-		str2ba(destination, &adr);
-		if (bacmp(&session->dst, &adr))
+		if (g_strcmp0(session->destination, destination))
 			continue;
 
 		if (g_strcmp0(service, session->driver->service))
 			continue;
 
+		if (source && g_strcmp0(session->source, source))
+			continue;
+
 		if (channel && session->channel != channel)
 			continue;
 
@@ -663,114 +305,54 @@ static struct obc_session *session_find(const char *source,
 	return NULL;
 }
 
-static int session_connect(struct obc_session *session,
-						struct callback_data *callback)
-{
-	int err;
-
-	if (session->obex) {
-		g_idle_add(connection_complete, callback);
-		err = 0;
-	} else if (session->channel > 0) {
-		session->io = rfcomm_connect(&session->src, &session->dst,
-							session->channel,
-							rfcomm_callback,
-							callback);
-		err = (session->io == NULL) ? -EINVAL : 0;
-	} else {
-		callback->sdp = service_connect(&session->src, &session->dst,
-						service_callback, callback);
-		err = (callback->sdp == NULL) ? -ENOMEM : 0;
-	}
-
-	return err;
-}
-
-static void adapter_reply(DBusPendingCall *call, void *user_data)
+static gboolean connection_complete(gpointer data)
 {
-	DBusError err;
-	DBusMessage *reply;
-	struct callback_data *callback = user_data;
-	struct obc_session *session = callback->session;
-	struct pending_req *req = find_session_request(session, call);
-
-	reply = dbus_pending_call_steal_reply(call);
-
-	session->pending_calls = g_slist_remove(session->pending_calls, req);
-	pending_req_finalize(req);
-
-	dbus_error_init(&err);
-	if (dbus_set_error_from_message(&err, reply)) {
-		error("manager replied with an error: %s, %s",
-				err.name, err.message);
-		dbus_error_free(&err);
-
-		goto failed;
-	}
+	struct callback_data *cb = data;
 
-	if (session_connect(session, callback) < 0)
-		goto failed;
+	cb->func(cb->session, 0, cb->data);
 
-	goto proceed;
+	obc_session_unref(cb->session);
 
-failed:
-	obc_session_unref(session);
-	g_free(callback);
+	g_free(cb);
 
-proceed:
-	dbus_message_unref(reply);
+	return FALSE;
 }
 
-static void manager_reply(DBusPendingCall *call, void *user_data)
+static int session_connect(struct obc_session *session,
+				session_callback_t function, void *user_data)
 {
-	DBusError err;
-	DBusMessage *reply;
-	char *adapter;
-	struct callback_data *callback = user_data;
-	struct obc_session *session = callback->session;
-	struct pending_req *req = find_session_request(session, call);
-
-	reply = dbus_pending_call_steal_reply(call);
+	struct callback_data *callback;
+	struct obc_transport *transport = session->transport;
+	struct obc_driver *driver = session->driver;
 
-	session->pending_calls = g_slist_remove(session->pending_calls, req);
-	pending_req_finalize(req);
+	callback = g_try_malloc0(sizeof(*callback));
+	if (callback == NULL)
+		return -ENOMEM;
 
-	dbus_error_init(&err);
-	if (dbus_set_error_from_message(&err, reply)) {
-		error("manager replied with an error: %s, %s",
-				err.name, err.message);
-		dbus_error_free(&err);
+	callback->func = function;
+	callback->data = user_data;
+	callback->session = obc_session_ref(session);
 
-		goto failed;
+	/* Connection completed */
+	if (session->obex) {
+		g_idle_add(connection_complete, callback);
+		return 0;
 	}
 
-	if (dbus_message_get_args(reply, NULL,
-				DBUS_TYPE_OBJECT_PATH, &adapter,
-				DBUS_TYPE_INVALID)) {
-		DBG("adapter path %s", adapter);
-
-		session->adapter = g_strdup(adapter);
-		req = send_method_call(session->conn_system,
-					BT_BUS_NAME, adapter,
-					BT_ADAPTER_IFACE, "RequestSession",
-					adapter_reply, callback,
-					DBUS_TYPE_INVALID);
-		if (!req)
-			goto failed;
-
-		session->pending_calls = g_slist_prepend(session->pending_calls,
-									req);
-	} else
-		goto failed;
-
-	goto proceed;
+	/* Ongoing connection */
+	if (session->id > 0)
+		return 0;
 
-failed:
-	obc_session_unref(session);
-	g_free(callback);
+	session->id = transport->connect(session->source, session->destination,
+					driver->uuid, session->channel,
+					transport_func, callback);
+	if (session->id == 0) {
+		obc_session_unref(callback->session);
+		g_free(callback);
+		return -EINVAL;
+	}
 
-proceed:
-	dbus_message_unref(reply);
+	return 0;
 }
 
 struct obc_session *obc_session_create(const char *source,
@@ -781,89 +363,54 @@ struct obc_session *obc_session_create(const char *source,
 						session_callback_t function,
 						void *user_data)
 {
+	DBusConnection *conn;
 	struct obc_session *session;
-	struct callback_data *callback;
-	struct pending_req *req;
+	struct obc_transport *transport;
 	struct obc_driver *driver;
 
 	if (destination == NULL)
 		return NULL;
 
 	session = session_find(source, destination, service, channel, owner);
-	if (session) {
-		obc_session_ref(session);
+	if (session != NULL)
 		goto proceed;
-	}
 
-	driver = obc_driver_find(service);
-	if (!driver)
+	/* FIXME: Do proper transport lookup when the API supports it */
+	transport = obc_transport_find("Bluetooth");
+	if (transport == NULL)
 		return NULL;
 
-	session = g_try_malloc0(sizeof(*session));
-	if (session == NULL)
+	driver = obc_driver_find(service);
+	if (driver == NULL)
 		return NULL;
 
-	session->refcount = 1;
-	session->channel = channel;
-
-	session->conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
-	if (session->conn == NULL) {
-		session_free(session);
+	conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
+	if (conn == NULL)
 		return NULL;
-	}
 
-	session->conn_system = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
-	if (session->conn_system == NULL) {
-		session_free(session);
+	session = g_try_malloc0(sizeof(*session));
+	if (session == NULL)
 		return NULL;
-	}
-
-	if (source == NULL)
-		bacpy(&session->src, BDADDR_ANY);
-	else
-		str2ba(source, &session->src);
 
-	str2ba(destination, &session->dst);
+	session->refcount = 1;
+	session->transport = transport;
 	session->driver = driver;
+	session->conn = conn;
+	session->source = g_strdup(source);
+	session->destination = g_strdup(destination);
+	session->channel = channel;
 
-	DBG("driver %s", driver->service);
+	if (owner)
+		obc_session_set_owner(session, owner, owner_disconnected);
 
 proceed:
-	callback = g_try_malloc0(sizeof(*callback));
-	if (callback == NULL) {
+	if (session_connect(session, function, user_data) < 0) {
 		obc_session_unref(session);
 		return NULL;
 	}
 
-	callback->session = obc_session_ref(session);
-	callback->func = function;
-	callback->data = user_data;
-
-	if (source) {
-		req = send_method_call(session->conn_system,
-				BT_BUS_NAME, BT_PATH,
-				BT_MANAGER_IFACE, "FindAdapter",
-				manager_reply, callback,
-				DBUS_TYPE_STRING, &source,
-				DBUS_TYPE_INVALID);
-	} else {
-		req = send_method_call(session->conn_system,
-				BT_BUS_NAME, BT_PATH,
-				BT_MANAGER_IFACE, "DefaultAdapter",
-				manager_reply, callback,
-				DBUS_TYPE_INVALID);
-	}
-
-	if (!req) {
-		obc_session_unref(session);
-		g_free(callback);
-		return NULL;
-	}
-
-	session->pending_calls = g_slist_prepend(session->pending_calls, req);
-
-	if (owner)
-		obc_session_set_owner(session, owner, owner_disconnected);
+	DBG("session %p transport %s driver %s", session,
+			session->transport->name, session->driver->service);
 
 	return session;
 }
@@ -900,15 +447,14 @@ void obc_session_shutdown(struct obc_session *session)
 		obc_session_remove_transfer(session, transfer);
 	}
 
-
 	/* Unregister interfaces */
 	if (session->path)
 		session_unregistered(session);
 
-	/* Shutdown io */
-	if (session->io) {
-		int fd = g_io_channel_unix_get_fd(session->io);
-		shutdown(fd, SHUT_RDWR);
+	/* Disconnect transport */
+	if (session->id > 0 && session->transport != NULL) {
+		session->transport->disconnect(session->id);
+		session->id = 0;
 	}
 
 	obc_session_unref(session);
@@ -1008,8 +554,6 @@ static DBusMessage *session_get_properties(DBusConnection *connection,
 	struct obc_session *session = user_data;
 	DBusMessage *reply;
 	DBusMessageIter iter, dict;
-	char addr[18];
-	char *paddr = addr;
 
 	reply = dbus_message_new_method_return(message);
 	if (!reply)
@@ -1022,11 +566,12 @@ static DBusMessage *session_get_properties(DBusConnection *connection,
 			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
 			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
 
-	ba2str(&session->src, addr);
-	append_entry(&dict, "Source", DBUS_TYPE_STRING, &paddr);
+	if (session->source != NULL)
+		append_entry(&dict, "Source", DBUS_TYPE_STRING,
+							&session->source);
 
-	ba2str(&session->dst, addr);
-	append_entry(&dict, "Destination", DBUS_TYPE_STRING, &paddr);
+	append_entry(&dict, "Destination", DBUS_TYPE_STRING,
+							&session->destination);
 
 	append_entry(&dict, "Channel", DBUS_TYPE_BYTE, &session->channel);
 
-- 
1.7.7.5


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH obexd 6/6] client: simplify handling of D-Bus pending calls in bluetooth.c
  2012-01-20  9:49 [PATCH obexd 1/6] client: fix circular dependency of session and transfer Luiz Augusto von Dentz
                   ` (3 preceding siblings ...)
  2012-01-20  9:50 ` [PATCH obexd 5/6] client: move bluetooth specific code from session.c to bluetooth.c Luiz Augusto von Dentz
@ 2012-01-20  9:50 ` Luiz Augusto von Dentz
  2012-01-20 15:05 ` [PATCH obexd 1/6] client: fix circular dependency of session and transfer Johan Hedberg
  5 siblings, 0 replies; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2012-01-20  9:50 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

There is no much of point to have a user_data if it is always the same
type, besides this code is very inefficient and cause a lookup in the list
of pending calls everytime a reply is received.
---
 client/bluetooth.c |  177 ++++++++++++++++++++-------------------------------
 1 files changed, 70 insertions(+), 107 deletions(-)

diff --git a/client/bluetooth.c b/client/bluetooth.c
index 563124d..3441d4b 100644
--- a/client/bluetooth.c
+++ b/client/bluetooth.c
@@ -53,7 +53,7 @@ struct bluetooth_session {
 	bdaddr_t src;
 	bdaddr_t dst;
 	uint16_t port;
-	DBusConnection *conn_system; /* system bus connection */
+	DBusConnection *conn; /* system bus connection */
 	sdp_session_t *sdp;
 	GIOChannel *io;
 	GSList *pending_calls;
@@ -63,11 +63,6 @@ struct bluetooth_session {
 	void *user_data;
 };
 
-struct pending_req {
-	DBusPendingCall *call;
-	void *user_data;
-};
-
 static GSList *sessions = NULL;
 
 static GQuark obc_bt_error_quark(void)
@@ -75,21 +70,22 @@ static GQuark obc_bt_error_quark(void)
 	return g_quark_from_static_string("obc-bluetooth-error-quark");
 }
 
-static struct pending_req *send_method_call(DBusConnection *connection,
-				const char *dest, const char *path,
-				const char *interface, const char *method,
-				DBusPendingCallNotifyFunction cb,
-				void *user_data, int type, ...)
+static int send_method_call(struct bluetooth_session *session,
+					const char *path,
+					const char *interface,
+					const char *method,
+					DBusPendingCallNotifyFunction cb,
+					int type, ...)
 {
 	DBusMessage *msg;
 	DBusPendingCall *call;
 	va_list args;
-	struct pending_req *req;
 
-	msg = dbus_message_new_method_call(dest, path, interface, method);
+	msg = dbus_message_new_method_call(BT_BUS_NAME, path, interface,
+								method);
 	if (!msg) {
 		error("Unable to allocate new D-Bus %s message", method);
-		return NULL;
+		return -ENOMEM;
 	}
 
 	va_start(args, type);
@@ -97,40 +93,35 @@ static struct pending_req *send_method_call(DBusConnection *connection,
 	if (!dbus_message_append_args_valist(msg, type, args)) {
 		dbus_message_unref(msg);
 		va_end(args);
-		return NULL;
+		return -EINVAL;
 	}
 
 	va_end(args);
 
 	if (!cb) {
-		g_dbus_send_message(connection, msg);
+		g_dbus_send_message(session->conn, msg);
 		return 0;
 	}
 
-	if (!dbus_connection_send_with_reply(connection, msg, &call, -1)) {
+	if (!dbus_connection_send_with_reply(session->conn, msg, &call, -1)) {
 		error("Sending %s failed", method);
 		dbus_message_unref(msg);
-		return NULL;
+		return -EIO;
 	}
 
-	dbus_pending_call_set_notify(call, cb, user_data, NULL);
-
-	req = g_new0(struct pending_req, 1);
-	req->call = call;
-	req->user_data = user_data;
+	dbus_pending_call_set_notify(call, cb, session, NULL);
 
-	dbus_message_unref(msg);
+	session->pending_calls = g_slist_prepend(session->pending_calls, call);
 
-	return req;
+	return 0;
 }
 
-static void pending_req_finalize(struct pending_req *req)
+static void finalize_call(DBusPendingCall *call)
 {
-	if (!dbus_pending_call_get_completed(req->call))
-		dbus_pending_call_cancel(req->call);
+	if (!dbus_pending_call_get_completed(call))
+		dbus_pending_call_cancel(call);
 
-	dbus_pending_call_unref(req->call);
-	g_free(req);
+	dbus_pending_call_unref(call);
 }
 
 static void session_destroy(struct bluetooth_session *session)
@@ -145,20 +136,18 @@ static void session_destroy(struct bluetooth_session *session)
 	sessions = g_slist_remove(sessions, session);
 
 	if (session->adapter)
-		send_method_call(session->conn_system,
-				BT_BUS_NAME, session->adapter,
-				BT_ADAPTER_IFACE, "ReleaseSession",
-				NULL, NULL,
-				DBUS_TYPE_INVALID);
+		send_method_call(session, session->adapter, BT_ADAPTER_IFACE,
+						"ReleaseSession", NULL,
+						DBUS_TYPE_INVALID);
 
 	l = session->pending_calls;
 
 	while (l) {
-		struct pending_req *req = l->data;
+		DBusPendingCall *call = l->data;
 		l = l->next;
 
-		session->pending_calls = g_slist_remove(session->pending_calls, req);
-		pending_req_finalize(req);
+		session->pending_calls = g_slist_remove(session->pending_calls, call);
+		finalize_call(call);
 	}
 
 	if (session->io != NULL) {
@@ -166,8 +155,8 @@ static void session_destroy(struct bluetooth_session *session)
 		g_io_channel_unref(session->io);
 	}
 
-	if (session->conn_system)
-		dbus_connection_unref(session->conn_system);
+	if (session->conn)
+		dbus_connection_unref(session->conn);
 
 	g_free(session->service);
 	g_free(session->adapter);
@@ -436,34 +425,17 @@ static int session_connect(struct bluetooth_session *session)
 	return err;
 }
 
-static struct pending_req *find_session_request(
-				const struct bluetooth_session *session,
-				const DBusPendingCall *call)
-{
-	GSList *l;
-
-	for (l = session->pending_calls; l; l = l->next) {
-		struct pending_req *req = l->data;
-
-		if (req->call == call)
-			return req;
-	}
-
-	return NULL;
-}
-
 static void adapter_reply(DBusPendingCall *call, void *user_data)
 {
+	struct bluetooth_session *session = user_data;
 	DBusError err;
 	DBusMessage *reply;
-	struct bluetooth_session *session = user_data;
-	struct pending_req *req = find_session_request(session, call);
 	GError *gerr = NULL;
 
 	reply = dbus_pending_call_steal_reply(call);
 
-	session->pending_calls = g_slist_remove(session->pending_calls, req);
-	pending_req_finalize(req);
+	session->pending_calls = g_slist_remove(session->pending_calls, call);
+	finalize_call(call);
 
 	dbus_error_init(&err);
 	if (dbus_set_error_from_message(&err, reply)) {
@@ -474,10 +446,8 @@ static void adapter_reply(DBusPendingCall *call, void *user_data)
 		goto failed;
 	}
 
-	if (session_connect(session) < 0)
-		goto failed;
-
-	goto proceed;
+	if (session_connect(session) == 0)
+		goto proceed;
 
 failed:
 	g_set_error(&gerr, OBC_BT_ERROR, -EINVAL,
@@ -492,19 +462,26 @@ proceed:
 	dbus_message_unref(reply);
 }
 
+static int request_session(struct bluetooth_session *session, const char *adapter)
+{
+	session->adapter = g_strdup(adapter);
+	return send_method_call(session, adapter, BT_ADAPTER_IFACE,
+					"RequestSession", adapter_reply,
+					DBUS_TYPE_INVALID);
+}
+
 static void manager_reply(DBusPendingCall *call, void *user_data)
 {
+	struct bluetooth_session *session = user_data;
 	DBusError err;
 	DBusMessage *reply;
 	char *adapter;
-	struct bluetooth_session *session = user_data;
-	struct pending_req *req = find_session_request(session, call);
 	GError *gerr = NULL;
 
 	reply = dbus_pending_call_steal_reply(call);
 
-	session->pending_calls = g_slist_remove(session->pending_calls, req);
-	pending_req_finalize(req);
+	session->pending_calls = g_slist_remove(session->pending_calls, call);
+	finalize_call(call);
 
 	dbus_error_init(&err);
 	if (dbus_set_error_from_message(&err, reply)) {
@@ -515,26 +492,15 @@ static void manager_reply(DBusPendingCall *call, void *user_data)
 		goto failed;
 	}
 
-	if (dbus_message_get_args(reply, NULL,
+	if (!dbus_message_get_args(reply, NULL,
 				DBUS_TYPE_OBJECT_PATH, &adapter,
-				DBUS_TYPE_INVALID)) {
-		DBG("adapter path %s", adapter);
-
-		session->adapter = g_strdup(adapter);
-		req = send_method_call(session->conn_system,
-					BT_BUS_NAME, adapter,
-					BT_ADAPTER_IFACE, "RequestSession",
-					adapter_reply, session,
-					DBUS_TYPE_INVALID);
-		if (!req)
-			goto failed;
-
-		session->pending_calls = g_slist_prepend(session->pending_calls,
-									req);
-	} else
+				DBUS_TYPE_INVALID))
 		goto failed;
 
-	goto proceed;
+	DBG("adapter path %s", adapter);
+
+	if (request_session(session, adapter) == 0)
+		goto proceed;
 
 failed:
 	g_set_error(&gerr, OBC_BT_ERROR, -EINVAL, "No adapter found");
@@ -548,12 +514,27 @@ proceed:
 	dbus_message_unref(reply);
 }
 
+static int find_adapter(struct bluetooth_session *session, const char *source)
+{
+	if (source == NULL) {
+		bacpy(&session->src, BDADDR_ANY);
+		return send_method_call(session, BT_PATH, BT_MANAGER_IFACE,
+					"DefaultAdapter", manager_reply,
+					DBUS_TYPE_INVALID);
+	}
+
+	str2ba(source, &session->src);
+	return send_method_call(session, BT_PATH, BT_MANAGER_IFACE,
+					"FindAdapter", manager_reply,
+					DBUS_TYPE_STRING, &source,
+					DBUS_TYPE_INVALID);
+}
+
 static guint bluetooth_connect(const char *source, const char *destination,
 				const char *service, uint16_t port,
 				obc_transport_func func, void *user_data)
 {
 	struct bluetooth_session *session;
-	struct pending_req *req;
 	static guint id = 0;
 
 	DBG("");
@@ -569,8 +550,8 @@ static guint bluetooth_connect(const char *source, const char *destination,
 	session->func = func;
 	session->user_data = user_data;
 
-	session->conn_system = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
-	if (session->conn_system == NULL) {
+	session->conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
+	if (session->conn == NULL) {
 		g_free(session);
 		return 0;
 	}
@@ -578,29 +559,11 @@ static guint bluetooth_connect(const char *source, const char *destination,
 	session->service = g_strdup(service);
 	str2ba(destination, &session->dst);
 
-	if (source == NULL) {
-		bacpy(&session->src, BDADDR_ANY);
-		req = send_method_call(session->conn_system,
-				BT_BUS_NAME, BT_PATH,
-				BT_MANAGER_IFACE, "DefaultAdapter",
-				manager_reply, session,
-				DBUS_TYPE_INVALID);
-	} else {
-		str2ba(source, &session->src);
-		req = send_method_call(session->conn_system,
-				BT_BUS_NAME, BT_PATH,
-				BT_MANAGER_IFACE, "FindAdapter",
-				manager_reply, session,
-				DBUS_TYPE_STRING, &source,
-				DBUS_TYPE_INVALID);
-	}
-
-	if (req == NULL) {
+	if (find_adapter(session, source) < 0) {
 		g_free(session);
 		return 0;
 	}
 
-	session->pending_calls = g_slist_prepend(session->pending_calls, req);
 	sessions = g_slist_prepend(sessions, session);
 
 	return session->id;
-- 
1.7.7.5


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH obexd 1/6] client: fix circular dependency of session and transfer
  2012-01-20  9:49 [PATCH obexd 1/6] client: fix circular dependency of session and transfer Luiz Augusto von Dentz
                   ` (4 preceding siblings ...)
  2012-01-20  9:50 ` [PATCH obexd 6/6] client: simplify handling of D-Bus pending calls in bluetooth.c Luiz Augusto von Dentz
@ 2012-01-20 15:05 ` Johan Hedberg
  5 siblings, 0 replies; 7+ messages in thread
From: Johan Hedberg @ 2012-01-20 15:05 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth

Hi Luiz,

On Fri, Jan 20, 2012, Luiz Augusto von Dentz wrote:
> Currently the code has to to pass session to transfer via user data
> (void *) only to be casted to session.
> ---
>  client/ftp.c      |    7 +--
>  client/manager.c  |    6 +--
>  client/map.c      |    9 +---
>  client/pbap.c     |   42 ++++-------------
>  client/session.c  |  129 ++++++++++++++++++++++++++++++++++++++++++++---------
>  client/session.h  |    8 +---
>  client/sync.c     |    8 +--
>  client/transfer.c |   68 ++++++++++++++--------------
>  client/transfer.h |   13 +++---
>  9 files changed, 168 insertions(+), 122 deletions(-)

All six patches have been applied. Thanks.

Johan

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2012-01-20 15:05 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-01-20  9:49 [PATCH obexd 1/6] client: fix circular dependency of session and transfer Luiz Augusto von Dentz
2012-01-20  9:49 ` [PATCH obexd 2/6] client: remove unused field Luiz Augusto von Dentz
2012-01-20  9:49 ` [PATCH obexd 3/6] client: add support for transport drivers Luiz Augusto von Dentz
2012-01-20  9:49 ` [PATCH obexd 4/6] client: add bluetooth transport driver Luiz Augusto von Dentz
2012-01-20  9:50 ` [PATCH obexd 5/6] client: move bluetooth specific code from session.c to bluetooth.c Luiz Augusto von Dentz
2012-01-20  9:50 ` [PATCH obexd 6/6] client: simplify handling of D-Bus pending calls in bluetooth.c Luiz Augusto von Dentz
2012-01-20 15:05 ` [PATCH obexd 1/6] client: fix circular dependency of session and transfer Johan Hedberg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).