mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-09-19 04:59:59 +00:00
Writing the CCCD is the one GATT operation a peer can repeat freely on an open connection: no authentication, no Noise session, no announcement, and the Bluetooth spec puts no limit on how often a client may rewrite the descriptor. onDescriptorWriteRequest attached two non-idempotent effects to it. Each ENABLE_NOTIFICATION write appended to subscribedDevices with no contains() check, so N writes put N entries in the list one address owns. broadcastSinglePacketInternal iterates that list and notifies per entry, so every broadcast the mesh produces is then transmitted to that address N times. Each write also scheduled onDeviceConnected, which calls sendBroadcastAnnounce(). That is unthrottled and floods at maxTtl, so a peer could drive a mesh-wide ANNOUNCE at whatever rate it wrote the descriptor. Subscribe by address and return whether the device was newly subscribed, run the peer-connect side effects only on that transition, and honour DISABLE_NOTIFICATION_VALUE instead of keeping a peer on the broadcast feed until it disconnects. Removal now matches on address like the connection cleanup paths, so an unsubscribe cannot miss because the framework handed us a different BluetoothDevice instance for the same address. Refs #901