How to pass SO_RCVTIMEO option to a socket?

Is it possible to pass the SO_RCVTIMEO socket option (man 7 socket ) to an Erlang/Elixir socket with inet:setopts/2 and how?

Bonus question: how do you do it with ranch?

Help would be highly appreciated!

First. I know nothing about this. Have a read below and feel free to completely ignore everything :smiley:

Looking at the manual page of inet:setopts/2 you can use the raw option to set options not explicitly supported by setopts

They have an example setting TCP_LINGER2 to 30 using this:

inet:setopts(Sock,[{raw,6,8,<<30:32/native>>}])
or in elixir
:inet.setopts(sock, [{:raw, 6, 8, <<30::32-native>>}])

Unfortunately I don’t know the protocol level or option number for SO_RCVTIMEO (it might be platform dependent?) and I don’t know how to format a timeval struct outside of C.

My best guess would be something like:

$ cat tempo.c
#include <sys/socket.h>
#include <stdio.h>

int main() {
    printf("SO_RCVTIMEO: %d\n", SO_RCVTIMEO);
    printf("SOL_SOCKET: %d\n", SOL_SOCKET); 
    printf("sizeof(time_t): %lu\n", sizeof(time_t));
    printf("sizeof(timeval): %lu\n", sizeof(struct timeval));
}
$ gcc tempo.c
$ ./a.out
SO_RCVTIMEO: 20
SOL_SOCKET: 1
sizeof(time_t): 8
sizeof(timeval): 16

And then use the above values to try to set the option.

:inet.setopts(socket, [{:raw, 1, 20, <<30::64-native-unsigned, 0::64-native-unsigned>>}]).

This might be very dangerous. Are 1 and 20 and the timeval sizes and format platform and machine architecture dependent? Is the option even set? I don’t know how to find out.

As for ranch you should be able to use Transport:setopts/2 which means either ranch_tcp or ranch_ssl depending on transport used. There might also be an option to pass the raw option in when you start a listener through the options.

2 Likes

Thank you, it’s helping!

In the documentation page socket usage we can read:

rcvtimeo timeval() yes yes This option is not normally supported (see why below). OTP has to be explicitly built with the --enable-esock-rcvsndtime configure option for this to be available. Since our implementation is nonblocking, its unknown if and how this option works, or even if it may cause malfunctions. Therefor, we do not recommend setting this option. Instead, use the Timeout argument to, for instance, the recv/3 function.

2 Likes