aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClaudio Takahasi <claudio.takahasi@openbossa.org>2010-09-17 17:26:57 -0300
committerAnderson Lizardo <anderson.lizardo@openbossa.org>2010-09-22 15:55:18 -0400
commitd0bfd6eaa586b86bc1b191de0cb9c12e331a22fa (patch)
treedaab00a2bb17cad213050cd7de6ddcaa32e130e9
parent8545bdc1eae7c4e4a6ef90c74b3e6c070e3bbe9c (diff)
downloadbluez-d0bfd6eaa586b86bc1b191de0cb9c12e331a22fa.tar.gz
bluez-d0bfd6eaa586b86bc1b191de0cb9c12e331a22fa.tar.xz
bluez-d0bfd6eaa586b86bc1b191de0cb9c12e331a22fa.zip
Use the destroy function to reset the GAttrib reference
In the client, after local or remote initiated disconnection the GAttrib reference shall be set to NULL to allow a proper control of references and further connections.
-rw-r--r--attrib/client.c15
-rw-r--r--attrib/gattrib.c27
-rw-r--r--src/attrib-server.c11
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)