* [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; 8+ 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, ¶ms) < 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, ¶ms) < 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] 8+ 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; 8+ 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] 8+ 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; 8+ 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] 8+ 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; 8+ 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] 8+ 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; 8+ 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] 8+ 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; 8+ 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] 8+ 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; 8+ 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] 8+ messages in thread
* [PATCH obexd 2/6] client: remove unused field
2012-04-19 14:06 [PATCH obexd 1/6] client: Remove buffer based transfer Luiz Augusto von Dentz
@ 2012-04-19 14:06 ` Luiz Augusto von Dentz
0 siblings, 0 replies; 8+ messages in thread
From: Luiz Augusto von Dentz @ 2012-04-19 14:06 UTC (permalink / raw)
To: linux-bluetooth
From: Mikel Astiz <mikel.astiz@bmw-carit.de>
The errorcode field is set but never used, so it can safely be removed.
In addition there is no need for such a field, because errors can be
propagated using the available callback.
---
client/transfer.c | 13 +++----------
1 files changed, 3 insertions(+), 10 deletions(-)
diff --git a/client/transfer.c b/client/transfer.c
index bc4324d..a40f849 100644
--- a/client/transfer.c
+++ b/client/transfer.c
@@ -67,7 +67,6 @@ struct obc_transfer {
guint xfer;
gint64 size;
gint64 transferred;
- int err;
};
static GQuark obc_transfer_error_quark(void)
@@ -288,10 +287,8 @@ static gboolean get_xfer_progress(const void *buf, gsize len,
gint w;
w = write(transfer->fd, buf, len);
- if (w < 0) {
- transfer->err = -errno;
+ if (w < 0)
return FALSE;
- }
transfer->transferred += w;
}
@@ -310,10 +307,8 @@ static void xfer_complete(GObex *obex, GError *err, gpointer user_data)
transfer->xfer = 0;
- if (err) {
- transfer->err = err->code;
+ if (err)
goto done;
- }
transfer->size = transfer->transferred;
@@ -390,10 +385,8 @@ static gssize put_xfer_progress(void *buf, gsize len, gpointer user_data)
gssize size;
size = read(transfer->fd, buf, len);
- if (size <= 0) {
- transfer->err = -errno;
+ if (size <= 0)
return size;
- }
if (callback)
callback->func(transfer, transfer->transferred, NULL,
--
1.7.7.6
^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2012-04-19 14:06 UTC | newest]
Thread overview: 8+ 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
-- strict thread matches above, loose matches on Subject: below --
2012-04-19 14:06 [PATCH obexd 1/6] client: Remove buffer based transfer Luiz Augusto von Dentz
2012-04-19 14:06 ` [PATCH obexd 2/6] client: remove unused field Luiz Augusto von Dentz
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).