You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Make P2P transfers actually go direct (and stay direct) across NAT, and
ship large files reliably.
- daemon.go: rewrite relayProbeLoop → tryDirectUpgrade. The old loop sent
a one-way SendDirectProbe every 5 min, which a stateful NAT/firewall
always drops (no conntrack pinhole). Now it fires a beacon-coordinated
RequestHolePunch to open the pinhole on both NATs, then pushes encrypted
probes at the peer's REAL address so the peer's ClearRelayOnDirect
promotes the path. Unpins blackhole-pinned (non-relay-only) peers,
resolves fresh when uncached, and runs every 15 s (was 5 min).
- tunnel.go: add SendDirectProbeTo — encrypted probe to an explicit real
address (the upgrade primitive; the stored peers[] entry for a relay
peer is the beacon placeholder).
- ipc.go: handlePreferDirect — drop tunnel + cached resolution so the next
dial re-runs resolve + punch; unpin relay.
- pilotctl/main.go: send-file streams by default (TypeFileStream) and
falls back to single-frame TypeFile when the peer never sends an
INIT-ACK (back-compat); --no-stream forces legacy; reports
transport/sha256/throughput. Adds `prefer-direct` command +
--prefer-direct/--timeout flags.
Verified on Mac↔GCP-VM (true dual-NAT) and a fresh throwaway VM: tunnel
goes relay=False via hole-punch in ~8 s through a default-deny firewall,
holds direct through a 50 MB transfer (no flip), byte-perfect sha256,
~7-15× the relay throughput. Survives a cold restart of both ends.
go.mod points common/dataexchange at branch commits (pseudo-versions)
pending their tagged releases; the version-bump to proper tags happens at
release time (v1.11.1), which is intentionally held for review.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
// Reject files that would exceed the data-exchange frame cap before
3726
3795
// opening the connection — keeps the failure path clean and avoids
3727
3796
// streaming a quarter-gigabyte just to have the receiver close.
3728
-
iflen(data) >dataexchange.MaxFrameSize {
3797
+
ifuint32(len(data)) >dataexchange.MaxFrameSize {
3729
3798
fatalCode("invalid_argument",
3730
-
"file too large: %d bytes (max %d). The chunked-streaming protocol planned in docs/PROPOSAL-reliable-file-transfer.md will lift this; until then split the file or compress it.",
3799
+
"file too large: %d bytes (max %d) for the legacy single-frame path. Use the default streamed transfer (omit --no-stream) against a v1.12.0+ receiver.",
0 commit comments