diff options
author | Wim Taymans <wtaymans@redhat.com> | 2014-08-08 22:35:40 +0200 |
---|---|---|
committer | Wim Taymans <wtaymans@redhat.com> | 2014-08-08 22:35:40 +0200 |
commit | 792e0ee80f833c2f0b51d2dd875a2e6590a4914b (patch) | |
tree | 5c58446018fb537d88691f02c392e3212fc0464b /src | |
parent | 4c6007ce197ba7fc37dcd20e1fbd780b3cc4f2a8 (diff) |
When the owner of the SCO socket vanishes, close the socket and go IDLE
again.
Diffstat (limited to 'src')
-rw-r--r-- | src/hsd-headset.c | 55 | ||||
-rw-r--r-- | src/hsd-headset.h | 1 | ||||
-rw-r--r-- | src/hsd-profile.c | 15 |
3 files changed, 55 insertions, 16 deletions
diff --git a/src/hsd-headset.c b/src/hsd-headset.c index dcea642..1ed514d 100644 --- a/src/hsd-headset.c +++ b/src/hsd-headset.c @@ -110,6 +110,36 @@ headset_set_state (HsdHeadset *h, } } +static void +headset_do_disconnect (HsdHeadset *h) +{ + if (h->fd != -1) { + shutdown (h->fd, SHUT_RDWR); + close (h->fd); + h->fd = -1; + } + + if (h->owner) { + g_free (h->owner); + h->owner = NULL; + g_bus_unwatch_name (h->owner_watch); + h->owner_watch = 0; + } + headset_set_state (h, HSD_HEADSET_STATE_IDLE); +} + + +static void +headset_owner_vanished (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + HsdHeadset *h = user_data; + + g_warning ("SCO connection owner vanished"); + headset_do_disconnect (h); +} + static gboolean headset_connect_cb (GIOChannel *io, GIOCondition cond, gpointer user_data) { @@ -142,11 +172,7 @@ headset_connect_cb (GIOChannel *io, GIOCondition cond, gpointer user_data) connect_failed: { - close (h->fd); - h->fd = -1; - g_free (h->owner); - h->owner = NULL; - headset_set_state (h, HSD_HEADSET_STATE_IDLE); + headset_do_disconnect (h); g_dbus_method_invocation_return_dbus_error (invocation, HSD_HEADSET_INTERFACE ".Error.Failed", "failed to connect"); return FALSE; @@ -180,6 +206,7 @@ headset_connect (HsdHeadset *h, if (h->state != HSD_HEADSET_STATE_IDLE) goto not_idle; + src_addr = h->adapter_addr; dst_addr = h->device_addr; @@ -224,6 +251,13 @@ headset_connect (HsdHeadset *h, headset_set_state (h, HSD_HEADSET_STATE_PENDING); h->owner = g_strdup (sender); h->invocation = invocation; + /* we need to make sure the owner stays alive */ + h->owner_watch = g_bus_watch_name_on_connection (connection, + sender, + G_BUS_NAME_WATCHER_FLAGS_NONE, + NULL, + headset_owner_vanished, + h, NULL); io = g_io_channel_unix_new(h->fd); g_io_add_watch(io, G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL, @@ -282,14 +316,7 @@ headset_disconnect (HsdHeadset *h, if (h->owner != NULL && strcmp (h->owner, sender)) goto not_owner; - if (h->fd != -1) { - shutdown (h->fd, SHUT_RDWR); - close (h->fd); - } - h->fd = -1; - - h->owner = NULL; - headset_set_state (h, HSD_HEADSET_STATE_IDLE); + headset_do_disconnect (h); g_dbus_method_invocation_return_value (invocation, NULL); @@ -499,13 +526,13 @@ hsd_headset_free (HsdHeadset *headset) { GDBusConnection *conn = hsd_dbus_connection_get (); + headset_do_disconnect (headset); if (headset->id) g_dbus_connection_unregister_object (conn, headset->id); g_free (headset->device); g_free (headset->device_addr); g_free (headset->adapter); g_free (headset->adapter_addr); - g_free (headset->owner); g_io_channel_unref (headset->rfcomm); g_free (headset); } diff --git a/src/hsd-headset.h b/src/hsd-headset.h index cecc12d..ba7337a 100644 --- a/src/hsd-headset.h +++ b/src/hsd-headset.h @@ -37,6 +37,7 @@ struct _HsdHeadset { HsdHeadsetState state; gchar *owner; + guint owner_watch; gint fd; GDBusMethodInvocation *invocation; }; diff --git a/src/hsd-profile.c b/src/hsd-profile.c index 3625a46..d144dfe 100644 --- a/src/hsd-profile.c +++ b/src/hsd-profile.c @@ -22,6 +22,7 @@ #include "hsd.h" #include "hsd-headset.h" #include "hsd-profile.h" +#include "hsd-manager.h" typedef struct { HsdProfileId id; @@ -95,7 +96,9 @@ profile_new_connection (HsdProfile *p, if (headset == NULL) goto failure; - hsd_manager_add_headset (p->manager, headset); + hsd_manager_add_headset (p->manager, headset, &error); + if (error != NULL) + goto failure; g_dbus_method_invocation_return_value (invocation, NULL); @@ -125,7 +128,10 @@ profile_request_disconnection (HsdProfile *p, if (headset == NULL) goto unknown_headset; - hsd_manager_remove_headset (p->manager, headset); + hsd_manager_remove_headset (p->manager, headset, &error); + if (error != NULL) + goto failure; + hsd_headset_free (headset); g_dbus_method_invocation_return_value (invocation, NULL); @@ -137,6 +143,11 @@ unknown_headset: "org.freedesktop.Headset.Error.Rejected", "no such transport"); return; } +failure: + { + g_dbus_method_invocation_take_error (invocation, error); + return; + } } static void |