diff options
-rw-r--r-- | attrib/client.c | 15 | ||||
-rw-r--r-- | attrib/gattrib.c | 27 | ||||
-rw-r--r-- | src/attrib-server.c | 11 |
3 files changed, 29 insertions, 24 deletions
diff --git a/attrib/client.c b/attrib/client.c index d695e235..a3c01a11 100644 --- a/attrib/client.c +++ b/attrib/client.c @@ -316,12 +316,19 @@ static void events_handler(const uint8_t *pdu, uint16_t len, static void primary_cb(guint8 status, const guint8 *pdu, guint16 plen, gpointer user_data); +static void attrib_destroy(gpointer user_data) +{ + struct gatt_service *gatt = user_data; + + gatt->attrib = NULL; +} + static void attrib_disconnect(gpointer user_data) { struct gatt_service *gatt = user_data; + /* Remote initiated disconnection only */ g_attrib_unref(gatt->attrib); - gatt->attrib = NULL; } static void connect_cb(GIOChannel *chan, GError *gerr, gpointer user_data) @@ -452,9 +459,8 @@ static DBusMessage *register_watcher(DBusConnection *conn, g_io_channel_unref(io); gatt->listen = TRUE; - if (prim->watchers == NULL) - g_attrib_set_disconnect_function(gatt->attrib, - attrib_disconnect, gatt); + g_attrib_set_destroy_function(gatt->attrib, attrib_destroy, gatt); + g_attrib_set_disconnect_function(gatt->attrib, attrib_disconnect, gatt); done: watcher = g_new0(struct watcher, 1); @@ -1260,6 +1266,7 @@ int attrib_client_register(bdaddr_t *sba, bdaddr_t *dba, const char *path, gatt->attrib = g_attrib_new(io); g_io_channel_unref(io); + g_attrib_set_destroy_function(gatt->attrib, attrib_destroy, gatt); g_attrib_set_disconnect_function(gatt->attrib, attrib_disconnect, gatt); diff --git a/attrib/gattrib.c b/attrib/gattrib.c index bcab5cc0..ed181683 100644 --- a/attrib/gattrib.c +++ b/attrib/gattrib.c @@ -175,6 +175,7 @@ void g_attrib_unref(GAttrib *attrib) while ((c = g_queue_pop_head(attrib->queue))) command_destroy(c); + attrib->queue = NULL; for (l = attrib->events; l; l = l->next) @@ -186,10 +187,11 @@ void g_attrib_unref(GAttrib *attrib) if (attrib->write_watch > 0) g_source_remove(attrib->write_watch); - if (attrib->read_watch > 0) + if (attrib->read_watch > 0) { g_source_remove(attrib->read_watch); + g_io_channel_unref(attrib->io); + } - g_io_channel_unref(attrib->io); if (attrib->destroy) attrib->destroy(attrib->destroy_user_data); @@ -221,16 +223,6 @@ gboolean g_attrib_set_destroy_function(GAttrib *attrib, return TRUE; } -static void destroy_receiver(gpointer data) -{ - struct _GAttrib *attrib = data; - - attrib->read_watch = 0; - - if (attrib->disconnect) - attrib->disconnect(attrib->disc_user_data); -} - static gboolean can_write_data(GIOChannel *io, GIOCondition cond, gpointer data) { @@ -294,8 +286,12 @@ static gboolean received_data(GIOChannel *io, GIOCondition cond, gpointer data) gsize len; GIOStatus iostat; - if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) + if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) { + attrib->read_watch = 0; + if (attrib->disconnect) + attrib->disconnect(attrib->disc_user_data); return FALSE; + } memset(buf, 0, sizeof(buf)); @@ -363,10 +359,9 @@ GAttrib *g_attrib_new(GIOChannel *io) attrib->mtu = 512; attrib->queue = g_queue_new(); - attrib->read_watch = g_io_add_watch_full(attrib->io, - G_PRIORITY_DEFAULT, + attrib->read_watch = g_io_add_watch(attrib->io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, - received_data, attrib, destroy_receiver); + received_data, attrib); return g_attrib_ref(attrib); } diff --git a/src/attrib-server.c b/src/attrib-server.c index 871e7e5e..35a7d1aa 100644 --- a/src/attrib-server.c +++ b/src/attrib-server.c @@ -420,10 +420,11 @@ static uint16_t mtu_exchange(struct gatt_channel *channel, uint16_t mtu, return enc_mtu_resp(channel->mtu, pdu, len); } -static void channel_destroy(void *user_data) +static void channel_disconnect(void *user_data) { struct gatt_channel *channel = user_data; + g_attrib_unref(channel->attrib); clients = g_slist_remove(clients, channel); g_free(channel); @@ -537,7 +538,8 @@ static void connect_event(GIOChannel *io, GError *err, void *user_data) channel->id = g_attrib_register(channel->attrib, GATTRIB_ALL_EVENTS, channel_handler, channel, NULL); - g_attrib_set_disconnect_function(channel->attrib, channel_destroy, + + g_attrib_set_disconnect_function(channel->attrib, channel_disconnect, channel); clients = g_slist_append(clients, channel); @@ -654,12 +656,13 @@ void attrib_server_exit(void) struct gatt_channel *channel = l->data; g_source_remove(channel->id); + g_attrib_unref(channel->attrib); } + g_slist_free(clients); + if (handle) remove_record_from_server(handle); - - g_slist_free(clients); } int attrib_db_add(uint16_t handle, uuid_t *uuid, const uint8_t *value, int len) |