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

Calling setsockopts on unconnected socket #16

Open
thirtythreeforty opened this issue Apr 23, 2014 · 7 comments
Open

Calling setsockopts on unconnected socket #16

thirtythreeforty opened this issue Apr 23, 2014 · 7 comments

Comments

@thirtythreeforty
Copy link
Contributor

As far as I can tell, it isn't possible to set options on a socket without first getting it into the connected state. It would be useful to do this, for example, to set the socket option SO_REUSEADDR before connecting. The problem is that the socket isn't actually created until connection time.

Using setsockopt with inet_stream::getfd works fine after connecting, because the socket file descriptor is then valid.

Am I missing something, or is this not possible?

@dermesser
Copy link
Owner

It's hardly possible for both the C and the C++ part because TCP client sockets are created and immediately connected after that in create_inet_stream_socket in C/inet/libinetsocket.c (actual socket()/connect() in lines 185+). From the viewpoint of libsocket++, it's an atomic operation.

The only possibility I see at the moment is introducing some more parameters in create_inet_stream_socket which are passed to a setsockopt call. Or, if you want to especially set the SO_REUSEADDR flag, a boolean (in C: int) flag.

@thirtythreeforty
Copy link
Contributor Author

I follow. Shouldn't the socket be created when the object is created (RAII) and then only connected when you call connect()? (The constructor could of course call connect() too if appropriate.)

I think the more-parameter option is a decent one, but how would you set multiple options in a scalable way? The only possibility I see is accepting a std::vector of parameter:value pairs but that doesn't seem very clean in C.

@dermesser
Copy link
Owner

It may at first seem as a better alternative to do it the RAII way you mentioned.

But there comes a load of problems with it, the (in my opinion) most important one being the choice of the address family. Usually I would use LIBSOCKET_BOTH to let getaddrinfo() choose what address family to use. In that case, I have to create the socket after calling getaddrinfo(), which is done in create_inet_stream_socket(). But if I want to create the socket first and then connect it, I already have to know the address family. I may do that, libinetsocket has a function for it, but it's still not desirable (I believe).

Using an additional parameter int sockopts may work best in that situation. It would be passed to create_inet_stream_socket and inet_stream::inet_stream() (and connect() and so on) and take the values defined in <sys/socket.h>.

@thirtythreeforty
Copy link
Contributor Author

Gotcha. That makes sense.

If you are going to pass sockopts, how would you pass multiple options? For example, if I want to set the two options SO_REUSEADDR and SO_REUSEPORT, I can't just bitwise-or them together for a single call... They're defined as 2 and 15.

@dermesser
Copy link
Owner

Hm... Didn't think of that...

What about implementing LIBSOCKET_... wrappers that may get bitwise ORed, for example: LIBSOCKET_REUSEADDR == 1, LIBSOCKET_REUSEPORT == 2, LIBSOCKET_DONTROUTE == 4 etc. And then converting them back to the SO_... constants.

@thirtythreeforty
Copy link
Contributor Author

That would work. There would be a lot of if statements, but welcome to C 😆. Adding an argument is going to break the interface for existing programs, as C doesn't overload. C++ should be fine though.

Also, oops, I didn't mean to close this.

@dermesser
Copy link
Owner

cf. https://github.com/dermesser/libsocket/blob/master/C/inet/libinetsocket.c#L572 Maybe a little more compact, and we're fine 👍

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