[RFC v4 1/9] media: Fix accesstype comparison

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Mikel Astiz <mikel.astiz@xxxxxxxxxxxx>

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

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux