mirror of
https://github.com/meshcore-dev/meshcore_py.git
synced 2026-06-11 11:56:18 +00:00
G4: F04 + NEW-A — symmetric send() failure signaling across all transports
Why: TCP was the only transport that fired _disconnect_callback on a dead transport or send failure. Serial and BLE returned silently, leaving ConnectionManager unaware the link was down. Additionally, transport.write() (TCP/serial) and write_gatt_char (BLE) had no try/except — any write-time exception escaped the send() coroutine unhandled. This commit makes all three transports symmetric: (a) fire _disconnect_callback when transport is None/dead, (b) wrap the write call in try/except and fire _disconnect_callback on failure. Refs: Forensics report findings F04, NEW-A
This commit is contained in:
@@ -171,11 +171,19 @@ class BLEConnection:
|
|||||||
async def send(self, data):
|
async def send(self, data):
|
||||||
if not self.client:
|
if not self.client:
|
||||||
logger.error("Client is not connected")
|
logger.error("Client is not connected")
|
||||||
|
if self._disconnect_callback:
|
||||||
|
await self._disconnect_callback("ble_transport_lost")
|
||||||
return False
|
return False
|
||||||
if not self.rx_char:
|
if not self.rx_char:
|
||||||
logger.error("RX characteristic not found")
|
logger.error("RX characteristic not found")
|
||||||
return False
|
return False
|
||||||
await self.client.write_gatt_char(self.rx_char, bytes(data), response=True)
|
try:
|
||||||
|
await self.client.write_gatt_char(self.rx_char, bytes(data), response=True)
|
||||||
|
except Exception as exc:
|
||||||
|
logger.warning(f"BLE write failed: {exc}")
|
||||||
|
if self._disconnect_callback:
|
||||||
|
await self._disconnect_callback(f"ble_write_failed: {exc}")
|
||||||
|
return False
|
||||||
|
|
||||||
async def disconnect(self):
|
async def disconnect(self):
|
||||||
"""Disconnect from the BLE device."""
|
"""Disconnect from the BLE device."""
|
||||||
|
|||||||
@@ -125,11 +125,18 @@ class SerialConnection:
|
|||||||
async def send(self, data):
|
async def send(self, data):
|
||||||
if not self.transport:
|
if not self.transport:
|
||||||
logger.error("Transport not connected, cannot send data")
|
logger.error("Transport not connected, cannot send data")
|
||||||
|
if self._disconnect_callback:
|
||||||
|
await self._disconnect_callback("serial_transport_lost")
|
||||||
return
|
return
|
||||||
size = len(data)
|
size = len(data)
|
||||||
pkt = b"\x3c" + size.to_bytes(2, byteorder="little") + data
|
pkt = b"\x3c" + size.to_bytes(2, byteorder="little") + data
|
||||||
logger.debug(f"sending pkt : {pkt}")
|
logger.debug(f"sending pkt : {pkt}")
|
||||||
self.transport.write(pkt)
|
try:
|
||||||
|
self.transport.write(pkt)
|
||||||
|
except OSError as exc:
|
||||||
|
logger.warning(f"Serial write failed: {exc}")
|
||||||
|
if self._disconnect_callback:
|
||||||
|
await self._disconnect_callback(f"serial_write_failed: {exc}")
|
||||||
|
|
||||||
async def disconnect(self):
|
async def disconnect(self):
|
||||||
"""Close the serial connection."""
|
"""Close the serial connection."""
|
||||||
|
|||||||
@@ -137,7 +137,12 @@ class TCPConnection:
|
|||||||
size = len(data)
|
size = len(data)
|
||||||
pkt = b"\x3c" + size.to_bytes(2, byteorder="little") + data
|
pkt = b"\x3c" + size.to_bytes(2, byteorder="little") + data
|
||||||
logger.debug(f"sending pkt : {pkt}")
|
logger.debug(f"sending pkt : {pkt}")
|
||||||
self.transport.write(pkt)
|
try:
|
||||||
|
self.transport.write(pkt)
|
||||||
|
except (OSError, ConnectionResetError) as exc:
|
||||||
|
logger.warning(f"TCP write failed: {exc}")
|
||||||
|
if self._disconnect_callback:
|
||||||
|
await self._disconnect_callback(f"tcp_write_failed: {exc}")
|
||||||
|
|
||||||
async def disconnect(self):
|
async def disconnect(self):
|
||||||
"""Close the TCP connection."""
|
"""Close the TCP connection."""
|
||||||
|
|||||||
Reference in New Issue
Block a user