Skip to content

Commit

Permalink
Merge pull request #733 from alyssais/listening
Browse files Browse the repository at this point in the history
Add Eio_unix.Net.import_socket_listening
  • Loading branch information
talex5 authored May 28, 2024
2 parents 2c5eb61 + 3b2a679 commit 3e67f7d
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 2 deletions.
5 changes: 5 additions & 0 deletions lib_eio/unix/net.ml
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,23 @@ type t = [`Generic | `Unix] Eio.Net.ty r

type _ Effect.t +=
| Import_socket_stream : Switch.t * bool * Unix.file_descr -> [`Unix_fd | stream_socket_ty] r Effect.t
| Import_socket_listening : Switch.t * bool * Unix.file_descr -> [`Unix_fd | listening_socket_ty] r Effect.t
| Import_socket_datagram : Switch.t * bool * Unix.file_descr -> [`Unix_fd | datagram_socket_ty] r Effect.t
| Socketpair_stream : Switch.t * Unix.socket_domain * int ->
([`Unix_fd | stream_socket_ty] r * [`Unix_fd | stream_socket_ty] r) Effect.t
| Socketpair_datagram : Switch.t * Unix.socket_domain * int ->
([`Unix_fd | datagram_socket_ty] r * [`Unix_fd | datagram_socket_ty] r) Effect.t

let open_stream s = (s : _ stream_socket :> [< `Unix_fd | stream_socket_ty] r)
let open_listening s = (s : _ listening_socket :> [< `Unix_fd | listening_socket_ty] r)
let open_datagram s = (s : _ datagram_socket :> [< `Unix_fd | datagram_socket_ty] r)

let import_socket_stream ~sw ~close_unix fd =
open_stream @@ Effect.perform (Import_socket_stream (sw, close_unix, fd))

let import_socket_listening ~sw ~close_unix fd =
open_listening @@ Effect.perform (Import_socket_listening (sw, close_unix, fd))

let import_socket_datagram ~sw ~close_unix fd =
open_datagram @@ Effect.perform (Import_socket_datagram (sw, close_unix, fd))

Expand Down
13 changes: 11 additions & 2 deletions lib_eio/unix/net.mli
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,22 @@ end
(** {2 Creating or importing sockets} *)

val import_socket_stream : sw:Switch.t -> close_unix:bool -> Unix.file_descr -> [`Unix_fd | stream_socket_ty] r
(** [import_socket_stream ~sw ~close_unix:true fd] is an Eio flow that uses [fd].
(** [import_socket_stream ~sw ~close_unix fd] is an Eio flow that uses [fd].
It can be cast to e.g. {!source} for a one-way flow.
The socket object will be closed when [sw] finishes.
The [close_unix] and [sw] arguments are passed to {!Fd.of_unix}. *)

val import_socket_listening : sw:Switch.t -> close_unix:bool -> Unix.file_descr -> [`Unix_fd | listening_socket_ty] r
(** [import_socket_listening ~sw ~close_unix fd] is an Eio listening socket that uses [fd].
The socket object will be closed when [sw] finishes.
The [close_unix] and [sw] arguments are passed to {!Fd.of_unix}. *)

