-
Notifications
You must be signed in to change notification settings - Fork 77
add Eio_unix.Sockopt for setting/getting socket options #575
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,47 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
open Eio.Std | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let pp_sockopt_value : type a. a Eio.Net.Sockopt.t -> a -> string = fun opt v -> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
match opt with | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_DEBUG -> Fmt.str "SO_DEBUG = %b" v | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_BROADCAST -> Fmt.str "SO_BROADCAST = %b" v | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_REUSEADDR -> Fmt.str "SO_REUSEADDR = %b" v | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_KEEPALIVE -> Fmt.str "SO_KEEPALIVE = %b" v | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_DONTROUTE -> Fmt.str "SO_DONTROUTE = %b" v | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_OOBINLINE -> Fmt.str "SO_OOBINLINE = %b" v | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.TCP_NODELAY -> Fmt.str "TCP_NODELAY = %b" v | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.IPV6_ONLY -> Fmt.str "IPV6_ONLY = %b" v | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_REUSEPORT -> Fmt.str "SO_REUSEPORT = %b" v | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_SNDBUF -> Fmt.str "SO_SNDBUF = %d" v | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_RCVBUF -> Fmt.str "SO_RCVBUF = %d" v | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_TYPE -> Fmt.str "SO_TYPE = %d" v | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_RCVLOWAT -> Fmt.str "SO_RCVLOWAT = %d" v | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_SNDLOWAT -> Fmt.str "SO_SNDLOWAT = %d" v | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_LINGER -> Fmt.str "SO_LINGER = %s" (match v with None -> "None" | Some n -> string_of_int n) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_RCVTIMEO -> Fmt.str "SO_RCVTIMEO = %f" v | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_SNDTIMEO -> Fmt.str "SO_SNDTIMEO = %f" v | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _ -> "unknown" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let setsockopt : type a. string -> a Eio.Net.Sockopt.t -> a -> unit = fun label opt v -> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let opt_desc = pp_sockopt_value opt v in | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
traceln "%s: setsockopt %s" label opt_desc | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+24
to
+26
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Then this is just:
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let getsockopt : type a. string -> a Eio.Net.Sockopt.t -> a = fun label opt -> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
match opt with | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_DEBUG -> traceln "%s: getsockopt SO_DEBUG = false" label; false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_BROADCAST -> traceln "%s: getsockopt SO_BROADCAST = false" label; false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_REUSEADDR -> traceln "%s: getsockopt SO_REUSEADDR = false" label; false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_KEEPALIVE -> traceln "%s: getsockopt SO_KEEPALIVE = false" label; false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_DONTROUTE -> traceln "%s: getsockopt SO_DONTROUTE = false" label; false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_OOBINLINE -> traceln "%s: getsockopt SO_OOBINLINE = false" label; false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.TCP_NODELAY -> traceln "%s: getsockopt TCP_NODELAY = false" label; false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.IPV6_ONLY -> traceln "%s: getsockopt IPV6_ONLY = false" label; false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_REUSEPORT -> traceln "%s: getsockopt SO_REUSEPORT = false" label; false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_SNDBUF -> traceln "%s: getsockopt SO_SNDBUF = 0" label; 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_RCVBUF -> traceln "%s: getsockopt SO_RCVBUF = 0" label; 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_TYPE -> traceln "%s: getsockopt SO_TYPE = 0" label; 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_RCVLOWAT -> traceln "%s: getsockopt SO_RCVLOWAT = 0" label; 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_SNDLOWAT -> traceln "%s: getsockopt SO_SNDLOWAT = 0" label; 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_LINGER -> traceln "%s: getsockopt SO_LINGER = None" label; None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_RCVTIMEO -> traceln "%s: getsockopt SO_RCVTIMEO = 0.0" label; 0.0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Eio.Net.Sockopt.SO_SNDTIMEO -> traceln "%s: getsockopt SO_SNDTIMEO = 0.0" label; 0.0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _ -> raise (Failure "Mock getsockopt not implemented") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+28
to
+47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems a shame not to reuse the printer from above:
Suggested change
(though not 100% sure it's useful to log gets... might be a bit noisy) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
(** Mock socket option helpers *) | ||
|
||
val pp_sockopt_value : 'a Eio.Net.Sockopt.t -> 'a -> string | ||
(** [pp_sockopt_value opt v] formats socket option [opt] with value [v] as a string | ||
for trace output. Returns [unknown] for unrecognised options. *) | ||
|
||
val setsockopt : string -> 'a Eio.Net.Sockopt.t -> 'a -> unit | ||
(** [setsockopt label opt v] simulates setting socket option [opt] to value [v]. | ||
Outputs a trace message using [label] to identify the socket. *) | ||
|
||
val getsockopt : string -> 'a Eio.Net.Sockopt.t -> 'a | ||
(** [getsockopt label opt] simulates getting the value of socket option [opt]. | ||
Outputs a trace message using [label] to identify the socket. | ||
Returns default mock values for all standard options. | ||
|
||
Default values: | ||
- Boolean options: [false] | ||
- Integer options: [0] | ||
- Timeout options: [0.0] | ||
|
||
@raise Failure if the option is not recognized. *) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -102,6 +102,33 @@ module Sockaddr : sig | |
val pp : Format.formatter -> [< t] -> unit | ||
end | ||
|
||
(** Socket options. *) | ||
module Sockopt : sig | ||
(** An extensible type for socket options. Portable options can be defined | ||
here, while platform-specific options can be added by backends. *) | ||
|
||
type _ t = .. | ||
|
||
type _ t += | ||
| SO_DEBUG : bool t (** Enable socket debugging *) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you mean separate the socket options fro the TCP/IP level options? Seems easier to just keep the types corresponding to the names of the sockopts themselves as they're well known. |
||
| SO_BROADCAST : bool t (** Permit sending of broadcast messages *) | ||
| SO_REUSEADDR : bool t (** Allow reuse of local addresses *) | ||
| SO_KEEPALIVE : bool t (** Keep TCP connection alive *) | ||
| SO_DONTROUTE : bool t (** Bypass routing tables *) | ||
| SO_OOBINLINE : bool t (** Leave out-of-band data in line *) | ||
| TCP_NODELAY : bool t (** Disable Nagle's algorithm *) | ||
| IPV6_ONLY : bool t (** Restrict to IPv6 only *) | ||
| SO_REUSEPORT : bool t (** Allow reuse of local port *) | ||
| SO_SNDBUF : int t (** Send buffer size *) | ||
| SO_RCVBUF : int t (** Receive buffer size *) | ||
| SO_TYPE : int t (** Socket type (get only) *) | ||
| SO_RCVLOWAT : int t (** Receive low water mark *) | ||
| SO_SNDLOWAT : int t (** Send low water mark *) | ||
| SO_LINGER : int option t (** Linger on close if data present *) | ||
| SO_RCVTIMEO : float t (** Receive timeout *) | ||
| SO_SNDTIMEO : float t (** Send timeout *) | ||
end | ||
|
||
(** {2 Types} *) | ||
|
||
type socket_ty = [`Socket | `Close] | ||
|
@@ -127,6 +154,18 @@ type 'tag ty = [`Network | `Platform of 'tag] | |
type 'a t = 'a r | ||
constraint 'a = [> [> `Generic] ty] | ||
|
||
(** {2 Socket options} *) | ||
|
||
val setsockopt : [> `Socket] r -> 'a Sockopt.t -> 'a -> unit | ||
(** [setsockopt s opt v] sets socket option [opt] to value [v] on socket [s]. | ||
|
||
@raise Invalid_argument if the socket option is not supported by the backend. *) | ||
|
||
val getsockopt : [> `Socket] r -> 'a Sockopt.t -> 'a | ||
(** [getsockopt s opt] gets the value of socket option [opt] on socket [s]. | ||
|
||
@raise Invalid_argument if the socket option is not supported by the backend. *) | ||
|
||
(** {2 Out-bound Connections} *) | ||
|
||
val connect : sw:Switch.t -> [> 'tag ty] t -> Sockaddr.stream -> 'tag stream_socket_ty r | ||
|
@@ -304,11 +343,18 @@ val close : [> `Close] r -> unit | |
(** {2 Provider Interface} *) | ||
|
||
module Pi : sig | ||
module type SOCKET = sig | ||
type t | ||
val setsockopt : t -> 'a Sockopt.t -> 'a -> unit | ||
val getsockopt : t -> 'a Sockopt.t -> 'a | ||
end | ||
|
||
module type STREAM_SOCKET = sig | ||
type tag | ||
include Flow.Pi.SHUTDOWN | ||
include Flow.Pi.SOURCE with type t := t | ||
include Flow.Pi.SINK with type t := t | ||
include SOCKET with type t := t | ||
val close : t -> unit | ||
end | ||
|
||
|
@@ -319,6 +365,7 @@ module Pi : sig | |
module type DATAGRAM_SOCKET = sig | ||
type tag | ||
include Flow.Pi.SHUTDOWN | ||
include SOCKET with type t := t | ||
val send : t -> ?dst:Sockaddr.datagram -> Cstruct.t list -> unit | ||
val recv : t -> Cstruct.t -> Sockaddr.datagram * int | ||
val close : t -> unit | ||
|
@@ -331,7 +378,7 @@ module Pi : sig | |
module type LISTENING_SOCKET = sig | ||
type t | ||
type tag | ||
|
||
include SOCKET with type t := t | ||
val accept : t -> sw:Switch.t -> tag stream_socket_ty r * Sockaddr.stream | ||
val close : t -> unit | ||
val listening_addr : t -> Sockaddr.stream | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be slightly simpler and more consistent to make this an actual pretty-printer, e.g.