Skip to content

Commit

Permalink
use extensible types and move to Eio_unix.Net
Browse files Browse the repository at this point in the history
  • Loading branch information
avsm committed Jul 22, 2023
1 parent 68cea67 commit 92a06fe
Show file tree
Hide file tree
Showing 13 changed files with 126 additions and 73 deletions.
2 changes: 2 additions & 0 deletions lib_eio/mock/eio_mock.mli
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ module Flow : sig
on_copy_bytes : int Handler.t;
set_copy_method : copy_method -> unit;
attach_to_switch : Eio.Switch.t -> unit;
getsockopt : 'a . 'a Eio.Net.Sockopt.t -> 'a;
setsockopt : 'a . 'a Eio.Net.Sockopt.t -> 'a -> unit;
>

val make : ?pp:string Fmt.t -> string -> t
Expand Down
9 changes: 9 additions & 0 deletions lib_eio/mock/flow.ml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ type t = <
on_copy_bytes : int Handler.t;
set_copy_method : copy_method -> unit;
attach_to_switch : Switch.t -> unit;
getsockopt : 'a . 'a Eio.Net.Sockopt.t -> 'a;
setsockopt : 'a . 'a Eio.Net.Sockopt.t -> 'a -> unit;
>

let pp_default f s =
Expand All @@ -34,6 +36,7 @@ let rec takev len = function
| x :: _ when Cstruct.length x >= len -> [Cstruct.sub x 0 len]
| x :: xs -> x :: takev (len - Cstruct.length x) xs


let make ?(pp=pp_default) label =
let on_read = Handler.make (`Raise End_of_file) in
let on_copy_bytes = Handler.make (`Return 4096) in
Expand Down Expand Up @@ -108,6 +111,12 @@ let make ?(pp=pp_default) label =
Queue.take on_close ()
done;
traceln "%s: closed" label

method getsockopt : 'a . 'a Eio.Net.Sockopt.t -> 'a = fun _ ->
failwith label

method setsockopt : 'a . 'a Eio.Net.Sockopt.t -> 'a -> unit = fun _ ->
failwith "TODO"
end

let on_read (t:t) = Handler.seq t#on_read
Expand Down
7 changes: 7 additions & 0 deletions lib_eio/mock/net.ml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@ let listening_socket label =

method close =
traceln "%s: closed" label

method getsockopt _opt =
traceln "%s: getsockopt" label;
failwith "TODO"

method setsockopt (_: _ Eio.Net.Sockopt.t) _ =
traceln "%s: setsockopt TODO" label
end

let on_accept (l:listening_socket) actions =
Expand Down
9 changes: 9 additions & 0 deletions lib_eio/net.ml
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,19 @@ module Sockaddr = struct
Format.fprintf f "udp:%a:%d" Ipaddr.pp_for_uri addr port
end

module Sockopt = struct
type _ t = ..
end

class virtual socket = object (_ : <Generic.t; Generic.close; ..>)
method probe _ = None
method virtual setsockopt : 'a . 'a Sockopt.t -> 'a -> unit
method virtual getsockopt : 'a . 'a Sockopt.t -> 'a
end

