Skip to content

Commit

Permalink
add Eio_unix.Sockopt for setting socket options
Browse files Browse the repository at this point in the history
  • Loading branch information
avsm committed Jul 7, 2023
1 parent b4b3540 commit 7fca564
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 12 deletions.
2 changes: 1 addition & 1 deletion lib_eio/unix/dune
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
(foreign_stubs
(language c)
(include_dirs include)
(names fork_action stubs))
(names sockopt fork_action stubs))
(libraries eio unix threads mtime.clock.os))
1 change: 1 addition & 0 deletions lib_eio/unix/eio_unix.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
module Fd = Fd
module Resource = Resource
module Private = Private
module Sockopt = Sockopt

include Types
type socket = Net.stream_socket
Expand Down
14 changes: 14 additions & 0 deletions lib_eio/unix/eio_unix.mli
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,20 @@ module Stdenv : sig
You can use the functions in {!Eio.Stdenv} to access these fields if you prefer. *)
end

module Sockopt : sig
type 'a t = 'a Eio_unix__Sockopt.t =
| SO_KEEPALIVE : bool t
| SO_REUSEADDR : bool t
| SO_REUSEPORT : bool t
| TCP_CORK : int t
| TCP_KEEPCNT : int t
| TCP_KEEPIDLE : int t
| TCP_KEEPINTVL : int t

val set : Fd.t -> 'a t -> 'a -> unit
val get : Fd.t -> 'a t -> 'a
end

(** API for Eio backends only. *)
module Private : sig
type _ Effect.t +=
Expand Down
65 changes: 65 additions & 0 deletions lib_eio/unix/sockopt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>

#ifdef __linux__
#include <netinet/in.h>
#include <netinet/tcp.h>
#endif

#include <caml/mlvalues.h>
#include <caml/unixsupport.h>
#include <caml/socketaddr.h>

#ifndef TCP_CORK
#define TCP_CORK (-1)
#endif

#ifndef TCP_KEEPCNT
#define TCP_KEEPCNT (-1)
#endif

#ifndef TCP_KEEPIDLE
#define TCP_KEEPIDLE (-1)
#endif

#ifndef TCP_KEEPINTVL
#define TCP_KEEPINTVL (-1)
#endif

struct socket_option {
int level;
int option;
};

/* Not exported by caml/sockaddr.h */
CAMLexport value caml_unix_getsockopt_aux(char *, int, int, int, value);
CAMLexport value caml_unix_setsockopt_aux(char *, int, int, int, value, value);

static struct socket_option sockopt_int[] = {
{ IPPROTO_TCP, TCP_CORK },
{ IPPROTO_TCP, TCP_KEEPCNT },
{ IPPROTO_TCP, TCP_KEEPIDLE },
{ IPPROTO_TCP, TCP_KEEPINTVL }
};

CAMLprim value eio_unix_getsockopt_int(value vsocket, value voption)
{
struct socket_option *opt = &(sockopt_int[Int_val(voption)]);
return caml_unix_getsockopt_aux("eio_unix_getsockopt_int",
1, /* TYPE_INT */
opt->level,
opt->option,
vsocket);
}

CAMLprim value eio_unix_setsockopt_int(value vsocket, value voption, value val)
{
struct socket_option *opt = &(sockopt_int[Int_val(voption)]);
return caml_unix_setsockopt_aux("eio_unix_setsockopt_int",
1, /* TYPE_INT */
opt->level,
opt->option,
vsocket,
val);
}
43 changes: 43 additions & 0 deletions lib_eio/unix/sockopt.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
type socket_int_option =
EIO_TCP_CORK
| EIO_TCP_KEEPCNT
| EIO_TCP_KEEPIDLE
| EIO_TCP_KEEPINTVL

external setsockopt_int : Unix.file_descr -> socket_int_option -> int -> unit =
"eio_unix_setsockopt_int"
external getsockopt_int : Unix.file_descr -> socket_int_option -> int =
"eio_unix_getsockopt_int"

type _ t =
| SO_KEEPALIVE : bool t
| SO_REUSEADDR : bool t
| SO_REUSEPORT : bool t
| TCP_CORK : int t
| TCP_KEEPCNT : int t
| TCP_KEEPIDLE : int t
| TCP_KEEPINTVL : int t

