Skip to content

Commit 68cea67

Browse files
committed
add Eio_unix.Sockopt for setting socket options
1 parent e5a0e54 commit 68cea67

File tree

7 files changed

+142
-12
lines changed

7 files changed

+142
-12
lines changed

lib_eio/unix/dune

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
(foreign_stubs
55
(language c)
66
(include_dirs include)
7-
(names fork_action stubs))
7+
(names sockopt fork_action stubs))
88
(libraries eio unix threads mtime.clock.os))

lib_eio/unix/eio_unix.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
module Fd = Fd
44
module Resource = Resource
55
module Private = Private
6+
module Sockopt = Sockopt
67

78
include Types
89
type socket = Net.stream_socket

lib_eio/unix/eio_unix.mli

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,20 @@ module Stdenv : sig
8484
You can use the functions in {!Eio.Stdenv} to access these fields if you prefer. *)
8585
end
8686

87+
module Sockopt : sig
88+
type 'a t = 'a Eio_unix__Sockopt.t =
89+
| SO_KEEPALIVE : bool t
90+
| SO_REUSEADDR : bool t
91+
| SO_REUSEPORT : bool t
92+
| TCP_CORK : int t
93+
| TCP_KEEPCNT : int t
94+
| TCP_KEEPIDLE : int t
95+
| TCP_KEEPINTVL : int t
96+
97+
val set : Fd.t -> 'a t -> 'a -> unit
98+
val get : Fd.t -> 'a t -> 'a
99+
end
100+
87101
(** API for Eio backends only. *)
88102
module Private : sig
89103
type _ Effect.t +=

lib_eio/unix/sockopt.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#include <stdlib.h>
2+
#include <unistd.h>
3+
#include <sys/socket.h>
4+
5+
#ifdef __linux__
6+
#include <netinet/in.h>
7+
#include <netinet/tcp.h>
8+
#endif
9+
10+
#include <caml/mlvalues.h>
11+
#include <caml/unixsupport.h>
12+
#include <caml/socketaddr.h>
13+
14+
#ifndef TCP_CORK
15+
#define TCP_CORK (-1)
16+
#endif
17+
18+
#ifndef TCP_KEEPCNT
19+
#define TCP_KEEPCNT (-1)
20+
#endif
21+
22+
#ifndef TCP_KEEPIDLE
23+
#define TCP_KEEPIDLE (-1)
24+
#endif
25+
26+
#ifndef TCP_KEEPINTVL
27+
#define TCP_KEEPINTVL (-1)
28+
#endif
29+
30+
struct socket_option {
31+
int level;
32+
int option;
33+
};
34+
35+
/* Not exported by caml/sockaddr.h */
36+
CAMLexport value caml_unix_getsockopt_aux(char *, int, int, int, value);
37+
CAMLexport value caml_unix_setsockopt_aux(char *, int, int, int, value, value);
38+
39+
static struct socket_option sockopt_int[] = {
40+
{ IPPROTO_TCP, TCP_CORK },
41+
{ IPPROTO_TCP, TCP_KEEPCNT },
42+
{ IPPROTO_TCP, TCP_KEEPIDLE },
43+
{ IPPROTO_TCP, TCP_KEEPINTVL }
44+
};
45+
46+
CAMLprim value eio_unix_getsockopt_int(value vsocket, value voption)
47+
{
48+
struct socket_option *opt = &(sockopt_int[Int_val(voption)]);
49+
return caml_unix_getsockopt_aux("eio_unix_getsockopt_int",
50+
1, /* TYPE_INT */
51+
opt->level,
52+
opt->option,
53+
vsocket);
54+
}
55+
56+
CAMLprim value eio_unix_setsockopt_int(value vsocket, value voption, value val)
57+
{
58+
struct socket_option *opt = &(sockopt_int[Int_val(voption)]);
59+
return caml_unix_setsockopt_aux("eio_unix_setsockopt_int",
60+
1, /* TYPE_INT */
61+
opt->level,
62+
opt->option,
63+
vsocket,
64+
val);
65+
}

