From ece7355483a5d1e077781f5bdd39a6ba8bf59401 Mon Sep 17 00:00:00 2001 From: Patrick Ferris Date: Wed, 28 Feb 2024 13:19:12 +0000 Subject: [PATCH] Expose listen in linux --- lib_eio_linux/eio_linux.ml | 1 - lib_eio_linux/eio_linux.mli | 22 ++++++++++++++++++++++ lib_eio_linux/low_level.ml | 29 +++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/lib_eio_linux/eio_linux.ml b/lib_eio_linux/eio_linux.ml index 26390b450..8c97b54a3 100644 --- a/lib_eio_linux/eio_linux.ml +++ b/lib_eio_linux/eio_linux.ml @@ -262,7 +262,6 @@ let connect ~sw connect_addr = let sock = Fd.of_unix ~sw ~seekable:false ~close_unix:true sock_unix in Low_level.connect sock addr; (flow sock :> _ Eio_unix.Net.stream_socket) - module Impl = struct type t = unit type tag = [`Unix | `Generic] diff --git a/lib_eio_linux/eio_linux.mli b/lib_eio_linux/eio_linux.mli index aa8cfa3d1..a17e2868e 100644 --- a/lib_eio_linux/eio_linux.mli +++ b/lib_eio_linux/eio_linux.mli @@ -147,6 +147,14 @@ module Low_level : sig val connect : fd -> Unix.sockaddr -> unit (** [connect fd addr] attempts to connect socket [fd] to [addr]. *) + val listen : + reuse_addr:bool -> + reuse_port:bool -> + backlog:int -> + sw:Switch.t -> + Eio.Net.Sockaddr.stream -> + fd + val await_readable : fd -> unit (** [await_readable fd] blocks until [fd] is readable (or has an error). *) @@ -251,3 +259,17 @@ module Low_level : sig end end + +val flow : + fd -> + [< `Close + | `File + | `Flow + | `Platform of [ `Generic | `Unix ] + | `R + | `Shutdown + | `Socket + | `Stream + | `Unix_fd + | `W ] + r diff --git a/lib_eio_linux/low_level.ml b/lib_eio_linux/low_level.ml index 9ba42b62f..8a9d6da39 100644 --- a/lib_eio_linux/low_level.ml +++ b/lib_eio_linux/low_level.ml @@ -233,6 +233,35 @@ let connect fd addr = raise ex ) +let listen ~reuse_addr ~reuse_port ~backlog ~sw listen_addr = + if reuse_addr then ( + match listen_addr with + | `Tcp _ -> () + | `Unix path -> + match Unix.lstat path with + | Unix.{ st_kind = S_SOCK; _ } -> Unix.unlink path + | _ -> () + | exception Unix.Unix_error (Unix.ENOENT, _, _) -> () + | exception Unix.Unix_error (code, name, arg) -> raise @@ Err.wrap code name arg + ); + let addr = Eio_unix.Net.sockaddr_to_unix listen_addr in + let sock_unix = Unix.socket ~cloexec:true (Eio_unix.Net.socket_domain_of listen_addr) Unix.SOCK_STREAM 0 in + let sock = Fd.of_unix ~sw ~seekable:false ~close_unix:true sock_unix in + (* For Unix domain sockets, remove the path when done (except for abstract sockets). *) + begin match listen_addr with + | `Unix path -> + if String.length path > 0 && path.[0] <> Char.chr 0 then + Switch.on_release sw (fun () -> Unix.unlink path) + | `Tcp _ -> () + end; + if reuse_addr then + Unix.setsockopt sock_unix Unix.SO_REUSEADDR true; + if reuse_port then + Unix.setsockopt sock_unix Unix.SO_REUSEPORT true; + Unix.bind sock_unix addr; + Unix.listen sock_unix backlog; + sock + let send_msg fd ?(fds=[]) ?dst buf = Fd.use_exn "send_msg" fd @@ fun fd -> Fd.use_exn_list "send_msg" fds @@ fun fds ->