gatt: Fix failure of repeated AcquireNotify calls
authorRob Spanton <rob@adventurousmachines.com>
Tue, 9 Jul 2019 16:57:22 +0000 (17:57 +0100)
committerhimanshu <h.himanshu@samsung.com>
Tue, 11 Feb 2020 08:57:47 +0000 (14:27 +0530)
This patch fixes a problem that can be encountered if a DBUS client
performs the following steps:

 1) Calls AcquireNotify on a characteristic
 2) Closes the fd produced by AcquireNotify
 3) Immediately calls AcquireNotify again on the same characteristic
 4) Disconnects DBUS client (does not have to be immediately)
 5) Reconnects DBUS client and call AcquireNotify

If these steps are followed, then the third call to AcquireNotify
will often be responded to with an error message stating "Notify
acquired".  Furthermore, the second call to AcquireNotify will not be
provided with an fd.

It turns out that the following was happening:  Closing the fd causes
bluez to disable notifications on that characteristic by writing to
the CCC.  If the second call to AcquireNotify is made before that CCC
write has completed, then a new write to the CCC to re-enable
notifications is enqueued.  Once that first write has completed, the
second write is then taken from the queue and started in
`disable_ccc_callback()`.  Unfortunately `disable_ccc_callback()` was
not actually using the data from the queue, but was instead just
re-using the data that it had been passed (`notify_data` instead of
`next_data`).

This meant that the write to the CCC to enable notifications would
happen, but the callback that needed to be made to the code that was
waiting for the enqueued operation to complete would never happen.  In
this AcquireNotify case, the register_notify_io_cb() function would
not be called, resulting in no socket creation and no response to the
second AcquireNotify call.  Instead it would leave some state
hanging around on bluez's representation of the characteristic, and so
subsequent calls to AcquireNotify by any DBUS client would fail with
the aforementioned error.

The fix is simple here -- make `disable_ccc_callback()` pass the
correct data through.

Change-Id: Ia49678498d713b2285c06ed01b72a6c0e1a6fe35
Signed-off-by: himanshu <h.himanshu@samsung.com>
src/shared/gatt-client.c

index ab3cf94..94bd7e2 100644 (file)
@@ -2163,7 +2163,7 @@ static void disable_ccc_callback(uint8_t opcode, const void *pdu,
         */
        while (1) {
                next_data = queue_pop_head(notify_data->chrc->reg_notify_queue);
-               if (!next_data || notify_data_write_ccc(notify_data, true,
+               if (!next_data || notify_data_write_ccc(next_data, true,
                                                        enable_ccc_callback))
                        return;
        }