From 2694192d2829c1eb85696ad7e71a6f570b011251 Mon Sep 17 00:00:00 2001 From: torlando-tech Date: Sun, 18 Jan 2026 13:09:56 -0500 Subject: [PATCH] fix: consume duplicate identity handshake when identity already known via Kotlin callback When Kotlin provides the identity via callback (from the identity characteristic read), the address_to_identity mapping gets set BEFORE the 16-byte handshake data arrives through _data_received_callback. Previously, _handle_identity_handshake would see the identity already exists and return False, causing the 16-byte handshake data to be passed to the reassembler where it fails with "Invalid fragment type 0xXX". The fix checks if received 16-byte data matches the known identity and consumes it silently if so. This prevents the handshake data from being misinterpreted as a fragment. Symptoms fixed: - BLEReassembler: Invalid fragment type 0xc9 (first byte of peer identity) - Messages not flowing even though connections appear established Co-Authored-By: Claude Opus 4.5 --- src/ble_reticulum/BLEInterface.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/ble_reticulum/BLEInterface.py b/src/ble_reticulum/BLEInterface.py index 5b912a0..49ed348 100644 --- a/src/ble_reticulum/BLEInterface.py +++ b/src/ble_reticulum/BLEInterface.py @@ -1186,14 +1186,24 @@ class BLEInterface(Interface): Returns: True if data was handled as identity handshake, False otherwise """ + # Identity handshake detection: exactly 16 bytes + if len(data) != 16: + return False # Not a handshake + # Check if we already have peer identity peer_identity = self.address_to_identity.get(address) if peer_identity: - return False # Already have identity, not a handshake - - # Identity handshake detection: exactly 16 bytes, no existing identity - if len(data) != 16: - return False # Not a handshake + # We already have identity for this address (probably set via Kotlin callback). + # The 16-byte handshake data may still arrive through the data channel. + # Check if it matches the identity we have - if so, consume it silently. + if data == peer_identity: + RNS.log(f"{self} received duplicate identity handshake from {address} (already known via callback)", RNS.LOG_DEBUG) + return True # Consume the data, don't pass to reassembler + else: + # 16 bytes but doesn't match known identity - log warning but still consume + # to avoid passing identity-like data to the reassembler + RNS.log(f"{self} received 16-byte data from {address} that differs from known identity, consuming as handshake", RNS.LOG_WARNING) + return True # Consume to prevent reassembler errors try: # Store central's identity