Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

create_tcp_listener(local_port=0): return listeners with the same port #857

Open
1 task done
gschaffner opened this issue Jan 9, 2025 · 1 comment
Open
1 task done
Labels
enhancement New feature or request

Comments

@gschaffner
Copy link
Collaborator

Things to check first

  • I have searched the existing issues and didn't find my feature already requested there

Feature description

it would be nice if multilistener = await create_tcp_listener(local_port=0) used the same port for both of the listeners. This would be [implemented via something roughly] like

def get_free_ipv4_ipv6_port(kind, bind_ipv4_addr, bind_ipv6_addr):
    if platform_has_dualstack and bind_ipv4_addr == bind_ipv6_addr == "":
        # We can use the dualstack_sock.bind(("", 0)) trick
        ...
    else:
        ...

Currently, folks who need this have to implement it downstream.)

Ow, that's definitely something I would like to fix! Strange that nobody has reported that as an issue. I definitely meant for the listener to bind to the same ephemeral port if the local port was omitted.

Originally posted by @agronholm in #856 (comment)

Use case

.

@gschaffner
Copy link
Collaborator Author

gschaffner commented Jan 9, 2025

BTW, I have initially labelled this as a feature request rather than as a bug because I wanted to point out that trio.open_tcp_listeners(port=0) does happily return listeners with different ports. IMO this is also surprising behavior for Trio users, but AnyIO does at least currently match Trio's semantics here. Trio does include a warning about it, however, and port is a required argument on Trio. On AnyIO, this behavior is a bit more surprising to users than it is on Trio. This is because on AnyIO it is undocumented (AFAIK), local_port=0 is the default, and AnyIO just lets you do multilistener.extra(SocketAttribute.local_port) which silently ignores one of them, whereas Trio's list[Listener] return type probably helps remind users that they really do need to check them both.

(The multilistener.extra(SocketAttribute.[...]) behavior is documented. I only pointed it out above as I think it may nonetheless surprise unsuspecting users and get used incorrectly.)

(Also, I suppose that fixing this would technically be a breaking change. On a machine that is totally out of free IPv6 ephemeral ports, it would now fail where it previously passed. I think that that is fine.)

Feel free to change the label to bug.

Strange that nobody has reported that as an issue.

Personally (n=1), IIRC the reason that I didn't bring up this behavior on Gitter when I first noticed it was just some combination of limited time and IPv6 support being a low priority on our (my workplace's) particular networks. Perhaps others have also noticed it but similarly had IPv6 support be a low priority for them?

Also, I suspect that code that mistakenly queries only one of the SocketAttribute.local_ports without checking the other probably isn't caught by most test code. If the test client uses happy eyeballs and is on localhost, it will almost always connect fine anyway. (It would only fail if a different application is using the same port number on the other IP version.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant