transport server: bind to the address family enabled on the host - #1832
Draft
Narasimha-sc wants to merge 1 commit into
Draft
transport server: bind to the address family enabled on the host#1832Narasimha-sc wants to merge 1 commit into
Narasimha-sc wants to merge 1 commit into
Conversation
Narasimha-sc
force-pushed
the
nd/rc-listener-ipv4-fallback
branch
from
August 18, 2026 14:35
d340e19 to
bc8f91e
Compare
Narasimha-sc
force-pushed
the
nd/rc-listener-ipv4-fallback
branch
from
August 18, 2026 14:49
bc8f91e to
321731e
Compare
startTCPServer resolves the wildcard address with AI_PASSIVE only and then selects IPv6 address when it is present. On the hosts where IPv6 is disabled in the kernel (ipv6.disable=1) getaddrinfo still returns `::`, creating the socket fails with EAFNOSUPPORT, and the desktop app cannot be connected from the mobile app (simplex-chat/simplex-chat#5515). Add startTCPServerConfigured that also passes AI_ADDRCONFIG, so that the address families without any configured address are excluded - IPv6 wildcard address is only chosen when IPv6 is enabled, and IPv4 wildcard address is used otherwise. Use it for the remote control TLS server, as its address is advertised as IPv4 in the invitation. Some systems do not report configured families in all cases (e.g. Windows does not count loopback addresses), so when resolution with AI_ADDRCONFIG fails the addresses are resolved without it, with the previous behaviour. startTCPServer is unchanged and is still used for SMP/XFTP/ntf servers and for the local TCP server, so they keep failing when IPv6 is disabled.
Narasimha-sc
force-pushed
the
nd/rc-listener-ipv4-fallback
branch
from
August 18, 2026 15:19
321731e to
ff2c627
Compare
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.
Connecting a mobile to the desktop fails when IPv6 is disabled in the kernel (
ipv6.disable=1) — simplex-chat/simplex-chat#5515, simplex-chat/simplex-chat#3531.startTCPServerresolves the wildcard address withAI_PASSIVEonly, and thenselectpicks the IPv6 address whenever one is returned:getaddrinforeturns::even when the host has no IPv6 at all, so the filter selects it andsocket AF_INET6throwsEAFNOSUPPORT.AI_ADDRCONFIGis the missing part of the filter: it excludes the address families that have no address configured on any interface. This addsstartTCPServerConfigured, which passes it, and uses it for the remote control TLS server — the only listener that has to accept connections on an IPv6-less host, as its address is advertised as IPv4 in the invitation.startTCPServeritself is unchanged: SMP/XFTP/ntf servers and the local TCP server keep requiring IPv6, and still fail if it is disabled.Measured
Calling the two functions from this branch with
host = Nothing:startTCPServerstartTCPServerConfigured[::][::]ipv6.disable=1(no IPv6 addresses,socket(AF_INET6)→ EAFNOSUPPORT)Network.Socket.socket: unsupported operation (Address family not supported by protocol)0.0.0.0net.ipv6.conf.all.disable_ipv6=1[::]0.0.0.0Verified in a network namespace — the third row with the real sysctl, the second with an
LD_PRELOADshim makingsocket(AF_INET6)returnEAFNOSUPPORTon top of a namespace with no IPv6 addresses. Also checked thatAI_ADDRCONFIGnever empties the result: on a host with no addresses configured at all glibc falls back to returning both families, sofromJustinselectstays safe.Verified with the XRCP pairing tests, run in a namespace with
disable_ipv6=1plus anLD_PRELOADshim makingsocket(AF_INET6)returnEAFNOSUPPORT:startTCPServer(before this change) the tests hang — the bind throws insidebracketOnError's acquire, sostartedPortis never filled andreadTMVarblocks;startTCPServerConfiguredthey pass in 2.3s (3/3 repeat runs).SMP server via TLS(37 tests) passes unchanged, and the strictstartTCPServerstill binds[::]in every state measured.Two notes on
AI_ADDRCONFIGsemantics that shaped the patch. It keys off configured addresses rather than socket support, so a host that has IPv6 addresses (link-local included) but cannot createAF_INET6sockets would still fail — a combination neitheripv6.disable=1nordisable_ipv6=1produces, as both remove every IPv6 address. And glibc counts only non-loopback addresses, falling back to returning all families when none are configured, while Windows documents that loopback is not a valid global address and promises no such fallback — hence resolving again without the flag if the flagged call fails, so an offline Windows desktop keeps binding as it does today.Supersedes the earlier
catchAny-on-bind version of this PR, which worked around the selection instead of fixing it.