Skip to content

Commit

Permalink
Eio.Net: add getnameinfo
Browse files Browse the repository at this point in the history
  • Loading branch information
bikallem committed Aug 24, 2022
1 parent 1df4155 commit 104f379
Show file tree
Hide file tree
Showing 10 changed files with 60 additions and 14 deletions.
3 changes: 3 additions & 0 deletions lib_eio/mock/eio_mock.mli
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ module Net : sig
on_connect : <Eio.Net.stream_socket; Eio.Flow.close> Handler.t;
on_datagram_socket : <Eio.Net.datagram_socket; Eio.Flow.close> Handler.t;
on_getaddrinfo : Eio.Net.Sockaddr.t list Handler.t;
on_getnameinfo : (string * string) Handler.t;
>

type listening_socket = <
Expand All @@ -143,6 +144,8 @@ module Net : sig

val on_getaddrinfo : t -> Eio.Net.Sockaddr.t list Handler.actions -> unit

val on_getnameinfo : t -> (string * string) Handler.actions -> unit

val listening_socket : string -> listening_socket
(** [listening_socket label] can be configured to provide mock connections. *)

Expand Down
9 changes: 9 additions & 0 deletions lib_eio/mock/net.ml
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,23 @@ type t = <
on_connect : <Eio.Net.stream_socket; Eio.Flow.close> Handler.t;
on_datagram_socket : <Eio.Net.datagram_socket; Eio.Flow.close> Handler.t;
on_getaddrinfo : Eio.Net.Sockaddr.t list Handler.t;
on_getnameinfo : (string * string) Handler.t;
>

let make label =
let on_listen = Handler.make (`Raise (Failure "Mock listen handler not configured")) in
let on_connect = Handler.make (`Raise (Failure "Mock connect handler not configured")) in
let on_datagram_socket = Handler.make (`Raise (Failure "Mock datagram_socket handler not configured")) in
let on_getaddrinfo = Handler.make (`Raise (Failure "Mock getaddrinfo handler not configured")) in
let on_getnameinfo = Handler.make (`Raise (Failure "Mock getnameinfo handler not configured")) in
object
inherit Eio.Net.t

method on_listen = on_listen
method on_connect = on_connect
method on_datagram_socket = on_datagram_socket
method on_getaddrinfo = on_getaddrinfo
method on_getnameinfo = on_getnameinfo

method listen ~reuse_addr:_ ~reuse_port:_ ~backlog:_ ~sw addr =
traceln "%s: listen on %a" label Eio.Net.Sockaddr.pp addr;
Expand All @@ -42,6 +45,10 @@ let make label =
method getaddrinfo ~service node =
traceln "%s: getaddrinfo ~service:%s %s" label service node;
Handler.run on_getaddrinfo

method getnameinfo sockaddr =
traceln "%s: getnameinfo %a" label Eio.Net.Sockaddr.pp sockaddr;
Handler.run on_getnameinfo
end

let on_connect (t:t) actions =
Expand All @@ -58,6 +65,8 @@ let on_datagram_socket (t:t) actions =

let on_getaddrinfo (t:t) actions = Handler.seq t#on_getaddrinfo actions

let on_getnameinfo (t:t) actions = Handler.seq t#on_getnameinfo actions

type listening_socket = <
Eio.Net.listening_socket;
on_accept : (Flow.t * Eio.Net.Sockaddr.stream) Handler.t;
Expand Down
3 changes: 3 additions & 0 deletions lib_eio/net.ml
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ class virtual t = object
method virtual connect : sw:Switch.t -> Sockaddr.stream -> <stream_socket; Flow.close>
method virtual datagram_socket : sw:Switch.t -> Sockaddr.datagram -> <datagram_socket; Flow.close>
method virtual getaddrinfo : service:string -> string -> Sockaddr.t list
method virtual getnameinfo : Sockaddr.t -> (string * string)
end

let listen ?(reuse_addr=false) ?(reuse_port=false) ~backlog ~sw (t:#t) = t#listen ~reuse_addr ~reuse_port ~backlog ~sw
Expand All @@ -190,4 +191,6 @@ let datagram_socket ~sw (t:#t) = t#datagram_socket ~sw

let getaddrinfo ?(service="") (t:#t) hostname = t#getaddrinfo ~service hostname

let getnameinfo (t:#t) sockaddr = t#getnameinfo sockaddr

let close = Flow.close
6 changes: 6 additions & 0 deletions lib_eio/net.mli
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ class virtual t : object
method virtual connect : sw:Switch.t -> Sockaddr.stream -> <stream_socket; Flow.close>
method virtual datagram_socket : sw:Switch.t -> Sockaddr.datagram -> <datagram_socket; Flow.close>
method virtual getaddrinfo : service:string -> string -> Sockaddr.t list
method virtual getnameinfo : Sockaddr.t -> (string * string)
end

(** {2 Out-bound Connections} *)
Expand Down Expand Up @@ -183,6 +184,11 @@ val getaddrinfo: ?service:string -> #t -> string -> Sockaddr.t list
For a more thorough treatment, @see <https://man7.org/linux/man-pages/man3/getaddrinfo.3.html> getaddrinfo *)

val getnameinfo : #t -> Sockaddr.t -> (string * string)
(** [getnameinfo t sockaddr] is [(hostname, service)] corresponding to [sockaddr]. [hostname] is the
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 Closing} *)
val close : <close: unit; ..> -> unit
(** [close t] marks the socket as closed. It can no longer be used after this. *)
11 changes: 11 additions & 0 deletions lib_eio/unix/eio_unix.ml
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,14 @@ module Ipaddr = struct
end

module Ctf = Ctf_unix

let getnameinfo (sockaddr : Eio.Net.Sockaddr.t) =
let sockaddr, options =
match sockaddr with
| `Unix s -> (Unix.ADDR_UNIX s, [])
| `Tcp (addr, port) -> (Unix.ADDR_INET (Ipaddr.to_unix addr, port), [])
| `Udp (addr, port) -> (Unix.ADDR_INET (Ipaddr.to_unix addr, port), [Unix.NI_DGRAM])
in
run_in_systhread (fun () ->
let Unix.{ni_hostname; ni_service} = Unix.getnameinfo sockaddr options in
(ni_hostname, ni_service))
3 changes: 3 additions & 0 deletions lib_eio/unix/eio_unix.mli
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,6 @@ module Private : sig
end

module Ctf = Ctf_unix

val getnameinfo : Eio.Net.Sockaddr.t -> (string * string)
(** [getnameinfo sockaddr] returns domain name and service for [sockaddr]. *)
4 changes: 3 additions & 1 deletion lib_eio_linux/eio_linux.ml
Original file line number Diff line number Diff line change
Expand Up @@ -908,7 +908,7 @@ module Low_level = struct
in
Eio_unix.run_in_systhread @@ fun () ->
Unix.getaddrinfo node service []
|> List.filter_map to_eio_sockaddr_t
|> List.filter_map to_eio_sockaddr_t
end

external eio_eventfd : int -> Unix.file_descr = "caml_eio_eventfd"
Expand Down Expand Up @@ -1139,6 +1139,8 @@ let net = object
udp_socket sock

method getaddrinfo = Low_level.getaddrinfo

method getnameinfo = Eio_unix.getnameinfo
end

type stdenv = <
Expand Down
1 change: 0 additions & 1 deletion lib_eio_linux/eio_linux.mli
Original file line number Diff line number Diff line change
Expand Up @@ -253,5 +253,4 @@ module Low_level : sig
val getaddrinfo : service:string -> string -> Eio.Net.Sockaddr.t list
(** [getaddrinfo host] returns a list of IP addresses for [host]. [host] is either a domain name or
an ipaddress. *)

end
25 changes: 13 additions & 12 deletions lib_eio_luv/eio_luv.ml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,17 @@ let get_loop () =
enter_unchecked @@ fun t k ->
Suspended.continue k t.loop

let luv_addr_of_eio host port =
let host = Unix.string_of_inet_addr (Eio_unix.Ipaddr.to_unix host) in
match Luv.Sockaddr.ipv6 host port with
| Ok addr -> addr
| Error _ -> Luv.Sockaddr.ipv4 host port |> or_raise

let luv_ip_addr_to_eio addr =
let host = Luv.Sockaddr.to_string addr |> Option.get in
let port = Luv.Sockaddr.port addr |> Option.get in
(Eio_unix.Ipaddr.of_unix (Unix.inet_addr_of_string host), port)

module Low_level = struct
type 'a or_error = ('a, Luv.Error.t) result

