Repository navigation
feat(server): add FSEND_ENABLE_RELAY (pairing + STUN only mode) - #86
Merged
Merged
Conversation
By default the server still forwards data (unchanged). Setting FSEND_ENABLE_RELAY=false puts it in stun-only mode: it keeps answering STUN so peers can hole-punch a direct path, but carries no file data — useful for operators who want to help peers connect without paying for or being liable for relayed traffic. Two enforcement points: - Relay: DisableForwarding drops data datagrams (STUN path untouched), so bytes never move even for a non-compliant client. Forwarding() exposes the mode to the signaling layer. - Allocate response: forwarding_disabled (omitempty, so old servers round-trip as false) tells the client to use RelayAddr for STUN but skip the relay fallback and fail fast with a clear error instead of dialing a relay that would only drop its datagrams. The UDP listener always binds (STUN needs it); only forwarding is gated. Tests: relay drops data while STUN still answers; allocate response flag mirrors the mode; client fails cleanly when forwarding is disabled; envBool parsing rejects typos. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The self-hosting table listed the per-session relay cap default as 1GB, but the code, ServerConfig.Default(), and `fsend server --help` all use 100MB. Correct the default and align the plain-byte-count example (100000000) with the decimal units the table documents. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds
FSEND_ENABLE_RELAY(defaulttrue). Setting itfalseruns the server in stun-only mode: it still answers STUN so peers can hole-punch a direct path, but carries no file data. For operators who want to help peers connect without paying for — or being liable for — relayed traffic.Default behaviour is unchanged (byte-identical to today); no protocol break.
Why
In the current architecture one UDP socket does three jobs: STUN binding, STUN-address delivery (via the allocate response), and byte forwarding. So a naive "disable the relay" that tears down the listener would also kill hole-punching, leaving same-LAN + public-IP peers only. This change decouples forwarding from STUN: STUN/pairing stay, only data forwarding is gated.
How
Two enforcement points:
internal/relay):ServerConfig.DisableForwarding(negative-framed so the zero value forwards). A one-line gate inhandledrops data datagrams after the STUN dispatch — bytes never move even for a non-compliant/old client.Forwarding()exposes the mode to the signaling layer.internal/server+cmd/fsend): allocate response gainsforwarding_disabled(omitempty, so old servers round-trip asfalse= forwarding-capable). The client keeps usingRelayAddrfor STUN but skips the relay dial and fails fast with a clearErrConnectFailedinstead of timing out on a relay that would only drop its packets. Applied at all three consumer sites (sender fallback, receiver fallback,--mode=relay).The UDP listener always binds (STUN needs it); only forwarding is gated. Bearer-token gate on allocate is unchanged. A startup log line announces stun-only mode.
Behaviour matrix
false→ unchangedTests (all pass,
-raceclean)TestForwardingDisabled— data dropped while STUN still answers (the core guarantee, one test)TestForwardingEnabledByDefault— default forwardsTestRelayAllocate_ForwardingDisabledFlag— response flag mirrors the mode;RelayAddralways setTestAllocAndDialRelay_ForwardingDisabled— client fails cleanly without dialingTestServerEnvBool—envBoolparses and rejects typos loudly (matchesenvInt/envBytes)Verified locally:
go build,go vet,gofmt -l, full suite incl.-race. (golangci-lint couldn't run locally — its binary targets go1.25 vs the repo's 1.26.4; CI covers it.)Docs
docs/self-hosting.md: config row + a "Pairing-only mode" section spelling out the trade-off (symmetric-NAT transfers fail rather than relay; UDP still binds for STUN).fsend server --helpupdated.Note
Second commit is an unrelated pre-existing doc fix (
FSEND_MAX_RELAY_BYTES_PER_SESSIONdefault was documented as 1GB; the real default is 100MB). Kept separate so it can be dropped/cherry-picked independently.🤖 Generated with Claude Code