From patchwork Thu Jul 16 23:18:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 11668557 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3C4981751 for ; Thu, 16 Jul 2020 23:19:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1EAFD20739 for ; Thu, 16 Jul 2020 23:19:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="tlWeZyYh" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726984AbgGPXTG (ORCPT ); Thu, 16 Jul 2020 19:19:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45032 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726189AbgGPXTD (ORCPT ); Thu, 16 Jul 2020 19:19:03 -0400 Received: from mail-pj1-x1044.google.com (mail-pj1-x1044.google.com [IPv6:2607:f8b0:4864:20::1044]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BAE64C061755 for ; Thu, 16 Jul 2020 16:18:59 -0700 (PDT) Received: by mail-pj1-x1044.google.com with SMTP id gc15so3446068pjb.0 for ; Thu, 16 Jul 2020 16:18:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=CX74muhyV/pRHgal4c+5eAgaYcu9OhB2bqVlNBbpWPY=; b=tlWeZyYhdvELQRbBK2wYeh7v+/nzkmqiwAHHOdyaLkUS37fs0dgjxxcbJpTNI58iAi Qm1X21B1Agd53gndQSjM6T8dzuXT/kpLLGeGFVZxDQHn8yCQMWbhEGR3aFxt43BI5KHE ff+pYUKIW+00a80+W3A3jWpXMYPzNs/h8SxRbecftE8r/yTUSZgqAdJAW5bBVjwQCG0b g95Ae7W59/GjCO8+dhKw4EkYDeDdftNF/dwjfnw/ntm86aO9eHL3X6GUFDup1V4JrrJE 25e6X3DkgPmzewURI7x7UDneUkXDij1hxFvAlsTILd/fv6PyKDgFA4KGjbaU/Xh1ncwR IJPQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=CX74muhyV/pRHgal4c+5eAgaYcu9OhB2bqVlNBbpWPY=; b=D3hpvgSfaxm90rSvEEZSiGb4iQmXL9kSZfZdt0kV2zR/vUuhBNMOX7LihCUoSNlf0e 9E7ODOCdvvH7Dst/U4N4B/dXtg5mw0SeTo2o/uMzfesaOED/wxu+h/H8yapkb/PiGfuf tV57IwOPeIR5PPcYVEUC5ddDYqrMqhFRXYS6Z+vxfnD6tqDi0cVsAvWh5Eif/YEJHBf5 mGqDCa38faeCpx+pUOJs6n1DxxREVA/faOSit5Jwk9jWafcD3RgaqasQfygaK5tgplVD Usk9cGIGjw4ko+FFHVGX/LjxX/M8El5fkuF4Tt/3W71UW+ZEsc4/xZRrA2WCs/1E3dSW D9+Q== X-Gm-Message-State: AOAM530v7ZHa7FF0PwZbtRlKNmmr38BYFbqPpZvfKmi4l8Rfg9IyzSu2 XYXeqiU0R67yLDOUp2E0Q4OJbIZkYKY= X-Google-Smtp-Source: ABdhPJxzCyao9FEV6ADUuVRH1cVu6hwwZhNukvJxA8Vnwb+9UtCL3xwz7ww8x7vTkRYsl8MJUze9eQ== X-Received: by 2002:a17:90a:d304:: with SMTP id p4mr7482109pju.153.1594941538736; Thu, 16 Jul 2020 16:18:58 -0700 (PDT) Received: from localhost.localdomain (c-71-56-157-77.hsd1.or.comcast.net. [71.56.157.77]) by smtp.gmail.com with ESMTPSA id a2sm6024530pgf.53.2020.07.16.16.18.57 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 Jul 2020 16:18:58 -0700 (PDT) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH BlueZ 1/4] shared/att: Fix possible crash on disconnect Date: Thu, 16 Jul 2020 16:18:54 -0700 Message-Id: <20200716231857.934396-1-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.25.3 MIME-Version: 1.0 Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz If there are pending request while disconnecting they would be notified but clients may endup being freed in the proccess which will then be calling bt_att_cancel to cancal its requests causing the following trace: Invalid read of size 4 at 0x1D894C: enable_ccc_callback (gatt-client.c:1627) by 0x1D247B: disc_att_send_op (att.c:417) by 0x1CCC17: queue_remove_all (queue.c:354) by 0x1D47B7: disconnect_cb (att.c:635) by 0x1E0707: watch_callback (io-glib.c:170) by 0x48E963B: g_main_context_dispatch (in /usr/lib/libglib-2.0.so.0.6400.4) by 0x48E9AC7: ??? (in /usr/lib/libglib-2.0.so.0.6400.4) by 0x48E9ECF: g_main_loop_run (in /usr/lib/libglib-2.0.so.0.6400.4) by 0x1E0E97: mainloop_run (mainloop-glib.c:79) by 0x1E13B3: mainloop_run_with_signal (mainloop-notify.c:201) by 0x12BC3B: main (main.c:770) Address 0x7d40a28 is 24 bytes inside a block of size 32 free'd at 0x484A2E0: free (vg_replace_malloc.c:540) by 0x1CCC17: queue_remove_all (queue.c:354) by 0x1CCC83: queue_destroy (queue.c:73) by 0x1D7DD7: bt_gatt_client_free (gatt-client.c:2209) by 0x16497B: batt_free (battery.c:77) by 0x16497B: batt_remove (battery.c:286) by 0x1A0013: service_remove (service.c:176) by 0x1A9B7B: device_remove_gatt_service (device.c:3691) by 0x1A9B7B: gatt_service_removed (device.c:3805) by 0x1CC90B: queue_foreach (queue.c:220) by 0x1DE27B: notify_service_changed.isra.0.part.0 (gatt-db.c:369) by 0x1DE387: notify_service_changed (gatt-db.c:361) by 0x1DE387: gatt_db_service_destroy (gatt-db.c:385) by 0x1DE3EF: gatt_db_remove_service (gatt-db.c:519) by 0x1D674F: discovery_op_complete (gatt-client.c:388) by 0x1D6877: discover_primary_cb (gatt-client.c:1260) by 0x1E220B: discovery_op_complete (gatt-helpers.c:628) by 0x1E249B: read_by_grp_type_cb (gatt-helpers.c:730) by 0x1D247B: disc_att_send_op (att.c:417) by 0x1CCC17: queue_remove_all (queue.c:354) by 0x1D47B7: disconnect_cb (att.c:635) --- src/shared/att.c | 46 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/src/shared/att.c b/src/shared/att.c index ed3af2920..58f23dfcb 100644 --- a/src/shared/att.c +++ b/src/shared/att.c @@ -84,6 +84,7 @@ struct bt_att { struct queue *req_queue; /* Queued ATT protocol requests */ struct queue *ind_queue; /* Queued ATT protocol indications */ struct queue *write_queue; /* Queue of PDUs ready to send */ + bool in_disc; /* Cleanup queues on disconnect_cb */ bt_att_timeout_func_t timeout_callback; bt_att_destroy_func_t timeout_destroy; @@ -222,8 +223,10 @@ static void destroy_att_send_op(void *data) free(op); } -static void cancel_att_send_op(struct att_send_op *op) +static void cancel_att_send_op(void *data) { + struct att_send_op *op = data; + if (op->destroy) op->destroy(op->user_data); @@ -631,11 +634,6 @@ static bool disconnect_cb(struct io *io, void *user_data) /* Dettach channel */ queue_remove(att->chans, chan); - /* Notify request callbacks */ - queue_remove_all(att->req_queue, NULL, NULL, disc_att_send_op); - queue_remove_all(att->ind_queue, NULL, NULL, disc_att_send_op); - queue_remove_all(att->write_queue, NULL, NULL, disc_att_send_op); - if (chan->pending_req) { disc_att_send_op(chan->pending_req); chan->pending_req = NULL; @@ -654,6 +652,15 @@ static bool disconnect_cb(struct io *io, void *user_data) bt_att_ref(att); + att->in_disc = true; + + /* Notify request callbacks */ + queue_remove_all(att->req_queue, NULL, NULL, disc_att_send_op); + queue_remove_all(att->ind_queue, NULL, NULL, disc_att_send_op); + queue_remove_all(att->write_queue, NULL, NULL, disc_att_send_op); + + att->in_disc = false; + queue_foreach(att->disconn_list, disconn_handler, INT_TO_PTR(err)); bt_att_unregister_all(att); @@ -1574,6 +1581,30 @@ bool bt_att_chan_cancel(struct bt_att_chan *chan, unsigned int id) return true; } +static bool bt_att_disc_cancel(struct bt_att *att, unsigned int id) +{ + struct att_send_op *op; + + op = queue_find(att->req_queue, match_op_id, UINT_TO_PTR(id)); + if (op) + goto done; + + op = queue_find(att->ind_queue, match_op_id, UINT_TO_PTR(id)); + if (op) + goto done; + + op = queue_find(att->write_queue, match_op_id, UINT_TO_PTR(id)); + +done: + if (!op) + return false; + + /* Just cancel since disconnect_cb will be cleaning up */ + cancel_att_send_op(op); + + return true; +} + bool bt_att_cancel(struct bt_att *att, unsigned int id) { const struct queue_entry *entry; @@ -1591,6 +1622,9 @@ bool bt_att_cancel(struct bt_att *att, unsigned int id) return true; } + if (att->in_disc) + return bt_att_disc_cancel(att, id); + op = queue_remove_if(att->req_queue, match_op_id, UINT_TO_PTR(id)); if (op) goto done; From patchwork Thu Jul 16 23:18:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 11668555 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DB7A3618 for ; Thu, 16 Jul 2020 23:19:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C03872074B for ; Thu, 16 Jul 2020 23:19:06 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hOGI+TPs" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726977AbgGPXTF (ORCPT ); Thu, 16 Jul 2020 19:19:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45048 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726828AbgGPXTD (ORCPT ); Thu, 16 Jul 2020 19:19:03 -0400 Received: from mail-pj1-x1044.google.com (mail-pj1-x1044.google.com [IPv6:2607:f8b0:4864:20::1044]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3FC1FC08C5C0 for ; Thu, 16 Jul 2020 16:19:00 -0700 (PDT) Received: by mail-pj1-x1044.google.com with SMTP id b92so5441967pjc.4 for ; Thu, 16 Jul 2020 16:19:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=8usU1d9z6P0on7EH8VOSZKPN/Qf36pOKKeX7ZcAp564=; b=hOGI+TPsl3RU1UI4/IxdpjCKs1mdb22uSRHSLUxuJZoIjCdnAPiRhJUxcgqjK5oFPI kKqepTqY6QzQ1AEike/tEhONqEJp1nO18sblgWfqfnHIh/HEcCDUBzAgSAdETRpSO7h2 sQ4wNZwp18PD0X0iCiQlJMLnScdEQheJD23T4CZpDqH2zCvCHUU/9TIcDGOQzL0SHf40 HTKs4zWgF+xi7GmPFwPJZtUrmz2kRSoz4uTM36vZQptfts9mVoeGt7/mX5JO/i4u3lRx bwQsz/qGHMMDcm9RMNYIfLeHbT1eHGB4kMmef6kevYR23FwHe1Rw80YxlXva7NULrnum nV0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=8usU1d9z6P0on7EH8VOSZKPN/Qf36pOKKeX7ZcAp564=; b=lV7kHfT2jssaWAQ7PR8NEOgUWLf++vqs1z4EE0dzaxOKViZu9zyTv11EacoVBwloM2 QkKk1h9GOlcdYBk9sqHyL1ryvOZW+EcdObwkFqspmO4k+QUgEu87jDATykSvSWXHWG3I 8YGNSGc8FXqXta3U1rMarqp9M9H30LU2C8ORzPZrC/zdigQwZt3oJX3E5vHtESN4bKwp pbzT0YxkpkKOD2JJ0/V66Dz68zcSKNBB7EdYrE5JLGwUdjJtSL4nIuCsoNOaIKcrscys ePfjIkK42MJsXq1fkqxeRzooE8fJS1uZX241oXDFkjOtUPJt2IotQaqYr+vE0AUdJX2J Tb6w== X-Gm-Message-State: AOAM531nWSLFVwb4i+kAJb59h56kRS13qMn3lvijl2dbaBRObfRxhrK0 9m8mKdlWtl5TDpQgGpK1gPaQHvn4y6s= X-Google-Smtp-Source: ABdhPJzYMPNoNHP9RTwTd2WT7XKzMeeZ58JmGjSk4IOsBjF0xjj9MPmI80sZbmxR/kk0QlhZ/O2vUA== X-Received: by 2002:a17:90b:3010:: with SMTP id hg16mr7268925pjb.69.1594941539458; Thu, 16 Jul 2020 16:18:59 -0700 (PDT) Received: from localhost.localdomain (c-71-56-157-77.hsd1.or.comcast.net. [71.56.157.77]) by smtp.gmail.com with ESMTPSA id a2sm6024530pgf.53.2020.07.16.16.18.58 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 Jul 2020 16:18:59 -0700 (PDT) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH BlueZ 2/4] shared/gatt-db: Add support for notifying attribute changes Date: Thu, 16 Jul 2020 16:18:55 -0700 Message-Id: <20200716231857.934396-2-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.25.3 In-Reply-To: <20200716231857.934396-1-luiz.dentz@gmail.com> References: <20200716231857.934396-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This enables to get notified when an attribute has been changed e.g. it is being removed so the code can detect changes changes at attribute level. --- src/shared/gatt-db.c | 103 +++++++++++++++++++++++++++++++++++++++++++ src/shared/gatt-db.h | 8 ++++ 2 files changed, 111 insertions(+) diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c index 5eccab3b9..e939ddc3a 100644 --- a/src/shared/gatt-db.c +++ b/src/shared/gatt-db.c @@ -81,6 +81,13 @@ struct notify { void *user_data; }; +struct attribute_notify { + unsigned int id; + gatt_db_attribute_cb_t removed; + gatt_db_destroy_func_t destroy; + void *user_data; +}; + struct pending_read { struct gatt_db_attribute *attrib; unsigned int id; @@ -114,6 +121,9 @@ struct gatt_db_attribute { unsigned int write_id; struct queue *pending_writes; + + unsigned int next_notify_id; + struct queue *notify_list; }; struct gatt_db_service { @@ -171,6 +181,16 @@ static void pending_write_free(void *data) pending_write_result(p, -ECANCELED); } +static void attribute_notify_destroy(void *data) +{ + struct attribute_notify *notify = data; + + if (notify->destroy) + notify->destroy(notify->user_data); + + free(notify); +} + static void attribute_destroy(struct gatt_db_attribute *attribute) { /* Attribute was not initialized by user */ @@ -179,6 +199,7 @@ static void attribute_destroy(struct gatt_db_attribute *attribute) queue_destroy(attribute->pending_reads, pending_read_free); queue_destroy(attribute->pending_writes, pending_write_free); + queue_destroy(attribute->notify_list, attribute_notify_destroy); free(attribute->value); free(attribute); @@ -208,6 +229,7 @@ static struct gatt_db_attribute *new_attribute(struct gatt_db_service *service, attribute->pending_reads = queue_new(); attribute->pending_writes = queue_new(); + attribute->notify_list = queue_new(); return attribute; @@ -352,12 +374,38 @@ static bool db_hash_update(void *user_data) return false; } +static void handle_attribute_notify(void *data, void *user_data) +{ + struct attribute_notify *notify = data; + struct gatt_db_attribute *attrib = user_data; + + if (notify->removed) + notify->removed(attrib, notify->user_data); +} + +static void notify_attribute_changed(struct gatt_db_service *service) +{ + int i; + + for (i = 0; i < service->num_handles; i++) { + struct gatt_db_attribute *attr = service->attributes[i]; + + if (!attr) + continue; + + queue_foreach(attr->notify_list, handle_attribute_notify, attr); + } +} + static void notify_service_changed(struct gatt_db *db, struct gatt_db_service *service, bool added) { struct notify_data data; + if (!added) + notify_attribute_changed(service); + if (queue_isempty(db->notify_list)) return; @@ -1993,3 +2041,58 @@ void *gatt_db_attribute_get_user_data(struct gatt_db_attribute *attrib) return attrib->user_data; } + +static bool match_attribute_notify_id(const void *a, const void *b) +{ + const struct attribute_notify *notify = a; + unsigned int id = PTR_TO_UINT(b); + + return notify->id == id; +} + +unsigned int gatt_db_attribute_register(struct gatt_db_attribute *attrib, + gatt_db_attribute_cb_t removed, + void *user_data, + gatt_db_destroy_func_t destroy) +{ + struct attribute_notify *notify; + + if (!attrib || !removed) + return 0; + + notify = new0(struct attribute_notify, 1); + notify->removed = removed; + notify->destroy = destroy; + notify->user_data = user_data; + + if (attrib->next_notify_id < 1) + attrib->next_notify_id = 1; + + notify->id = attrib->next_notify_id++; + + if (!queue_push_tail(attrib->notify_list, notify)) { + free(notify); + return 0; + } + + return notify->id; +} + +bool gatt_db_attribute_unregister(struct gatt_db_attribute *attrib, + unsigned int id) +{ + struct attribute_notify *notify; + + if (!attrib || !id) + return false; + + notify = queue_find(attrib->notify_list, match_attribute_notify_id, + UINT_TO_PTR(id)); + if (!notify) + return false; + + queue_remove(attrib->notify_list, notify); + attribute_notify_destroy(notify); + + return true; +} diff --git a/src/shared/gatt-db.h b/src/shared/gatt-db.h index a0fd66c53..5bf19d302 100644 --- a/src/shared/gatt-db.h +++ b/src/shared/gatt-db.h @@ -281,3 +281,11 @@ bool gatt_db_attribute_write_result(struct gatt_db_attribute *attrib, bool gatt_db_attribute_reset(struct gatt_db_attribute *attrib); void *gatt_db_attribute_get_user_data(struct gatt_db_attribute *attrib); + +unsigned int gatt_db_attribute_register(struct gatt_db_attribute *attrib, + gatt_db_attribute_cb_t removed, + void *user_data, + gatt_db_destroy_func_t destroy); + +bool gatt_db_attribute_unregister(struct gatt_db_attribute *attrib, + unsigned int id); From patchwork Thu Jul 16 23:18:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 11668559 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BED6E618 for ; Thu, 16 Jul 2020 23:19:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A4583208C9 for ; Thu, 16 Jul 2020 23:19:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="tUC56eiC" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727025AbgGPXTH (ORCPT ); Thu, 16 Jul 2020 19:19:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45088 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726846AbgGPXTD (ORCPT ); Thu, 16 Jul 2020 19:19:03 -0400 Received: from mail-pj1-x1031.google.com (mail-pj1-x1031.google.com [IPv6:2607:f8b0:4864:20::1031]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C3051C08C5CE for ; Thu, 16 Jul 2020 16:19:01 -0700 (PDT) Received: by mail-pj1-x1031.google.com with SMTP id mn17so5591576pjb.4 for ; Thu, 16 Jul 2020 16:19:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=HeZXwV8yLxbY3gUDwoAQlT9mAbB9u1/YqIhjlLCDDdI=; b=tUC56eiCD/aT0BlQDJwZ0AhSw+h5q5mTFpWNTIz9Rf8uY8xLQrMi/4B+z4F5nH097Q jStadvqIXBzoJH+0W/ngYmuAgVaRYZqYpTb9m2MwMTz5MUW8iyUFCVaAWSGz8KoN7Rep D1uJmI/WqsIvhEQrT2Qv3sYDgZWEwYC5gWAQTRUYGKbYDshj9p2ui+evxytb4pMgZR6Z V84I61+sSEw676t63oUPsOWZAmHNuJg3ZF9YcBMu9AXi6yw2Dn+7xV3u/PWYuEsbjXX0 aAUgZvYe9Fv3jfU4x3j5coVMk2mmPDHJCUZPw6oM5dMeKLspjNJyI/FqRWQnDUjmy5mA ZDcQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=HeZXwV8yLxbY3gUDwoAQlT9mAbB9u1/YqIhjlLCDDdI=; b=AUgnYFJ8ndK5z7pN9Y2qMhXTCCBSHpQXmTbL9bObx7BELl8ur51R8nTgQpmSP3NoTJ tOBPwQduR1l+/41fU/VYry0TCKcM+muBP5QjgXdAS1TJ2YxGG36tZqiSZ/88kjhc3esx /czAEjokQ+8mvkhInYSLE2Zi9Sm96gYp2FbV8Xr157rinprtc9BHjjXO+2/7x5eJCgVE AxlRbsqEnQSY0iYLjtMHANU2PzvEemkCbIPoSicx72q7JV4xPQqAbHW/ymFUlkeTUEqS D1pt1VJ/7G48VPhArIp1j1Tww+yziUkbOqiODIhchLoK6qJh+iwJ/W8MrSmmGfxwWd9p Q2rw== X-Gm-Message-State: AOAM533Wwy4EaCeUMco4e+YqSka6Ygl68rUTd0JsJdEvvtnG/Dykdsyt EYHNSLsO9csi4EM/8C/0xYH813KkDjI= X-Google-Smtp-Source: ABdhPJxkbMksebSnHK9DUdx7VczpcMEC+0UCKkIwmvynQN+3D7NfvEoUESbKWfFnTZJIGogSHHpt1A== X-Received: by 2002:a17:902:40a:: with SMTP id 10mr5429639ple.180.1594941540986; Thu, 16 Jul 2020 16:19:00 -0700 (PDT) Received: from localhost.localdomain (c-71-56-157-77.hsd1.or.comcast.net. [71.56.157.77]) by smtp.gmail.com with ESMTPSA id a2sm6024530pgf.53.2020.07.16.16.18.59 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 Jul 2020 16:19:00 -0700 (PDT) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH BlueZ 3/4] shared/gatt-client: Remove notification if its attribute is removed Date: Thu, 16 Jul 2020 16:18:56 -0700 Message-Id: <20200716231857.934396-3-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.25.3 In-Reply-To: <20200716231857.934396-1-luiz.dentz@gmail.com> References: <20200716231857.934396-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Sender: linux-bluetooth-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz If the attribute is being removed from the database it means the notification shall also be dropped, that way users don't have to cleanup its subscriptions themselves. --- src/shared/gatt-client.c | 70 +++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 18 deletions(-) diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c index 0b81a7a5c..e21aca1f0 100644 --- a/src/shared/gatt-client.c +++ b/src/shared/gatt-client.c @@ -174,9 +174,12 @@ static void request_unref(void *data) } struct notify_chrc { + struct bt_gatt_client *client; + struct gatt_db_attribute *attr; uint16_t value_handle; uint16_t ccc_handle; uint16_t properties; + unsigned int notify_id; int notify_count; /* Reference count of registered notify callbacks */ /* Pending calls to register_notify are queued here so that they can be @@ -235,6 +238,51 @@ static void find_ccc(struct gatt_db_attribute *attr, void *user_data) *ccc_ptr = attr; } +static bool match_notify_chrc(const void *data, const void *user_data) +{ + const struct notify_data *notify_data = data; + const struct notify_chrc *chrc = user_data; + + return notify_data->chrc == chrc; +} + +static void notify_data_cleanup(void *data) +{ + struct notify_data *notify_data = data; + + if (notify_data->att_id) + bt_att_cancel(notify_data->client->att, notify_data->att_id); + + notify_data_unref(notify_data); +} + +static void notify_chrc_free(void *data) +{ + struct notify_chrc *chrc = data; + + if (chrc->notify_id) + gatt_db_attribute_unregister(chrc->attr, chrc->notify_id); + + queue_destroy(chrc->reg_notify_queue, notify_data_unref); + free(chrc); +} + +static void chrc_removed(struct gatt_db_attribute *attr, void *user_data) +{ + struct notify_chrc *chrc = user_data; + struct bt_gatt_client *client = chrc->client; + struct notify_data *data; + + chrc->notify_id = 0; + + while ((data = queue_remove_if(client->notify_list, match_notify_chrc, + chrc))) + notify_data_cleanup(data); + + queue_remove(client->notify_chrcs, chrc); + notify_chrc_free(chrc); +} + static struct notify_chrc *notify_chrc_create(struct bt_gatt_client *client, uint16_t value_handle) { @@ -274,22 +322,18 @@ static struct notify_chrc *notify_chrc_create(struct bt_gatt_client *client, if (ccc) chrc->ccc_handle = gatt_db_attribute_get_handle(ccc); + chrc->client = client; + chrc->attr = attr; chrc->value_handle = value_handle; chrc->properties = properties; + chrc->notify_id = gatt_db_attribute_register(attr, chrc_removed, chrc, + NULL); queue_push_tail(client->notify_chrcs, chrc); return chrc; } -static void notify_chrc_free(void *data) -{ - struct notify_chrc *chrc = data; - - queue_destroy(chrc->reg_notify_queue, notify_data_unref); - free(chrc); -} - static bool match_notify_data_id(const void *a, const void *b) { const struct notify_data *notify_data = a; @@ -303,16 +347,6 @@ struct handle_range { uint16_t end; }; -static void notify_data_cleanup(void *data) -{ - struct notify_data *notify_data = data; - - if (notify_data->att_id) - bt_att_cancel(notify_data->client->att, notify_data->att_id); - - notify_data_unref(notify_data); -} - struct discovery_op; typedef void (*discovery_op_complete_func_t)(struct discovery_op *op,