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 Dec 9, 2022
1 parent 1d6cfeb commit d4cef4f
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 24 deletions.
6 changes: 4 additions & 2 deletions lib_eio/net.ml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ module Ipaddr = struct
let elide = min elide zeros in
let parts = if zeros = 0 then acc else zeros :: acc in
((if elide < -1 then Some elide else None), List.rev parts)

in
loop 0 0 [] t

Expand Down Expand Up @@ -245,7 +245,7 @@ let connect ~sw (t:#t) addr =
Exn.reraise_with_context ex bt "connecting to %a" Sockaddr.pp addr

let datagram_socket ?(reuse_addr=false) ?(reuse_port=false) ~sw (t:#t) addr =
let addr = (addr :> [Sockaddr.datagram | `UdpV4 | `UdpV6]) in
let addr = (addr :> [Sockaddr.datagram | `UdpV4 | `UdpV6]) in
t#datagram_socket ~reuse_addr ~reuse_port ~sw addr

let getaddrinfo ?(service="") (t:#t) hostname = t#getaddrinfo ~service hostname
Expand Down Expand Up @@ -291,3 +291,5 @@ let with_tcp_connect ?(timeout=Time.Timeout.none) ~host ~service t f =
| exception (Exn.Io _ as ex) ->
let bt = Printexc.get_raw_backtrace () in
Exn.reraise_with_context ex bt "connecting to %S:%s" host service

let setsockopt (s:#socket) = s#setsockopt
40 changes: 27 additions & 13 deletions lib_eio_linux/eio_linux.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1074,8 +1074,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 @@ -1096,15 +1102,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 @@ -1123,9 +1131,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 @@ -1144,14 +1150,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 @@ -1166,8 +1180,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 @@ -1227,7 +1241,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 @@ -727,8 +727,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 @@ -767,7 +773,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 @@ -789,7 +796,7 @@ class virtual ['a] listening_socket ~backlog sock = object (self)
raise (wrap_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 @@ -853,7 +860,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 @@ -918,10 +926,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 @@ -1245,7 +1253,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;
(socket handle :> Eio_unix.socket)
(stream_socket handle :> Eio_unix.socket)
with
| sock -> continue k sock
| exception (Eio.Io _ as ex) -> discontinue k ex
Expand All @@ -1265,7 +1273,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
(wrap a, wrap b)
with
Expand Down

0 comments on commit d4cef4f

Please sign in to comment.