Skip to content

Commit

Permalink
sockopt: implement setsockopt() for linux and luv backends
Browse files Browse the repository at this point in the history
  • Loading branch information
bikallem committed Nov 30, 2022
1 parent 64d770d commit 1d17d62
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 22 deletions.
2 changes: 2 additions & 0 deletions lib_eio/net.ml
Original file line number Diff line number Diff line change
Expand Up @@ -260,3 +260,5 @@ let with_tcp_connect ?(timeout=Time.Timeout.none) ~host ~service t f =
| `Unix _ -> None
)
|> aux

let setsockopt (s:#socket) = s#setsockopt
6 changes: 6 additions & 0 deletions lib_eio/net.mli
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,12 @@ val getnameinfo : #t -> Sockaddr.t -> (string * string)
registered domain name represented by [sockaddr]. [service] is the IANA specified textual name of the
port specified in [sockaddr], e.g. 'ftp', 'http', 'https', etc. *)

(** {2 Socket} *)

val setsockopt : #socket -> 'a sockopt -> 'a -> unit
(** [setsockopt s opt v] configures socket [s] with socket option and value [opt]
and [v] respectively. *)

(** {2 Closing} *)
val close : <close: unit; ..> -> unit
(** [close t] marks the socket as closed. It can no longer be used after this. *)
2 changes: 2 additions & 0 deletions lib_eio/unix/eio_unix.mli
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,5 @@ module Ctf = Ctf_unix

val getnameinfo : Eio.Net.Sockaddr.t -> (string * string)
(** [getnameinfo sockaddr] returns domain name and service for [sockaddr]. *)

val setsockopt : Unix.file_descr -> 'a Eio.Net.sockopt -> 'a -> unit
40 changes: 27 additions & 13 deletions lib_eio_linux/eio_linux.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1031,8 +1031,14 @@ let fallback_copy src dst =
done
with End_of_file -> ()

class socket sock = object
inherit Eio.Net.socket
method setsockopt = Eio_unix.setsockopt (FD.to_unix `Peek sock)
end

let udp_socket sock = object
inherit Eio.Net.datagram_socket
inherit socket sock
inherit! Eio.Net.datagram_socket

method close = FD.close sock

Expand All @@ -1053,15 +1059,17 @@ let udp_socket sock = object
raise (Failure "Expected INET UDP socket address but got Unix domain socket address.")
end

let flow fd =
class flow fd =
let is_tty = lazy (Unix.isatty (FD.get_exn "isatty" fd)) in
object (_ : <source; sink; ..>)
object
inherit Eio.Flow.two_way

method fd = fd
method close = FD.close fd

method stat = FD.fstat fd

method probe : type a. a Eio.Generic.ty -> a option = function
method! probe : type a. a Eio.Generic.ty -> a option = function
| FD -> Some fd
| Eio_unix.Private.Unix_file_descr op -> Some (FD.to_unix op fd)
| _ -> None
Expand All @@ -1080,9 +1088,7 @@ let flow fd =
method pwrite ~file_offset bufs =
Low_level.writev_single ~file_offset fd bufs

method read_methods = []

method write bufs = Low_level.writev fd bufs
method! write bufs = Low_level.writev fd bufs

method copy src =
match get_fd_opt src with
Expand All @@ -1101,14 +1107,22 @@ let flow fd =
| `Send -> Unix.SHUTDOWN_SEND
| `All -> Unix.SHUTDOWN_ALL

method unix_fd op = FD.to_unix op fd
end
method unix_fd (op: [`Peek | `Take]) = FD.to_unix op fd
end

let flow fd = new flow fd

let stream_socket fd = object(_ : <Eio.Net.stream_socket; ..>)
inherit socket fd
inherit! flow fd
end

let source fd = (flow fd :> source)
let sink fd = (flow fd :> sink)

let listening_socket fd = object
inherit Eio.Net.listening_socket
inherit socket fd
inherit! Eio.Net.listening_socket

method! probe : type a. a Eio.Generic.ty -> a option = function
| Eio_unix.Private.Unix_file_descr op -> Some (FD.to_unix op fd)
Expand All @@ -1123,8 +1137,8 @@ let listening_socket fd = object
| Unix.ADDR_UNIX path -> `Unix path
| Unix.ADDR_INET (host, port) -> `Tcp (Eio_unix.Ipaddr.of_unix host, port)
in
let flow = (flow client :> <Eio.Flow.two_way; Eio.Flow.close>) in
flow, client_addr
let stream_socket = (stream_socket client :> <Eio.Net.stream_socket; Eio.Flow.close>) in
stream_socket, client_addr
end

