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

[Feature Request] Compound Addresses (and sockets?) #84

Open
sulix opened this issue Oct 1, 2023 · 1 comment
Open

[Feature Request] Compound Addresses (and sockets?) #84

sulix opened this issue Oct 1, 2023 · 1 comment

Comments

@sulix
Copy link

sulix commented Oct 1, 2023

It's quite common to want to listen on, or connect to machines with multiple addresses. For the former, we can use NULL as an address, which does work as an API to binding on everything (though the implementation is not super-robust yet, see below), but for the latter, SDL_ResolveHostname() can only return a single SDL_Address, so only one of the addresses associated with the hostname can be retrieved.

This can cause problems if some of the addresses associated with the hostname are not reachable (e.g., a site has an IPv6 AAAA record, but the local machine only has a link-local IPv6 address). Equally, it makes it more complicated to listen on a subset of the local addresses (e.g., I want to listen on all addresses associated with one interface.).

One solution I've used in the past is to have "compound addresses", where there's a native "address list" type, and sockets can be bound to multiple addresses (possibly using several sockets behind the scenes, if required). As a bonus, this "address list" could also be an SDL_Address (give it a next pointer to turn it into a linked list, for example), and then the rest of the public API could remain the same.

In addition, it seems that the current implementation of using NULL/AF_UNSPEC to bind on all addresses doesn't always work (e.g., on my machine it'll bind to all addresses of the same family, such as all IPv4 addresses or all IPv6 addresses, but not both). Getting a truly reliable listener for both IPv6 and IPv4 has required setting up two separate sockets with the different address families (and using the V6ONLY option if family if AF_INET6 to prevent double-binding to compatibility addresses). Having multiple sockets backing a single visible socket would require a similar sort of "compound socket".

There'd be a lot of subtlety in getting this right, though: it's pretty straightforward to bind or listen on multiple addresses, but it gets more complicated when connecting / sending (do you send to all addresses, just the first one, a random one, implement some sort of retry logic until one works)? For the most part, it comes together pretty obviously for TCP/stream sockets, but UDP/datagram ones are a bit more ambiguous.

Does this seem like a useful idea, or just too much added complexity, in either the API or implementation? If so, I can experiment with a more concrete proposal.

@icculus
Copy link
Collaborator

icculus commented Oct 2, 2023

I think it's too much complexity that most things aren't going to use.

The exception is talking to both IPv4 and IPv6 at the same time, and the usual solution is to use a dual-stack socket by turning off the IPV6_V6ONLY flag, which allows IPv4 addresses map into the IPv6 address space. Linux defaults to this being off, WinSock defaults to it being on, and SDL_net is not explicitly setting it at the moment and probably should.

icculus added a commit that referenced this issue Oct 22, 2023
(It defaults to 1 for WinSock and 0 most other places.)

We try to do this no matter what, and we don't care if it fails; in case of
failure, it was either applied to a non-IPv6 socket where it would be
meaningless, or we're just going to have to live with what we got anyhow.

Reference Issue #84.
Reference Issue #58.
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

No branches or pull requests

2 participants