Skip to content

net: report the kernel-assigned port after listening on port 0 - #80

Open
0pcom wants to merge 2 commits into
tinygo-org:mainfrom
0magnet:listener-ephemeral-port
Open

0pcom wants to merge 2 commits into
tinygo-org:mainfrom
0magnet:listener-ephemeral-port

Conversation

@0pcom

@0pcom 0pcom commented Sep 1, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #97.

Listening on :0 asks the kernel for an ephemeral port, but the listener kept
the requested address, so ln.Addr() reported port 0. Binding an ephemeral port
and dialing ln.Addr(), the pattern httptest.NewServer uses, could not work.

Add GetSockname to the host netdev and look it up from listenTCP through an
optional interface, so netdevs that cannot report the bound address keep their
previous behavior. UDP is unaffected because ListenUDP already fills in a port
before binding.

The second commit is @yohimik's fix to preserve the listener zone when applying
the bound port, cherry picked with authorship preserved.

Verified on linux/amd64 with tinygo dev. Listen("127.0.0.1:0") reports the real
port and dialing ln.Addr().String() connects.

@yohimik

yohimik commented Sep 5, 2026

Copy link
Copy Markdown

I integrated your 7bf5e52 into the fork and kept your authorship and source commit reference. One small finding: the new TCPAddr assignment drops laddr.Zone. Adding Zone: laddr.Zone preserves it without changing the input address.

Tests and correction are available to use here. TestEphemeralListenDial checks a nonzero port from Listen("tcp4", "127.0.0.1:0"), calls normal Dial with l.Addr().String(), and transfers a byte. It fails on the fork before your patch and passes with your patch. TestEphemeralPreservesZone uses a fake netdev and fails on the original assignment, then passes with the Zone field preserved.

Both tests pass on Linux arm64 and native Darwin arm64 with released TinyGo 0.43.0-net.1, Go 1.26.7, isolated TINYGOROOT, and 15-second process limits. For integration with #74, Accept must retain setSockDefaults(nfd, syscall.SOCK_STREAM) before the new return. TestEphemeralAcceptedNoSigpipe also passes on Darwin and checks the accepted socket option.

No duplicate PR was opened. This remains your port fix. The fork's known close and poller limits are unchanged.

@0pcom

0pcom commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

Thank you — the Zone drop was real. Your 0f46080 is now cherry-picked here as 7b7aacb, authorship preserved.

One adaptation: ephemeralTestNetdev no longer embeds listenConfigNetdev, which lives in the #82 branch — the fake is self-contained (a nopNetdev with Socket/Bind/Listen/Close succeeding and the fixed GetSockname), so this PR stays independent of ListenConfig. Both tests pass with the dev compiler on linux/amd64: TestEphemeralPreservesZone fails on the old assignment and passes with Zone: laddr.Zone, as you found.

@deadprogram

Copy link
Copy Markdown
Member

Please update or replace this PR to follow https://github.com/tinygo-org/net/blob/main/AGENTS.md

Thank you.

0pcom and others added 2 commits September 30, 2026 12:55
Listening on ":0" asks the kernel for an ephemeral port, but the listener kept
the requested address, so ln.Addr() reported port 0 and dialing it could not
work. Add GetSockname to the host netdev and look it up from listenTCP through
an optional interface, so netdevs that cannot report the bound address keep
their previous behavior. ListenUDP already fills in a port before binding.
@0pcom
0pcom force-pushed the listener-ephemeral-port branch from 7b7aacb to c1c9fe3 Compare September 30, 2026 18:15
@0pcom

0pcom commented Sep 30, 2026

Copy link
Copy Markdown
Contributor Author

Updated to follow AGENTS.md. The description, commit messages and comments are rewritten, and the fixup commits are gone.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

net: Listener.Addr reports port 0 after listening on port 0

3 participants