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

Enable socket options #9

Closed
loganek opened this issue Jul 26, 2022 · 6 comments
Closed

Enable socket options #9

loganek opened this issue Jul 26, 2022 · 6 comments

Comments

@loganek
Copy link

loganek commented Jul 26, 2022

In POSIX we have setsockopt/getsockopt which allow setting various parameters of the socket. I don't think we want to expose all of them through the API, but there's at least few of them that I think is worth exposing (for example, SO_RCVTIMEO/SO_SNDTIMEO). Because option values can have different type, I don't think it'd be feasible to define a generic set_option/get_option` method. Instead, we might end-up in having property functions, e.g.:

set_timeout: func(socket: handle socket, timeout: Duration) -> expected<none, error>

what are your thoughts on that?

@sunfishcode
Copy link
Member

That makes sense to me.

For completeness, another option would be to have a single setsockopt/getsockopt which take a variant argument, with the variant determining which operation to perform and providing the operands, like this:

variant option {
    timeout(timeval),
    ...
}

setsockopt(socket: handle socket, opt: option) -> expected<_, error>;

or so. I'd be tempted to prefer that if it would allow libc to pass option through without looking at them, however a variant would still require libc to look at the opcode and construct the appropriate variant value. If libc is doing that, it isn't any extra work for it to just call a dedicated function like set_timeout.

@badeend
Copy link
Collaborator

badeend commented Aug 7, 2022

I've thought about adding socket options too. I just don't know what the most pragmatic way forward is yet.

In general, it feels like that, after the initial BSD sockets interface design was defined 40 years ago, every new functionality was dumped behind a socket option. So it is not quite as simple as adding "just" 2 functions (get/setsockopt) and calling it a day, because they're a portal into a huge interface surface area. Some of them clashing with WASM/WASI's design objectives.

I don't see any benefits to having a single variant, so I prefer to have separate functions for separate options, similar to what @loganek suggested.

An other aspect is deciding which socket options will make it into the MVP, and which don't. I'd like to prevent the MVP growing in scope forever because of everybody requesting their own favorite options to be added.

A while ago I did an inventory of all socket options. Below is a summary of what I think are the most common options:

Not needed

- SO_TYPE
- SO_PROTOCOL

Can already be derived from socket::kind() -> expected<socket-kind, error>.

No problems

- IP_TTL
- IPV6_UNICAST_HOPS
- TCP_NODELAY
- SO_KEEPALIVE
- SO_RCVBUF
- SO_SNDBUF
- SO_ACCEPTCONN
- FIONREAD (ioctl)

I have no objections to adding these.

Timeouts:

- SO_RCVTIMEO
- SO_SNDTIMEO

The component-model will have built-in cancellation for every async operation, not just send & receive. I think we can leverage that.

Dual stack

- IPV6_V6ONLY

See: #1

Affecting other sockets on the system

- SO_REUSEADDR
- SO_REUSEPORT
- SO_REUSEPORT_LB
- SO_EXCLUSIVEADDRUSE
- SO_LINGER
- IP_TOS
- IPV6_TCLASS

It's not clear to me what the security and/or sandboxing implications of these options are.

Multicast

- IP_ADD_MEMBERSHIP
- IP_DROP_MEMBERSHIP
- IP_BLOCK_SOURCE
- IP_UNBLOCK_SOURCE
- IP_MULTICAST_IF
- IP_MULTICAST_LOOP
- IP_MULTICAST_TTL
- IP_MSFILTER
- IP_ADD_SOURCE_MEMBERSHIP
- IP_DROP_SOURCE_MEMBERSHIP
- IPV6_JOIN_GROUP
- IPV6_ADD_MEMBERSHIP
- IPV6_LEAVE_GROUP
- IPV6_DROP_MEMBERSHIP
- IPV6_MULTICAST_HOPS
- IPV6_MULTICAST_IF
- IPV6_MULTICAST_LOOP
- MCAST_JOIN_GROUP
- MCAST_BLOCK_SOURCE
- MCAST_UNBLOCK_SOURCE
- MCAST_LEAVE_GROUP
- MCAST_JOIN_SOURCE_GROUP
- MCAST_LEAVE_SOURCE_GROUP
- MCAST_LEAVE_GROUP
- MCAST_MSFILTER
- get/setsourcefilter

Feels a bit much for the MVP.

@sunfishcode
Copy link
Member

I agree, having separate functions for the options sounds like the most practical approach, and fits well with WASI.

I also think your inventory here looks good. It's relatively easy to add or remove individual options as the proposal progresses, and the inventory here looks like a good starting point.

@loganek
Copy link
Author

loganek commented Aug 8, 2022

Thanks for sharing the list, I think that looks good.

Feels a bit much for the MVP.

How about we start with a few properties as part of the MVP (e.g. SO_RCVBUF/SO_SNDBUF) just to setup a pattern, and then add the rest later?

@badeend
Copy link
Collaborator

badeend commented Aug 21, 2022

I've created a PR with a handful of socket options: #13

For as far as a pattern exists, I used Rust's naming convention:

  • getter: $propertyName
  • setter: "set-" + $propertyName

@badeend
Copy link
Collaborator

badeend commented Feb 25, 2023

I'm going to close this. If more socket options are desired, those could be discussed in dedicated issues.

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

3 participants