Expand Down Expand Up @@ -428,7 +439,6 @@ module Low_level = struct
await_with_cancel ~request (fun loop -> Luv.DNS.getaddrinfo ~loop ~request ~service ~node ())
|> or_raise
|> List.filter_map to_eio_sockaddr_t

end

open Low_level
Expand Down Expand Up @@ -549,17 +559,6 @@ end
let luv_reuse_addr _sock _v = ()
let luv_reuse_port _sock _v = ()

let luv_addr_of_eio host port =
let host = Unix.string_of_inet_addr (Eio_unix.Ipaddr.to_unix host) in
match Luv.Sockaddr.ipv6 host port with
| Ok addr -> addr
| Error _ -> Luv.Sockaddr.ipv4 host port |> or_raise

let luv_ip_addr_to_eio addr =
let host = Luv.Sockaddr.to_string addr |> Option.get in
let port = Luv.Sockaddr.port addr |> Option.get in
(Eio_unix.Ipaddr.of_unix (Unix.inet_addr_of_string host), port)

module Udp = struct
type 'a t = [`UDP] Handle.t

Expand Down Expand Up @@ -671,6 +670,8 @@ let net = object
udp_socket dg_sock

method getaddrinfo = Low_level.getaddrinfo

method getnameinfo = Eio_unix.getnameinfo
end

let secure_random =
Expand Down
9 changes: 9 additions & 0 deletions tests/network.md
Original file line number Diff line number Diff line change
Expand Up @@ -527,3 +527,12 @@ EPIPE:
`Tcp ("*\000\020P@\t\b \000\000\000\000\000\000 \014", 443);
`Udp ("*\000\020P@\t\b \000\000\000\000\000\000 \014", 443)]
```

## getnameinfo

```ocaml
# Eio_main.run @@ fun env ->
let sockaddr = `Tcp (Eio.Net.Ipaddr.V4.loopback, 80) in
Eio.Net.getnameinfo env#net sockaddr;;
- : string * string = ("localhost", "http")
```

0 comments on commit 104f379

Please sign in to comment.