let set : type a . Fd.t -> a t -> a -> unit = fun sock k v ->
Fd.use_exn "Sockaddr.set" sock @@ fun fd ->
match k with
| TCP_CORK -> setsockopt_int fd EIO_TCP_CORK v
| TCP_KEEPCNT -> setsockopt_int fd EIO_TCP_KEEPCNT v
| TCP_KEEPIDLE -> setsockopt_int fd EIO_TCP_KEEPIDLE v
| TCP_KEEPINTVL -> setsockopt_int fd EIO_TCP_KEEPINTVL v
| SO_KEEPALIVE -> Unix.(setsockopt fd SO_KEEPALIVE v)
| SO_REUSEADDR -> Unix.(setsockopt fd SO_REUSEADDR v)
| SO_REUSEPORT -> Unix.(setsockopt fd SO_REUSEPORT v)

let get_descr : type a . Unix.file_descr -> a t -> a = fun fd k ->
match k with
| TCP_CORK -> getsockopt_int fd EIO_TCP_CORK
| TCP_KEEPCNT -> getsockopt_int fd EIO_TCP_KEEPCNT
| TCP_KEEPIDLE -> getsockopt_int fd EIO_TCP_KEEPIDLE
| TCP_KEEPINTVL -> getsockopt_int fd EIO_TCP_KEEPINTVL
| SO_KEEPALIVE -> Unix.(getsockopt fd SO_KEEPALIVE)
| SO_REUSEADDR -> Unix.(getsockopt fd SO_REUSEADDR)
| SO_REUSEPORT -> Unix.(getsockopt fd SO_REUSEPORT)

let get : type a . Fd.t -> a t -> a = fun sock k ->
Fd.use_exn "Sockaddr.get" sock (fun fd -> get_descr fd k)
11 changes: 11 additions & 0 deletions lib_eio/unix/sockopt.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
type _ t =
| SO_KEEPALIVE : bool t
| SO_REUSEADDR : bool t
| SO_REUSEPORT : bool t
| TCP_CORK : int t
| TCP_KEEPCNT : int t
| TCP_KEEPIDLE : int t
| TCP_KEEPINTVL : int t

val set : Fd.t -> 'a t -> 'a -> unit
val get : Fd.t -> 'a t -> 'a
18 changes: 7 additions & 11 deletions lib_eio_posix/net.ml
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,11 @@ let listen ~reuse_addr ~reuse_port ~backlog ~sw (listen_addr : Eio.Net.Sockaddr.
| `Unix _ | `Tcp _ ->
Switch.null_hook
in
if reuse_addr then
Eio_unix.Sockopt.(set sock SO_REUSEADDR true);
if reuse_port then
Eio_unix.Sockopt.(set sock SO_REUSEPORT true);
Fd.use_exn "listen" sock (fun fd ->
if reuse_addr then
Unix.setsockopt fd Unix.SO_REUSEADDR true;
if reuse_port then
Unix.setsockopt fd Unix.SO_REUSEPORT true;
Unix.bind fd addr;
Unix.listen fd backlog;
);
Expand All @@ -126,13 +126,9 @@ let create_datagram_socket ~reuse_addr ~reuse_port ~sw saddr =
begin match saddr with
| `Udp _ | `Unix _ as saddr ->
let addr = Eio_unix.Net.sockaddr_to_unix saddr in
Fd.use_exn "datagram_socket" sock (fun fd ->
if reuse_addr then
Unix.setsockopt fd Unix.SO_REUSEADDR true;
if reuse_port then
Unix.setsockopt fd Unix.SO_REUSEPORT true;
Unix.bind fd addr
)
if reuse_addr then Eio_unix.Sockopt.(set sock SO_REUSEADDR true);
if reuse_port then Eio_unix.Sockopt.(set sock SO_REUSEPORT true);
Fd.use_exn "datagram_socket" sock (fun fd -> Unix.bind fd addr)
| `UdpV4 | `UdpV6 -> ()
end;
(datagram_socket sock :> Eio.Net.datagram_socket)
Expand Down

0 comments on commit 7fca564

Please sign in to comment.