let setsockopt (s: #socket) opt v = s#setsockopt opt v
let getsockopt (s: #socket) opt = s#getsockopt opt

class virtual stream_socket = object (_ : #socket)
inherit Flow.two_way
end
Expand Down
17 changes: 17 additions & 0 deletions lib_eio/net.mli
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,17 @@ module Sockaddr : sig
val pp : Format.formatter -> [< t] -> unit
end

(* Socket options. *)
module Sockopt : sig
type _ t = ..
end

(** {2 Provider Interfaces} *)

class virtual socket : object (<Generic.close; ..>)
inherit Generic.t
method virtual setsockopt : 'a . 'a Sockopt.t -> 'a -> unit
method virtual getsockopt : 'a . 'a Sockopt.t -> 'a
end

class virtual stream_socket : object
Expand Down Expand Up @@ -136,6 +143,16 @@ class virtual t : object
method virtual getnameinfo : Sockaddr.t -> (string * string)
end

(** {2 Socket options} *)

val setsockopt : #socket -> 'a Sockopt.t -> 'a -> unit
(** [setsockopt s opt v] sets the [opt] option to value [v] on socket [s].
See {!Eio_unix.Net.Sockopt} for common Unix socket options. *)

val getsockopt : #socket -> 'a Sockopt.t -> 'a
(** [getsockopt s opt] retrieves the [opt] option on socket [fd].
See {!Eio_unix.Net.Sockopt} for common Unix socket options. *)

(** {2 Out-bound Connections} *)

val connect : sw:Switch.t -> #t -> Sockaddr.stream -> stream_socket
Expand Down
1 change: 0 additions & 1 deletion lib_eio/unix/eio_unix.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
module Fd = Fd
module Resource = Resource
module Private = Private
module Sockopt = Sockopt

include Types
type socket = Net.stream_socket
Expand Down
14 changes: 0 additions & 14 deletions lib_eio/unix/eio_unix.mli
Original file line number Diff line number Diff line change
Expand Up @@ -84,20 +84,6 @@ 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
48 changes: 48 additions & 0 deletions lib_eio/unix/net.ml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,54 @@ class virtual t = object
method getnameinfo = getnameinfo
end

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"

module Sockopt = struct
type _ Eio.Net.Sockopt.t +=
| SO_KEEPALIVE : bool Eio.Net.Sockopt.t
| SO_REUSEADDR : bool Eio.Net.Sockopt.t
| SO_REUSEPORT : bool Eio.Net.Sockopt.t
| TCP_CORK : int Eio.Net.Sockopt.t
| TCP_KEEPCNT : int Eio.Net.Sockopt.t
| TCP_KEEPIDLE : int Eio.Net.Sockopt.t
| TCP_KEEPINTVL : int Eio.Net.Sockopt.t

let set : type a . Fd.t -> a Eio.Net.Sockopt.t -> a -> unit = fun sock k v ->
Fd.use_exn "Sockopt.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)
| _ -> raise (Invalid_argument "TODO pp value")

let get_descr : type a . Unix.file_descr -> a Eio.Net.Sockopt.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)
| _ -> raise (Invalid_argument "TODO pp value")

let get : type a . Fd.t -> a Eio.Net.Sockopt.t -> a = fun sock k ->
Fd.use_exn "Sockopt.get" sock (fun fd -> get_descr fd k)
end

[@@@alert "-unstable"]

type _ Effect.t +=
Expand Down
19 changes: 19 additions & 0 deletions lib_eio/unix/net.mli
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,25 @@ val socketpair_datagram :
This creates OS-level resources using [socketpair(2)].
Note that, like all FDs created by Eio, they are both marked as close-on-exec by default. *)

module Sockopt : sig
(** Socket options *)

type _ Eio.Net.Sockopt.t +=
SO_KEEPALIVE : bool Eio.Net.Sockopt.t
| SO_REUSEADDR : bool Eio.Net.Sockopt.t
| SO_REUSEPORT : bool Eio.Net.Sockopt.t
| TCP_CORK : int Eio.Net.Sockopt.t (* TODO These are Linux-only; move to Eio_linux.Net? *)
| TCP_KEEPCNT : int Eio.Net.Sockopt.t
| TCP_KEEPIDLE : int Eio.Net.Sockopt.t
| TCP_KEEPINTVL : int Eio.Net.Sockopt.t

val set : Fd.t -> 'a Eio.Net.Sockopt.t -> 'a -> unit
(** [set fd opt v] sets the [opt] option to value [v] on socket [fd]. *)

val get : Fd.t -> 'a Eio.Net.Sockopt.t -> 'a
(** [get fd opt v] retrieves the [opt] option on socket [fd]. *)
end

(** {2 Private API for backends} *)

val getnameinfo : Eio.Net.Sockaddr.t -> (string * string)
Expand Down
43 changes: 0 additions & 43 deletions lib_eio/unix/sockopt.ml

This file was deleted.

11 changes: 0 additions & 11 deletions lib_eio/unix/sockopt.mli

This file was deleted.

5 changes: 5 additions & 0 deletions lib_eio_posix/flow.ml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ let shutdown fd cmd =
| Unix.Unix_error (Unix.ENOTCONN, _, _) -> ()
| Unix.Unix_error (code, name, arg) -> raise (Err.wrap code name arg)

let setsockopt fd opt v = Eio_unix.Net.Sockopt.set fd opt v
let getsockopt fd opt = Eio_unix.Net.Sockopt.get fd opt

let of_fd fd = object (_ : <Eio_unix.Net.stream_socket; Eio.File.rw>)
method fd = fd

Expand All @@ -83,6 +86,8 @@ let of_fd fd = object (_ : <Eio_unix.Net.stream_socket; Eio.File.rw>)
method write bufs = write_bufs fd bufs
method shutdown cmd = shutdown fd cmd
method close = Fd.close fd
method setsockopt opt v = setsockopt fd opt v
method getsockopt opt = getsockopt fd opt

method probe : type a. a Eio.Generic.ty -> a option = function
| Eio_unix.Resource.FD -> Some fd
Expand Down
14 changes: 10 additions & 4 deletions lib_eio_posix/net.ml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ let listening_socket ~hook fd = object
method! probe : type a. a Eio.Generic.ty -> a option = function
| Eio_unix.Resource.FD -> Some fd
| _ -> None

method getsockopt opt = Eio_unix.Net.Sockopt.get fd opt
method setsockopt opt v = Eio_unix.Net.Sockopt.set fd opt v
end

let datagram_socket sock = object
Expand All @@ -48,6 +51,9 @@ let datagram_socket sock = object
method recv buf =
let addr, recv = Err.run (Low_level.recv_msg sock) [| buf |] in
Eio_unix.Net.sockaddr_of_unix_datagram addr, recv

method getsockopt opt = Eio_unix.Net.Sockopt.get sock opt
method setsockopt opt v = Eio_unix.Net.Sockopt.set sock opt v
end

(* https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml *)
Expand Down Expand Up @@ -98,9 +104,9 @@ let listen ~reuse_addr ~reuse_port ~backlog ~sw (listen_addr : Eio.Net.Sockaddr.
Switch.null_hook
in
if reuse_addr then
Eio_unix.Sockopt.(set sock SO_REUSEADDR true);
Eio_unix.Net.Sockopt.(set sock SO_REUSEADDR true);
if reuse_port then
Eio_unix.Sockopt.(set sock SO_REUSEPORT true);
Eio_unix.Net.Sockopt.(set sock SO_REUSEPORT true);
Fd.use_exn "listen" sock (fun fd ->
Unix.bind fd addr;
Unix.listen fd backlog;
Expand All @@ -126,8 +132,8 @@ 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
if reuse_addr then Eio_unix.Sockopt.(set sock SO_REUSEADDR true);
if reuse_port then Eio_unix.Sockopt.(set sock SO_REUSEPORT true);
if reuse_addr then Eio_unix.Net.Sockopt.(set sock SO_REUSEADDR true);
if reuse_port then Eio_unix.Net.Sockopt.(set sock SO_REUSEPORT true);
Fd.use_exn "datagram_socket" sock (fun fd -> Unix.bind fd addr)
| `UdpV4 | `UdpV6 -> ()
end;
Expand Down

0 comments on commit 92a06fe

Please sign in to comment.