libsocket
libsocket copied to clipboard
Calling setsockopts on unconnected socket
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?
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.
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.
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>.
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.
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.
That would work. There would be a lot of if statements, but welcome to C :laughing:. 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.
cf. https://github.com/dermesser/libsocket/blob/master/C/inet/libinetsocket.c#L572 Maybe a little more compact, and we're fine :+1: