summaryrefslogtreecommitdiffstats
path: root/audio
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2007-08-21 06:48:14 +0000
committerJohan Hedberg <johan.hedberg@nokia.com>2007-08-21 06:48:14 +0000
commitc92c420f83dda53ebde74ad72cd0a3959d430901 (patch)
treebe6d064f24fd36556d7475b6e5f027435802425b /audio
parentf4f92d015b2bf4b5478d62fb8f4d0e28443f25cf (diff)
Implement RequestAuthorization support
Diffstat (limited to 'audio')
-rw-r--r--audio/a2dp.c4
-rw-r--r--audio/avdtp.c89
-rw-r--r--audio/manager.c125
-rw-r--r--audio/manager.h7
-rw-r--r--audio/sink.c4
-rw-r--r--audio/unix.c5
6 files changed, 170 insertions, 64 deletions
diff --git a/audio/a2dp.c b/audio/a2dp.c
index 1e22e7c8..febc112c 100644
--- a/audio/a2dp.c
+++ b/audio/a2dp.c
@@ -607,8 +607,8 @@ int a2dp_init(DBusConnection *conn, gboolean enable_sink, gboolean enable_source
if (enable_sink) {
source.sep = avdtp_register_sep(AVDTP_SEP_TYPE_SOURCE,
- AVDTP_MEDIA_TYPE_AUDIO,
- &ind, &cfm);
+ AVDTP_MEDIA_TYPE_AUDIO,
+ &ind, &cfm);
if (source.sep == NULL)
return -1;
diff --git a/audio/avdtp.c b/audio/avdtp.c
index 57de80b9..be2709da 100644
--- a/audio/avdtp.c
+++ b/audio/avdtp.c
@@ -36,10 +36,13 @@
#include <glib.h>
#include <bluetooth/bluetooth.h>
+#include <bluetooth/sdp.h>
#include "dbus.h"
#include "logging.h"
+#include "device.h"
+#include "manager.h"
#include "avdtp.h"
#include <bluetooth/l2cap.h>
@@ -274,6 +277,8 @@ struct avdtp {
struct pending_req *req;
guint dc_timer;
+
+ DBusPendingCall *pending_auth;
};
struct avdtp_error {
@@ -1363,7 +1368,15 @@ static gboolean session_cb(GIOChannel *chan, GIOCondition cond,
return TRUE;
failed:
+ if (session->pending_auth) {
+ manager_cancel_authorize(&session->dst, ADVANCED_AUDIO_UUID,
+ session->pending_auth);
+ dbus_pending_call_unref(session->pending_auth);
+ session->pending_auth = NULL;
+ }
+
connection_lost(session, -EIO);
+
return FALSE;
}
@@ -2041,8 +2054,12 @@ static struct avdtp *avdtp_get_internal(bdaddr_t *src, bdaddr_t *dst)
assert(dst != NULL);
session = find_session(src, dst);
- if (session)
- return session;
+ if (session) {
+ if (session->pending_auth)
+ return NULL;
+ else
+ return session;
+ }
session = g_new0(struct avdtp, 1);
@@ -2063,6 +2080,9 @@ struct avdtp *avdtp_get(bdaddr_t *src, bdaddr_t *dst)
session = avdtp_get_internal(src, dst);
+ if (!session)
+ return NULL;
+
return avdtp_ref(session);
}
@@ -2463,6 +2483,51 @@ int avdtp_unregister_sep(struct avdtp_local_sep *sep)
return 0;
}
+static void auth_cb(DBusPendingCall *call, void *data)
+{
+ GIOChannel *io;
+ struct avdtp *session = data;
+ DBusMessage *reply = dbus_pending_call_steal_reply(call);
+ DBusError err;
+
+ dbus_pending_call_unref(session->pending_auth);
+ session->pending_auth = NULL;
+
+ dbus_error_init(&err);
+ if (dbus_set_error_from_message(&err, reply)) {
+ error("Access denied: %s", err.message);
+
+ if (dbus_error_has_name(&err, DBUS_ERROR_NO_REPLY)) {
+ debug("Canceling authorization request");
+ manager_cancel_authorize(&session->dst,
+ ADVANCED_AUDIO_UUID,
+ NULL);
+ }
+
+ dbus_error_free(&err);
+
+ connection_lost(session, -EACCES);
+
+ dbus_message_unref(reply);
+
+ return;
+ }
+
+ session->buf = g_malloc0(session->mtu);
+
+ set_disconnect_timer(session);
+
+ session->state = AVDTP_SESSION_STATE_CONNECTED;
+
+ g_source_remove(session->io);
+
+ io = g_io_channel_unix_new(session->sock);
+ session->io = g_io_add_watch(io,
+ G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ (GIOFunc) session_cb, session);
+ g_io_channel_unref(io);
+}
+
static gboolean avdtp_server_cb(GIOChannel *chan, GIOCondition cond, void *data)
{
int srv_sk, cli_sk;
@@ -2471,7 +2536,7 @@ static gboolean avdtp_server_cb(GIOChannel *chan, GIOCondition cond, void *data)
struct l2cap_options l2o;
bdaddr_t src, dst;
struct avdtp *session;
- GIOChannel *cli_io;
+ GIOChannel *io;
char address[18];
if (cond & G_IO_NVAL)
@@ -2529,19 +2594,19 @@ static gboolean avdtp_server_cb(GIOChannel *chan, GIOCondition cond, void *data)
return TRUE;
}
- if (session->ref == 1)
- set_disconnect_timer(session);
+ if (!manager_authorize(&dst, ADVANCED_AUDIO_UUID, auth_cb, session,
+ &session->pending_auth)) {
+ close(cli_sk);
+ return TRUE;
+ }
session->mtu = l2o.imtu;
- session->buf = g_malloc0(session->mtu);
session->sock = cli_sk;
- session->state = AVDTP_SESSION_STATE_CONNECTED;
- cli_io = g_io_channel_unix_new(session->sock);
- session->io = g_io_add_watch(cli_io,
- G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- (GIOFunc) session_cb, session);
- g_io_channel_unref(cli_io);
+ io = g_io_channel_unix_new(session->sock);
+ session->io = g_io_add_watch(io, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ (GIOFunc) session_cb, session);
+ g_io_channel_unref(io);
return TRUE;
}
diff --git a/audio/manager.c b/audio/manager.c
index 6eebce94..4d8d424d 100644
--- a/audio/manager.c
+++ b/audio/manager.c
@@ -1383,10 +1383,11 @@ int remove_service_record(DBusConnection *conn, uint32_t rec_id)
return 0;
}
-static void send_cancel_auth(struct device *device)
+static void auth_cb(DBusPendingCall *call, void *data)
{
- DBusMessage *cancel;
- char addr[18], *address = addr;
+ struct device *device = data;
+ DBusMessage *reply = dbus_pending_call_steal_reply(call);
+ DBusError err;
const char *uuid;
if (headset_get_type(device) == SVC_HEADSET)
@@ -1394,35 +1395,12 @@ static void send_cancel_auth(struct device *device)
else
uuid = HFP_AG_UUID;
- cancel = dbus_message_new_method_call("org.bluez", "/org/bluez",
- "org.bluez.Database",
- "CancelAuthorizationRequest");
- if (!cancel) {
- error("Unable to allocate new method call");
- return;
- }
-
- ba2str(&device->dst, addr);
-
- dbus_message_append_args(cancel, DBUS_TYPE_STRING, &address,
- DBUS_TYPE_STRING, &uuid,
- DBUS_TYPE_INVALID);
-
- send_message_and_unref(connection, cancel);
-}
-
-static void auth_cb(DBusPendingCall *call, void *data)
-{
- struct device *device = data;
- DBusMessage *reply = dbus_pending_call_steal_reply(call);
- DBusError err;
-
dbus_error_init(&err);
if (dbus_set_error_from_message(&err, reply)) {
error("Access denied: %s", err.message);
if (dbus_error_has_name(&err, DBUS_ERROR_NO_REPLY)) {
debug("Canceling authorization request");
- send_cancel_auth(device);
+ manager_cancel_authorize(&device->dst, uuid, NULL);
}
dbus_error_free(&err);
@@ -1446,11 +1424,8 @@ static gboolean ag_io_cb(GIOChannel *chan, GIOCondition cond, void *data)
int srv_sk, cli_sk;
struct sockaddr_rc addr;
socklen_t size;
- char hs_address[18], *address = hs_address;
const char *uuid;
struct device *device;
- DBusMessage *auth;
- DBusPendingCall *pending;
headset_type_t type;
if (cond & G_IO_NVAL)
@@ -1500,28 +1475,9 @@ static gboolean ag_io_cb(GIOChannel *chan, GIOCondition cond, void *data)
headset_set_type(device, type);
- auth = dbus_message_new_method_call("org.bluez", "/org/bluez",
- "org.bluez.Database",
- "RequestAuthorization");
- if (!auth) {
- error("Unable to allocate RequestAuthorization method call");
+ if (!manager_authorize(&device->dst, uuid, auth_cb, device, NULL))
goto failed;
- }
- ba2str(&device->dst, hs_address);
-
- dbus_message_append_args(auth, DBUS_TYPE_STRING, &address,
- DBUS_TYPE_STRING, &uuid,
- DBUS_TYPE_INVALID);
-
- if (!dbus_connection_send_with_reply(connection, auth, &pending, -1)) {
- error("Sending of authorization request failed");
- goto failed;
- }
-
- dbus_pending_call_set_notify(pending, auth_cb, device, NULL);
- dbus_pending_call_unref(pending);
- dbus_message_unref(auth);
headset_set_state(device, HEADSET_STATE_CONNECT_IN_PROGRESS);
return TRUE;
@@ -1734,3 +1690,72 @@ struct device *manager_get_connected_device(void)
return NULL;
}
+
+void manager_cancel_authorize(bdaddr_t *dba, const char *uuid,
+ DBusPendingCall *pending)
+{
+ DBusMessage *cancel;
+ char addr[18], *address = addr;
+
+ if (pending)
+ dbus_pending_call_cancel(pending);
+
+ cancel = dbus_message_new_method_call("org.bluez", "/org/bluez",
+ "org.bluez.Database",
+ "CancelAuthorizationRequest");
+ if (!cancel) {
+ error("Unable to allocate new method call");
+ return;
+ }
+
+ ba2str(dba, addr);
+
+ dbus_message_append_args(cancel, DBUS_TYPE_STRING, &address,
+ DBUS_TYPE_STRING, &uuid,
+ DBUS_TYPE_INVALID);
+
+ send_message_and_unref(connection, cancel);
+}
+
+gboolean manager_authorize(bdaddr_t *dba, const char *uuid,
+ DBusPendingCallNotifyFunction cb,
+ void *user_data,
+ DBusPendingCall **pending)
+{
+ DBusMessage *auth;
+ char address[18], *addr_ptr = address;
+ DBusPendingCall *p;
+
+ ba2str(dba, address);
+
+ debug("Requesting authorization for device %s, UUID %s",
+ address, uuid);
+
+ auth = dbus_message_new_method_call("org.bluez", "/org/bluez",
+ "org.bluez.Database",
+ "RequestAuthorization");
+ if (!auth) {
+ error("Unable to allocate RequestAuthorization method call");
+ return FALSE;
+ }
+
+ dbus_message_append_args(auth, DBUS_TYPE_STRING, &addr_ptr,
+ DBUS_TYPE_STRING, &uuid,
+ DBUS_TYPE_INVALID);
+
+ if (!dbus_connection_send_with_reply(connection, auth, &p, -1)) {
+ error("Sending of authorization request failed");
+ dbus_message_unref(auth);
+ return FALSE;
+ }
+
+ dbus_pending_call_set_notify(p, cb, user_data, NULL);
+ if (pending)
+ *pending = p;
+ else
+ dbus_pending_call_unref(p);
+
+ dbus_message_unref(auth);
+
+ return TRUE;
+}
diff --git a/audio/manager.h b/audio/manager.h
index a18cf4fd..65992040 100644
--- a/audio/manager.h
+++ b/audio/manager.h
@@ -47,3 +47,10 @@ struct device *manager_device_connected(bdaddr_t *bda, const char *uuid);
struct device *manager_default_device();
struct device *manager_get_connected_device(void);
+
+gboolean manager_authorize(bdaddr_t *dba, const char *uuid,
+ DBusPendingCallNotifyFunction cb,
+ void *user_data,
+ DBusPendingCall **pending);
+void manager_cancel_authorize(bdaddr_t *dba, const char *uuid,
+ DBusPendingCall *pending);
diff --git a/audio/sink.c b/audio/sink.c
index ab9f401b..c09c019f 100644
--- a/audio/sink.c
+++ b/audio/sink.c
@@ -160,6 +160,10 @@ static DBusHandlerResult sink_connect(DBusConnection *conn,
if (!sink->session)
sink->session = avdtp_get(&dev->src, &dev->dst);
+ if (!sink->session)
+ return err_connect_failed(conn, msg,
+ "Unable to get a session");
+
if (sink->connect || sink->disconnect)
return err_connect_failed(conn, msg, "Connect in progress");
diff --git a/audio/unix.c b/audio/unix.c
index 19a140c0..3488fd5f 100644
--- a/audio/unix.c
+++ b/audio/unix.c
@@ -317,6 +317,11 @@ proceed:
if (!a2dp->session)
a2dp->session = avdtp_get(&dev->src, &dev->dst);
+ if (!a2dp->session) {
+ error("Unable to get a session");
+ goto failed;
+ }
+
id = a2dp_source_request_stream(a2dp->session, dev,
TRUE, a2dp_setup_complete,
client);