summaryrefslogtreecommitdiffstats
path: root/audio/avdtp.c
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/avdtp.c
parentf4f92d015b2bf4b5478d62fb8f4d0e28443f25cf (diff)
Implement RequestAuthorization support
Diffstat (limited to 'audio/avdtp.c')
-rw-r--r--audio/avdtp.c89
1 files changed, 77 insertions, 12 deletions
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;
}