let socket_domain_of = function
Expand Down Expand Up @@ -1183,7 +1197,7 @@ let net = object
let sock_unix = Unix.socket (socket_domain_of connect_addr) socket_type 0 in
let sock = FD.of_unix ~sw ~seekable:false ~close_unix:true sock_unix in
Low_level.connect sock addr;
(flow sock :> <Eio.Flow.two_way; Eio.Flow.close>)
(stream_socket sock :> <Eio.Net.stream_socket; Eio.Flow.close>)

method datagram_socket ~reuse_addr ~reuse_port ~sw saddr =
let sock_unix = Unix.socket ~cloexec:true (socket_domain_of saddr) Unix.SOCK_DGRAM 0 in
Expand Down
26 changes: 17 additions & 9 deletions lib_eio_luv/eio_luv.ml
Original file line number Diff line number Diff line change
Expand Up @@ -674,8 +674,14 @@ end
let source fd = (flow fd :> source)
let sink fd = (flow fd :> sink)

let socket sock = object
inherit Eio.Flow.two_way as super
class socket f sock = object
inherit Eio.Net.socket
method setsockopt = Eio_unix.setsockopt (f `Peek sock |> Option.get)
end

let stream_socket sock = object
inherit socket (Stream.to_unix_opt) sock
inherit! Eio.Net.stream_socket as super

method! probe : type a. a Eio.Generic.ty -> a option = function
| Eio_unix.Private.Unix_file_descr op -> Stream.to_unix_opt op sock
Expand Down Expand Up @@ -714,7 +720,8 @@ let socket sock = object
end

class virtual ['a] listening_socket ~backlog sock = object (self)
inherit Eio.Net.listening_socket as super
inherit socket Stream.to_unix_opt sock
inherit! Eio.Net.listening_socket as super

method! probe : type a. a Eio.Generic.ty -> a option = function
| Eio_unix.Private.Unix_file_descr op -> Stream.to_unix_opt op sock
Expand All @@ -736,7 +743,7 @@ class virtual ['a] listening_socket ~backlog sock = object (self)
raise (Luv_error e)
| Ok () ->
Switch.on_release sw (fun () -> Handle.ensure_closed client);
let flow = (socket client :> <Eio.Flow.two_way; Eio.Flow.close>) in
let flow = (stream_socket client :> <Eio.Net.stream_socket; Eio.Flow.close>) in
let client_addr = self#get_client_addr client in
flow, client_addr

Expand Down Expand Up @@ -800,7 +807,8 @@ module Udp = struct
end

let udp_socket endp = object
inherit Eio.Net.datagram_socket
inherit socket Handle.to_unix_opt endp
inherit! Eio.Net.datagram_socket

method close = Handle.close endp

Expand Down Expand Up @@ -865,10 +873,10 @@ let net = object
method connect ~sw = function
| `Tcp (host, port) ->
let sock = Stream.connect_tcp ~sw (luv_addr_of_eio host port) in
(socket sock :> < Eio.Flow.two_way; Eio.Flow.close >)
(stream_socket sock :> < Eio.Net.stream_socket; Eio.Flow.close >)
| `Unix path ->
let sock = Stream.connect_pipe ~sw path in
(socket sock :> < Eio.Flow.two_way; Eio.Flow.close >)
(stream_socket sock :> < Eio.Net.stream_socket; Eio.Flow.close >)

method datagram_socket ~reuse_addr ~reuse_port ~sw saddr =
let domain = socket_domain_of saddr in
Expand Down Expand Up @@ -1178,7 +1186,7 @@ let rec run : type a. (_ -> a) -> a = fun main ->
let sock = Luv.TCP.init ~loop () |> or_raise in
let handle = Handle.of_luv ~sw ~close_unix sock in
Luv.TCP.open_ sock fd |> or_raise;
continue k (socket handle :> Eio_unix.socket)
continue k (stream_socket handle :> Eio_unix.socket)
with Luv_error _ as ex ->
discontinue k ex
)
Expand All @@ -1197,7 +1205,7 @@ let rec run : type a. (_ -> a) -> a = fun main ->
let sock = Luv.TCP.init ~loop () |> or_raise in
Luv.TCP.open_ sock x |> or_raise;
let h = Handle.of_luv ~sw ~close_unix:true sock in
(socket h :> Eio_unix.socket)
(stream_socket h :> Eio_unix.socket)
in
continue k (wrap a, wrap b)
with Luv_error _ as ex ->
Expand Down

0 comments on commit 1d17d62

Please sign in to comment.