audio/media: Destroy transport if SetConfiguration fails
authorMarijn Suijten <marijns95@gmail.com>
Mon, 26 Oct 2020 19:54:08 +0000 (20:54 +0100)
committerAyush Garg <ayush.garg@samsung.com>
Fri, 11 Mar 2022 13:38:33 +0000 (19:08 +0530)
set_configuration creates a transport before calling SetConfiguration on
the MediaEndpoint1 DBus interface.  If this DBus call fails the
transport sticks around while it should instead be cleaned up.

When the peer retries or reconnects (in case of BlueZ which cuts the
connection due to a missing recount [1]) set_configuration finds this
old transport and returns FALSE.  The peer will never succeed this call
unless it randomly decides to call clear_configuration or BlueZ is
restarted.

[1]: https://marc.info/?l=linux-bluetooth&m=160364326629847&w=2

Signed-off-by: Anuj Jain <anuj01.jain@samsung.com>
Signed-off-by: Ayush Garg <ayush.garg@samsung.com>
profiles/audio/media.c

index c644376..c39bc94 100644 (file)
@@ -90,6 +90,7 @@ struct media_adapter {
 
 struct endpoint_request {
        struct media_endpoint   *endpoint;
+       struct media_transport  *transport;
        DBusMessage             *msg;
        DBusPendingCall         *call;
        media_endpoint_cb_t     cb;
@@ -353,6 +354,15 @@ static void endpoint_reply(DBusPendingCall *call, void *user_data)
                        return;
                }
 
+               if (dbus_message_is_method_call(request->msg,
+                                       MEDIA_ENDPOINT_INTERFACE,
+                                       "SetConfiguration")) {
+                       if (request->transport == NULL)
+                               error("Expected to destroy transport");
+                       else
+                               media_transport_destroy(request->transport);
+               }
+
                dbus_error_free(&err);
                goto done;
        }
@@ -392,6 +402,7 @@ done:
 
 static gboolean media_endpoint_async_call(DBusMessage *msg,
                                        struct media_endpoint *endpoint,
+                                       struct media_transport *transport,
                                        media_endpoint_cb_t cb,
                                        void *user_data,
                                        GDestroyNotify destroy)
@@ -413,6 +424,7 @@ static gboolean media_endpoint_async_call(DBusMessage *msg,
                                                                        NULL);
 
        request->endpoint = endpoint;
+       request->transport = transport;
        request->msg = msg;
        request->cb = cb;
        request->destroy = destroy;
@@ -448,7 +460,8 @@ static gboolean select_configuration(struct media_endpoint *endpoint,
                                        &capabilities, length,
                                        DBUS_TYPE_INVALID);
 
-       return media_endpoint_async_call(msg, endpoint, cb, user_data, destroy);
+       return media_endpoint_async_call(msg, endpoint, NULL,
+                                               cb, user_data, destroy);
 }
 
 static int transport_device_cmp(gconstpointer data, gconstpointer user_data)
@@ -702,7 +715,8 @@ static gboolean set_configuration(struct media_endpoint *endpoint,
 
        g_dbus_get_properties(conn, path, "org.bluez.MediaTransport1", &iter);
 
-       return media_endpoint_async_call(msg, endpoint, cb, user_data, destroy);
+       return media_endpoint_async_call(msg, endpoint, transport,
+                                               cb, user_data, destroy);
 }
 
 static void release_endpoint(struct media_endpoint *endpoint)