summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-node/src')
-rw-r--r--packages/meshbay-node/src/meshbay_node/transport/quic_server.py16
1 files changed, 16 insertions, 0 deletions
diff --git a/packages/meshbay-node/src/meshbay_node/transport/quic_server.py b/packages/meshbay-node/src/meshbay_node/transport/quic_server.py
index 8ab359d..9cb3bd8 100644
--- a/packages/meshbay-node/src/meshbay_node/transport/quic_server.py
+++ b/packages/meshbay-node/src/meshbay_node/transport/quic_server.py
@@ -273,6 +273,22 @@ class QuicChunkServer:
)
log.info("QuicChunkServer listening on %s:%d (QUIC/UDP)", self._host, self._port)
+ def punch_nat(self, peer_ip: str, peer_port: int) -> None:
+ """
+ Send a probe UDP packet FROM the QUIC server's own socket.
+
+ Critical for Port-Restricted Cone NAT (SFR résidentiel) :
+ the NAT only allows inbound from (peer_ip, peer_port) if the server
+ previously sent a packet TO (peer_ip, peer_port) from this same socket.
+
+ The QUIC client must connect FROM peer_port for the NAT entry to match.
+ """
+ if self._server and hasattr(self._server, '_transport') and self._server._transport:
+ self._server._transport.sendto(b'MESHBAY:NAT:PUNCH', (peer_ip, peer_port))
+ log.info("NAT probe sent → %s:%d", peer_ip, peer_port)
+ else:
+ log.warning("punch_nat: server transport not available")
+
async def stop(self) -> None:
if self._server:
self._server.close()