Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 42 additions & 12 deletions Interface/MeshCore_Dynamic_Interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,8 +548,11 @@ async def _async_setup(self):
await self._mc.commands.set_radio(
self.radio_freq, self.radio_bw, self.radio_sf, self.radio_cr
)
except Exception:
pass
except Exception as exc:
RNS.log(
f"MeshCore_Dynamic_Interface [{self.name}]: "
f"Radio config error: {exc}", RNS.LOG_WARNING
)

try:
secret_bytes = bytes.fromhex(self.channel_secret_hex)
Expand Down Expand Up @@ -652,8 +655,12 @@ async def _bind_discovery_loop(self):
f"{self.BIND_REQ_PREFIX}"
f"{self._own_mc_key}:{self._own_capability()}"
)
except Exception:
pass
except Exception as exc:
RNS.log(
f"MeshCore_Dynamic_Interface [{self.name}]: "
f"Failed to send RNSBIND_REQ: {exc}",
RNS.LOG_WARNING
)
retries += 1
await asyncio.sleep(self.BIND_RESP_WINDOW_S)

Expand All @@ -666,8 +673,12 @@ async def _bind_discovery_loop(self):
f"{self.BIND_PREFIX}"
f"{self._own_mc_key}:{self._own_capability()}"
)
except Exception:
pass
except Exception as exc:
RNS.log(
f"MeshCore_Dynamic_Interface [{self.name}]: "
f"Failed to send RNSBIND heartbeat: {exc}",
RNS.LOG_WARNING
)
await asyncio.sleep(self.BIND_HEARTBEAT_S)

async def _delayed_bind_response(self):
Expand All @@ -686,8 +697,12 @@ async def _delayed_bind_response(self):
f"after {delay:.1f}s backoff.",
RNS.LOG_DEBUG
)
except Exception:
pass
except Exception as exc:
RNS.log(
f"MeshCore_Dynamic_Interface [{self.name}]: "
f"Failed to send RNSBIND response: {exc}",
RNS.LOG_WARNING
)