val import_socket_datagram : sw:Switch.t -> close_unix:bool -> Unix.file_descr -> [`Unix_fd | datagram_socket_ty] r
(** [import_socket_datagram ~sw ~close_unix:true fd] is an Eio datagram socket that uses [fd].
(** [import_socket_datagram ~sw ~close_unix fd] is an Eio datagram socket that uses [fd].
The socket object will be closed when [sw] finishes.
Expand Down Expand Up @@ -100,6 +107,8 @@ val getnameinfo : Eio.Net.Sockaddr.t -> (string * string)
type _ Effect.t +=
| Import_socket_stream :
Switch.t * bool * Unix.file_descr -> [`Unix_fd | stream_socket_ty] r Effect.t (** See {!import_socket_stream} *)
| Import_socket_listening :
Switch.t * bool * Unix.file_descr -> [`Unix_fd | listening_socket_ty] r Effect.t (** See {!import_socket_listening} *)
| Import_socket_datagram :
Switch.t * bool * Unix.file_descr -> [`Unix_fd | datagram_socket_ty] r Effect.t (** See {!import_socket_datagram} *)
| Socketpair_stream : Eio.Switch.t * Unix.socket_domain * int ->
Expand Down
4 changes: 4 additions & 0 deletions lib_eio_linux/eio_linux.ml
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,10 @@ let run_event_loop (type a) ?fallback config (main : _ -> a) arg : a =
let fd = Fd.of_unix ~sw ~seekable:false ~close_unix fd in
continue k (Flow.of_fd fd :> _ Eio_unix.Net.stream_socket)
)
| Eio_unix.Net.Import_socket_listening (sw, close_unix, fd) -> Some (fun k ->
let fd = Fd.of_unix ~sw ~seekable:false ~close_unix fd in
continue k (listening_socket fd)
)
| Eio_unix.Net.Import_socket_datagram (sw, close_unix, fd) -> Some (fun k ->
let fd = Fd.of_unix ~sw ~seekable:false ~close_unix fd in
continue k (datagram_socket fd)
Expand Down
5 changes: 5 additions & 0 deletions lib_eio_posix/domain_mgr.ml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ let run_event_loop fn x =
Unix.set_nonblock unix_fd;
continue k (Flow.of_fd fd :> _ Eio_unix.Net.stream_socket)
)
| Eio_unix.Net.Import_socket_listening (sw, close_unix, unix_fd) -> Some (fun k ->
let fd = Fd.of_unix ~sw ~blocking:false ~close_unix unix_fd in
Unix.set_nonblock unix_fd;
continue k (Net.listening_socket ~hook:Switch.null_hook fd)
)
| Eio_unix.Net.Import_socket_datagram (sw, close_unix, unix_fd) -> Some (fun k ->
let fd = Fd.of_unix ~sw ~blocking:false ~close_unix unix_fd in
Unix.set_nonblock unix_fd;
Expand Down
5 changes: 5 additions & 0 deletions lib_eio_windows/domain_mgr.ml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ let run_event_loop fn x =
(try Unix.set_nonblock unix_fd with Unix.Unix_error (Unix.ENOTSOCK, _, _) -> ());
continue k (Flow.of_fd fd :> _ Eio_unix.Net.stream_socket)
)
| Eio_unix.Net.Import_socket_listening (sw, close_unix, unix_fd) -> Some (fun k ->
let fd = Fd.of_unix ~sw ~blocking:false ~close_unix unix_fd in
Unix.set_nonblock unix_fd;
continue k (Net.listening_socket ~hook:Switch.null_hook fd)
)
| Eio_unix.Net.Import_socket_datagram (sw, close_unix, unix_fd) -> Some (fun k ->
let fd = Fd.of_unix ~sw ~blocking:false ~close_unix unix_fd in
Unix.set_nonblock unix_fd;
Expand Down
23 changes: 23 additions & 0 deletions tests/network.md
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,29 @@ Wrapping a Unix FD as an Eio stream socket:
- : unit = ()
```

Wrapping a Unix FD as a listening Eio socket:

```ocaml
# run @@ fun ~net sw ->
let l = Unix.(socket PF_INET SOCK_STREAM 0) in
Unix.bind l (Unix.ADDR_INET (Unix.inet_addr_loopback, 8082));
Unix.listen l 40;
let l = Eio_unix.Net.import_socket_listening ~sw ~close_unix:true l in
Fiber.both
(fun () -> run_server ~sw l)
(fun () ->
run_client ~sw ~net ~addr:(`Tcp (Eio.Net.Ipaddr.V4.loopback, 8082));
traceln "Client finished - cancelling server";
raise Graceful_shutdown
);;
+Connecting to server...
+Server accepted connection from client
+Server received: "Hello from client"
+Client received: "Bye"
+Client finished - cancelling server
Exception: Graceful_shutdown.
```

Wrapping a Unix FD as an datagram Eio socket:

```ocaml
Expand Down

0 comments on commit 3e67f7d

Please sign in to comment.