lib_eio/unix/sockopt.ml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
type socket_int_option =
2+
EIO_TCP_CORK
3+
| EIO_TCP_KEEPCNT
4+
| EIO_TCP_KEEPIDLE
5+
| EIO_TCP_KEEPINTVL
6+
7+
external setsockopt_int : Unix.file_descr -> socket_int_option -> int -> unit =
8+
"eio_unix_setsockopt_int"
9+
external getsockopt_int : Unix.file_descr -> socket_int_option -> int =
10+
"eio_unix_getsockopt_int"
11+
12+
type _ t =
13+
| SO_KEEPALIVE : bool t
14+
| SO_REUSEADDR : bool t
15+
| SO_REUSEPORT : bool t
16+
| TCP_CORK : int t
17+
| TCP_KEEPCNT : int t
18+
| TCP_KEEPIDLE : int t
19+
| TCP_KEEPINTVL : int t
20+
21+
let set : type a . Fd.t -> a t -> a -> unit = fun sock k v ->
22+
Fd.use_exn "Sockaddr.set" sock @@ fun fd ->
23+
match k with
24+
| TCP_CORK -> setsockopt_int fd EIO_TCP_CORK v
25+
| TCP_KEEPCNT -> setsockopt_int fd EIO_TCP_KEEPCNT v
26+
| TCP_KEEPIDLE -> setsockopt_int fd EIO_TCP_KEEPIDLE v
27+
| TCP_KEEPINTVL -> setsockopt_int fd EIO_TCP_KEEPINTVL v
28+
| SO_KEEPALIVE -> Unix.(setsockopt fd SO_KEEPALIVE v)
29+
| SO_REUSEADDR -> Unix.(setsockopt fd SO_REUSEADDR v)
30+
| SO_REUSEPORT -> Unix.(setsockopt fd SO_REUSEPORT v)
31+
32+
let get_descr : type a . Unix.file_descr -> a t -> a = fun fd k ->
33+
match k with
34+
| TCP_CORK -> getsockopt_int fd EIO_TCP_CORK
35+
| TCP_KEEPCNT -> getsockopt_int fd EIO_TCP_KEEPCNT
36+
| TCP_KEEPIDLE -> getsockopt_int fd EIO_TCP_KEEPIDLE
37+
| TCP_KEEPINTVL -> getsockopt_int fd EIO_TCP_KEEPINTVL
38+
| SO_KEEPALIVE -> Unix.(getsockopt fd SO_KEEPALIVE)
39+
| SO_REUSEADDR -> Unix.(getsockopt fd SO_REUSEADDR)
40+
| SO_REUSEPORT -> Unix.(getsockopt fd SO_REUSEPORT)
41+
42+
let get : type a . Fd.t -> a t -> a = fun sock k ->
43+
Fd.use_exn "Sockaddr.get" sock (fun fd -> get_descr fd k)

lib_eio/unix/sockopt.mli

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
type _ t =
2+
| SO_KEEPALIVE : bool t
3+
| SO_REUSEADDR : bool t
4+
| SO_REUSEPORT : bool t
5+
| TCP_CORK : int t
6+
| TCP_KEEPCNT : int t
7+
| TCP_KEEPIDLE : int t
8+
| TCP_KEEPINTVL : int t
9+
10+
val set : Fd.t -> 'a t -> 'a -> unit
11+
val get : Fd.t -> 'a t -> 'a

lib_eio_posix/net.ml

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,11 @@ let listen ~reuse_addr ~reuse_port ~backlog ~sw (listen_addr : Eio.Net.Sockaddr.
9797
| `Unix _ | `Tcp _ ->
9898
Switch.null_hook
9999
in
100+
if reuse_addr then
101+
Eio_unix.Sockopt.(set sock SO_REUSEADDR true);
102+
if reuse_port then
103+
Eio_unix.Sockopt.(set sock SO_REUSEPORT true);
100104
Fd.use_exn "listen" sock (fun fd ->
101-
if reuse_addr then
102-
Unix.setsockopt fd Unix.SO_REUSEADDR true;
103-
if reuse_port then
104-
Unix.setsockopt fd Unix.SO_REUSEPORT true;
105105
Unix.bind fd addr;
106106
Unix.listen fd backlog;
107107
);
@@ -126,13 +126,9 @@ let create_datagram_socket ~reuse_addr ~reuse_port ~sw saddr =
126126
begin match saddr with
127127
| `Udp _ | `Unix _ as saddr ->
128128
let addr = Eio_unix.Net.sockaddr_to_unix saddr in
129-
Fd.use_exn "datagram_socket" sock (fun fd ->
130-
if reuse_addr then
131-
Unix.setsockopt fd Unix.SO_REUSEADDR true;
132-
if reuse_port then
133-
Unix.setsockopt fd Unix.SO_REUSEPORT true;
134-
Unix.bind fd addr
135-
)
129+
if reuse_addr then Eio_unix.Sockopt.(set sock SO_REUSEADDR true);
130+
if reuse_port then Eio_unix.Sockopt.(set sock SO_REUSEPORT true);
131+
Fd.use_exn "datagram_socket" sock (fun fd -> Unix.bind fd addr)
136132
| `UdpV4 | `UdpV6 -> ()
137133
end;
138134
(datagram_socket sock :> Eio.Net.datagram_socket)

0 commit comments

Comments
 (0)