# -------------------------------------------------------------------------
# Maintenance
Expand Down Expand Up @@ -877,7 +892,13 @@ async def _process_tunnel_text(self, text: str, sender: str = "", rx_mode: str =
b64 += "=" * (-len(b64) % 4)
try:
raw = base64.urlsafe_b64decode(b64)
except Exception:
except Exception as exc:
if self.debug_level == "debug":
RNS.log(
f"MeshCore_Dynamic_Interface [{self.name}]: "
f"base64 decode error: {exc}",
RNS.LOG_DEBUG
)
return

if len(raw) < self.HEADER_SIZE:
Expand Down Expand Up @@ -922,7 +943,12 @@ async def _process_tunnel_text(self, text: str, sender: str = "", rx_mode: str =
)
del self._assembly[key]
del self._assembly_meta[key]
except Exception:
except Exception as exc:
RNS.log(
f"MeshCore_Dynamic_Interface [{self.name}]: "
f"Reassembly failed for pkt_id={pkt_id} "
f"from '{sender}': {exc}", RNS.LOG_WARNING
)
self._assembly.pop(key, None)
self._assembly_meta.pop(key, None)
return
Expand Down Expand Up @@ -1126,8 +1152,12 @@ def processOutgoing(self, data):
try:
# Thread-safe blocking put handles backpressure cleanly
self._outqueue.put((mode, target, frag_str), block=True, timeout=None)
except Exception:
pass
except Exception as exc:
RNS.log(
f"MeshCore_Dynamic_Interface [{self.name}]: "
f"Failed to enqueue fragment: {exc}",
RNS.LOG_WARNING
)

self.txb += len(data)

Expand Down
62 changes: 30 additions & 32 deletions Interface/MeshCore_Interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ def _read_reticulum_config_file(self):
cfg[k.strip()] = v.strip()
if cfg:
return cfg
except Exception:
except Exception as exc:
_safe_log(self._LOG_WARNING, f"MeshCore: failed to read config file {p}: {exc}")
continue
return None

Expand Down Expand Up @@ -285,8 +286,8 @@ async def _on_rx_log(event):
# map advert name lower() -> contact public key for quick resolution
self.dest_to_node_dict[adv.lower()] = contact
_safe_log(self._LOG_INFO, f"MeshCore: discovered {len(contacts)} contacts on device")
except Exception:
pass
except Exception as exc:
_safe_log(self._LOG_WARNING, f"MeshCore: initial contact fetch failed: {exc}")

# Map endpoint_contact explicitly if configured
if self.endpoint_contact:
Expand All @@ -307,34 +308,29 @@ async def _on_rx_log(event):
_safe_log(self._LOG_INFO, "MeshCoreInterface: online (meshcore ready)")

# Register with RNS transport only once and only after online
try:
# RNS.Transport.register_interface(self) - use Interface.register? Use Transport global if available
if not self._registered_with_rns:
try:
# Preferred: RNS.Transport.register_interface
transport = getattr(RNS, "Transport", None)
if transport and hasattr(transport, "register_interface"):
transport.register_interface(self)
else:
# Fallback to Interface.register_interface if present
if hasattr(self, "register_interface"):
self.register_interface()
self._registered_with_rns = True
_safe_log(self._LOG_INFO, f"MeshCoreInterface: registered with Reticulum transport (name={self.name})")
except Exception as e:
_safe_log(self._LOG_WARNING, f"MeshCoreInterface: failed to register with Reticulum transport: {e}")
except Exception:
pass
if not self._registered_with_rns:
try:
# Preferred: RNS.Transport.register_interface
transport = getattr(RNS, "Transport", None)
if transport and hasattr(transport, "register_interface"):
transport.register_interface(self)
else:
# Fallback to Interface.register_interface if present
if hasattr(self, "register_interface"):
self.register_interface()
self._registered_with_rns = True
_safe_log(self._LOG_INFO, f"MeshCoreInterface: registered with Reticulum transport (name={self.name})")
except Exception as e:
_safe_log(self._LOG_WARNING, f"MeshCoreInterface: failed to register with Reticulum transport: {e}")

return True

fut = self._run_coro_no_wait(_async_setup())

try:
fut.result(timeout=5)
except Exception:
# That's fine; _async_setup will complete asynchronously
pass
except Exception as exc:
_safe_log(self._LOG_DEBUG, f"MeshCore: async setup did not complete within 5s (will continue in background): {exc}")

async def _handle_incoming_payload(self, event, payload):
"""
Expand Down Expand Up @@ -393,7 +389,8 @@ async def _handle_incoming_payload(self, event, payload):
sender_hex = contact_obj.get("public_key") or contact_obj.get("pubkey")
else:
sender_hex = str(from_key)
except Exception:
except Exception as exc:
_safe_log(self._LOG_DEBUG, f"MeshCore: sender key normalization fallback: {exc}")
sender_hex = str(from_key)

# Normalize short prefixes to hex-like strings for dictionary keys
Expand All @@ -412,8 +409,8 @@ async def _handle_incoming_payload(self, event, payload):
if sender_hex and isinstance(sender_hex, str) and len(sender_hex) >= 8:
# ensure a mapping exists for the sender prefix -> contact (use contact_obj if available)
self.dest_to_node_dict[sender_hex[:8]] = contact_obj or sender_hex
except Exception:
pass
except Exception as exc:
_safe_log(self._LOG_DEBUG, f"MeshCore: peer mapping update failed: {exc}")

# Debug: print raw metadata bytes for inspection
try:
Expand Down Expand Up @@ -513,10 +510,10 @@ async def _handle_new_contact_event(self, event):
self.endpoint_contact = pk
_safe_log(self._LOG_INFO, f"MeshCore: endpoint_contact resolved to {adv} ({pk[:12]}...)")
break
except Exception:
pass
except Exception:
pass
except Exception as exc:
_safe_log(self._LOG_WARNING, f"MeshCore: endpoint_contact resolution failed: {exc}")
except Exception as exc:
_safe_log(self._LOG_WARNING, f"MeshCore: _handle_new_contact_event error: {exc}")

def _payload_for_send(self, data: bytes) -> str:
"""
Expand Down Expand Up @@ -691,7 +688,8 @@ def process_outgoing(self, data: bytes):
mapped = self.dest_to_node_dict.get(bytes(rns_dest).hex()) or self.dest_to_node_dict.get(bytes(rns_dest).hex()[:8])
if mapped:
dest = mapped
except Exception:
except Exception as exc:
_safe_log(self._LOG_DEBUG, f"MeshCore: destination extraction failed: {exc}")
dest = None

# normalize dest to hex string if bytes
Expand Down