From: Mikel Astiz <mikel.astiz.oss@gmail.com>
To: linux-bluetooth@vger.kernel.org
Cc: Mikel Astiz <mikel.astiz@bmw-carit.de>
Subject: [RFC v4 1/9] media: Fix accesstype comparison
Date: Fri, 14 Sep 2012 14:03:08 +0200 [thread overview]
Message-ID: <1347624196-11281-2-git-send-email-mikel.astiz.oss@gmail.com> (raw)
In-Reply-To: <1347624196-11281-1-git-send-email-mikel.astiz.oss@gmail.com>
From: Mikel Astiz <mikel.astiz@bmw-carit.de>
Replace the string representation of the accesstype with a conventional
binary representation. This makes the code simpler and more efficient.
This also fixes a minor bug in the Release() D-Bus method, where the
string comparison was used to see whether the owner should be removed. A
client acquiring with "rw" and releasing with "wr" would lead to the
inconsistent state of having a released transport with an owner with no
accesstype. Partial releases can also get affected by this bug since the
released character (partial accesstype) got replaced by a whitespace.
Additionally, this approach is more robust in case new flags are added
in the future.
---
audio/transport.c | 119 ++++++++++++++++++++++++++++++-----------------------
1 files changed, 68 insertions(+), 51 deletions(-)
diff --git a/audio/transport.c b/audio/transport.c
index d40c92d..d418878 100644
--- a/audio/transport.c
+++ b/audio/transport.c
@@ -49,6 +49,11 @@
#define MEDIA_TRANSPORT_INTERFACE "org.bluez.MediaTransport"
+typedef enum {
+ TRANSPORT_LOCK_READ = 1,
+ TRANSPORT_LOCK_WRITE = 1 << 1,
+} transport_lock_t;
+
struct media_request {
DBusMessage *msg;
guint id;
@@ -58,7 +63,7 @@ struct media_owner {
struct media_transport *transport;
struct media_request *pending;
char *name;
- char *accesstype;
+ transport_lock_t lock;
guint watch;
};
@@ -84,8 +89,7 @@ struct media_transport {
int fd; /* Transport file descriptor */
uint16_t imtu; /* Transport input mtu */
uint16_t omtu; /* Transport output mtu */
- gboolean read_lock;
- gboolean write_lock;
+ transport_lock_t lock;
gboolean in_use;
guint (*resume) (struct media_transport *transport,
struct media_owner *owner);
@@ -104,6 +108,31 @@ struct media_transport {
void *data;
};
+static const char *lock2str(transport_lock_t lock)
+{
+ if (lock == 0)
+ return "";
+ else if (lock == TRANSPORT_LOCK_READ)
+ return "r";
+ else if (lock == TRANSPORT_LOCK_WRITE)
+ return "w";
+ else
+ return "rw";
+}
+
+static transport_lock_t str2lock(const char *str)
+{
+ transport_lock_t lock = 0;
+
+ if (g_strstr_len(str, -1, "r") != NULL)
+ lock |= TRANSPORT_LOCK_READ;
+
+ if (g_strstr_len(str, -1, "w") != NULL)
+ lock |= TRANSPORT_LOCK_WRITE;
+
+ return lock;
+}
+
void media_transport_destroy(struct media_transport *transport)
{
char *path;
@@ -148,17 +177,15 @@ static void media_request_reply(struct media_request *req,
}
static gboolean media_transport_release(struct media_transport *transport,
- const char *accesstype)
+ transport_lock_t lock)
{
- if (g_strstr_len(accesstype, -1, "r") != NULL) {
- transport->read_lock = FALSE;
+ transport->lock &= ~lock;
+
+ if (lock & TRANSPORT_LOCK_READ)
DBG("Transport %s: read lock released", transport->path);
- }
- if (g_strstr_len(accesstype, -1, "w") != NULL) {
- transport->write_lock = FALSE;
+ if (lock & TRANSPORT_LOCK_WRITE)
DBG("Transport %s: write lock released", transport->path);
- }
return TRUE;
}
@@ -191,7 +218,6 @@ static void media_owner_free(struct media_owner *owner)
media_owner_remove(owner);
g_free(owner->name);
- g_free(owner->accesstype);
g_free(owner);
}
@@ -200,7 +226,7 @@ static void media_transport_remove(struct media_transport *transport,
{
DBG("Transport %s Owner %s", transport->path, owner->name);
- media_transport_release(transport, owner->accesstype);
+ media_transport_release(transport, owner->lock);
/* Reply if owner has a pending request */
if (owner->pending)
@@ -260,10 +286,10 @@ static void a2dp_resume_complete(struct avdtp *session,
media_transport_set_fd(transport, fd, imtu, omtu);
- if (g_strstr_len(owner->accesstype, -1, "r") == NULL)
+ if ((owner->lock & TRANSPORT_LOCK_READ) == 0)
imtu = 0;
- if (g_strstr_len(owner->accesstype, -1, "w") == NULL)
+ if ((owner->lock & TRANSPORT_LOCK_WRITE) == 0)
omtu = 0;
ret = g_dbus_send_reply(transport->conn, req->msg,
@@ -371,10 +397,10 @@ static void headset_resume_complete(struct audio_device *dev, void *user_data)
media_transport_set_fd(transport, fd, imtu, omtu);
- if (g_strstr_len(owner->accesstype, -1, "r") == NULL)
+ if ((owner->lock & TRANSPORT_LOCK_READ) == 0)
imtu = 0;
- if (g_strstr_len(owner->accesstype, -1, "w") == NULL)
+ if ((owner->lock & TRANSPORT_LOCK_WRITE) == 0)
omtu = 0;
ret = g_dbus_send_reply(transport->conn, req->msg,
@@ -476,10 +502,10 @@ static void gateway_resume_complete(struct audio_device *dev, GError *err,
media_transport_set_fd(transport, fd, imtu, omtu);
- if (g_strstr_len(owner->accesstype, -1, "r") == NULL)
+ if ((owner->lock & TRANSPORT_LOCK_READ) == 0)
imtu = 0;
- if (g_strstr_len(owner->accesstype, -1, "w") == NULL)
+ if ((owner->lock & TRANSPORT_LOCK_WRITE) == 0)
omtu = 0;
ret = g_dbus_send_reply(transport->conn, req->msg,
@@ -569,35 +595,18 @@ static void media_owner_exit(DBusConnection *connection, void *user_data)
}
static gboolean media_transport_acquire(struct media_transport *transport,
- const char *accesstype)
+ transport_lock_t lock)
{
- gboolean read_lock = FALSE, write_lock = FALSE;
-
- if (g_strstr_len(accesstype, -1, "r") != NULL) {
- if (transport->read_lock == TRUE)
- return FALSE;
- read_lock = TRUE;
- }
-
- if (g_strstr_len(accesstype, -1, "w") != NULL) {
- if (transport->write_lock == TRUE)
- return FALSE;
- write_lock = TRUE;
- }
-
- /* Check invalid accesstype */
- if (read_lock == FALSE && write_lock == FALSE)
+ if (transport->lock & lock)
return FALSE;
- if (read_lock) {
- transport->read_lock = read_lock;
+ transport->lock |= lock;
+
+ if (lock & TRANSPORT_LOCK_READ)
DBG("Transport %s: read lock acquired", transport->path);
- }
- if (write_lock) {
- transport->write_lock = write_lock;
+ if (lock & TRANSPORT_LOCK_WRITE)
DBG("Transport %s: write lock acquired", transport->path);
- }
return TRUE;
@@ -616,16 +625,16 @@ static void media_transport_add(struct media_transport *transport,
static struct media_owner *media_owner_create(DBusConnection *conn,
DBusMessage *msg,
- const char *accesstype)
+ transport_lock_t lock)
{
struct media_owner *owner;
owner = g_new0(struct media_owner, 1);
owner->name = g_strdup(dbus_message_get_sender(msg));
- owner->accesstype = g_strdup(accesstype);
+ owner->lock = lock;
DBG("Owner created: sender=%s accesstype=%s", owner->name,
- accesstype);
+ lock2str(lock));
return owner;
}
@@ -662,6 +671,7 @@ static DBusMessage *acquire(DBusConnection *conn, DBusMessage *msg,
struct media_owner *owner;
struct media_request *req;
const char *accesstype, *sender;
+ transport_lock_t lock;
guint id;
if (!dbus_message_get_args(msg, NULL,
@@ -675,13 +685,17 @@ static DBusMessage *acquire(DBusConnection *conn, DBusMessage *msg,
if (owner != NULL)
return btd_error_not_authorized(msg);
- if (media_transport_acquire(transport, accesstype) == FALSE)
+ lock = str2lock(accesstype);
+ if (lock == 0)
+ return btd_error_invalid_args(msg);
+
+ if (media_transport_acquire(transport, lock) == FALSE)
return btd_error_not_authorized(msg);
- owner = media_owner_create(conn, msg, accesstype);
+ owner = media_owner_create(conn, msg, lock);
id = transport->resume(transport, owner);
if (id == 0) {
- media_transport_release(transport, accesstype);
+ media_transport_release(transport, lock);
media_owner_free(owner);
return btd_error_not_authorized(msg);
}
@@ -699,6 +713,7 @@ static DBusMessage *release(DBusConnection *conn, DBusMessage *msg,
struct media_transport *transport = data;
struct media_owner *owner;
const char *accesstype, *sender;
+ transport_lock_t lock;
struct media_request *req;
if (!dbus_message_get_args(msg, NULL,
@@ -712,7 +727,9 @@ static DBusMessage *release(DBusConnection *conn, DBusMessage *msg,
if (owner == NULL)
return btd_error_not_authorized(msg);
- if (g_strcmp0(owner->accesstype, accesstype) == 0) {
+ lock = str2lock(accesstype);
+
+ if (owner->lock == lock) {
guint id;
/* Not the last owner, no need to suspend */
@@ -742,9 +759,9 @@ static DBusMessage *release(DBusConnection *conn, DBusMessage *msg,
media_owner_add(owner, req);
return NULL;
- } else if (g_strstr_len(owner->accesstype, -1, accesstype) != NULL) {
- media_transport_release(transport, accesstype);
- g_strdelimit(owner->accesstype, accesstype, ' ');
+ } else if ((owner->lock & lock) == lock) {
+ media_transport_release(transport, lock);
+ owner->lock &= ~lock;
} else
return btd_error_not_authorized(msg);
--
1.7.7.6
next prev parent reply other threads:[~2012-09-14 12:03 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-09-14 12:03 [RFC v4 0/9] Optional acquire in Media API and related Mikel Astiz
2012-09-14 12:03 ` Mikel Astiz [this message]
2012-09-14 12:03 ` [RFC v4 2/9] media: Add a2dp_sep_is_playing() to internal API Mikel Astiz
2012-09-14 12:03 ` [RFC v4 3/9] media: Add gateway_get_state() " Mikel Astiz
2012-09-14 12:03 ` [RFC v4 4/9] media: Replace transport->in_use flag with state Mikel Astiz
2012-09-14 12:03 ` [RFC v4 5/9] media: Watch interface state changes in transport Mikel Astiz
2012-09-14 12:03 ` [RFC v4 6/9] media: Split transport state based on playing flag Mikel Astiz
2012-09-14 12:03 ` [RFC v4 7/9] media: Expose transport state in D-Bus Mikel Astiz
2012-09-14 12:03 ` [RFC v4 8/9] media: Automatically release transport when HUP Mikel Astiz
2012-09-14 12:03 ` [RFC v4 9/9] media: Extend media API with optional acquire Mikel Astiz
2012-09-14 12:16 ` [RFC v4 0/9] Optional acquire in Media API and related Maxim Levitsky
2012-09-14 12:40 ` Mikel Astiz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1347624196-11281-2-git-send-email-mikel.astiz.oss@gmail.com \
--to=mikel.astiz.oss@gmail.com \
--cc=linux-bluetooth@vger.kernel.org \
--cc=mikel.astiz@bmw-carit.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox