Skip to content

Commit 5c5598a

Browse files
committed
Add support for setting/getting socket options
This adds a Eio.Net.Sockopt.t extensible variant where portable options are exposed, and backend-specific sockopts for Unix and Linux. Windows can be added later, but is not part of this commit. Reviewed-by: Thomas Leonard <[email protected]>
1 parent 7695d22 commit 5c5598a

File tree

19 files changed

+735
-3
lines changed

19 files changed

+735
-3
lines changed

lib_eio/mock/flow.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ module Mock_flow = struct
108108
done;
109109
traceln "%s: closed" t.label
110110

111+
let setsockopt t opt v = Sockopt.setsockopt t.label opt v
112+
let getsockopt t opt = Sockopt.getsockopt t.label opt
113+
111114
let make ?(pp=pp_default) label =
112115
{
113116
pp;

lib_eio/mock/net.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ module Listening_socket = struct
123123

124124
let listening_addr { listening_addr; _ } = listening_addr
125125

126+
let setsockopt t opt v = Sockopt.setsockopt t.label opt v
127+
let getsockopt t opt = Sockopt.getsockopt t.label opt
128+
126129
type (_, _, _) Eio.Resource.pi += Type : ('t, 't -> t, listening_socket_ty) Eio.Resource.pi
127130
let raw (Eio.Resource.T (t, ops)) = Eio.Resource.get ops Type t
128131
end

lib_eio/mock/sockopt.ml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
open Eio.Std
2+
3+
let pp_sockopt_value : type a. a Eio.Net.Sockopt.t -> a -> string = fun opt v ->
4+
match opt with
5+
| Eio.Net.Sockopt.SO_DEBUG -> Fmt.str "SO_DEBUG = %b" v
6+
| Eio.Net.Sockopt.SO_BROADCAST -> Fmt.str "SO_BROADCAST = %b" v
7+
| Eio.Net.Sockopt.SO_REUSEADDR -> Fmt.str "SO_REUSEADDR = %b" v
8+
| Eio.Net.Sockopt.SO_KEEPALIVE -> Fmt.str "SO_KEEPALIVE = %b" v
9+
| Eio.Net.Sockopt.SO_DONTROUTE -> Fmt.str "SO_DONTROUTE = %b" v
10+
| Eio.Net.Sockopt.SO_OOBINLINE -> Fmt.str "SO_OOBINLINE = %b" v
11+
| Eio.Net.Sockopt.TCP_NODELAY -> Fmt.str "TCP_NODELAY = %b" v
12+
| Eio.Net.Sockopt.IPV6_ONLY -> Fmt.str "IPV6_ONLY = %b" v
13+
| Eio.Net.Sockopt.SO_REUSEPORT -> Fmt.str "SO_REUSEPORT = %b" v
14+
| Eio.Net.Sockopt.SO_SNDBUF -> Fmt.str "SO_SNDBUF = %d" v
15+
| Eio.Net.Sockopt.SO_RCVBUF -> Fmt.str "SO_RCVBUF = %d" v
16+
| Eio.Net.Sockopt.SO_TYPE -> Fmt.str "SO_TYPE = %d" v
17+
| Eio.Net.Sockopt.SO_RCVLOWAT -> Fmt.str "SO_RCVLOWAT = %d" v
18+
| Eio.Net.Sockopt.SO_SNDLOWAT -> Fmt.str "SO_SNDLOWAT = %d" v
19+
| Eio.Net.Sockopt.SO_LINGER -> Fmt.str "SO_LINGER = %s" (match v with None -> "None" | Some n -> string_of_int n)
20+
| Eio.Net.Sockopt.SO_RCVTIMEO -> Fmt.str "SO_RCVTIMEO = %f" v
21+
| Eio.Net.Sockopt.SO_SNDTIMEO -> Fmt.str "SO_SNDTIMEO = %f" v
22+
| _ -> "unknown"
23+
24+
let setsockopt : type a. string -> a Eio.Net.Sockopt.t -> a -> unit = fun label opt v ->
25+
let opt_desc = pp_sockopt_value opt v in
26+
traceln "%s: setsockopt %s" label opt_desc
27+
28+
let getsockopt : type a. string -> a Eio.Net.Sockopt.t -> a = fun label opt ->
29+
match opt with
30+
| Eio.Net.Sockopt.SO_DEBUG -> traceln "%s: getsockopt SO_DEBUG = false" label; false
31+
| Eio.Net.Sockopt.SO_BROADCAST -> traceln "%s: getsockopt SO_BROADCAST = false" label; false
32+
| Eio.Net.Sockopt.SO_REUSEADDR -> traceln "%s: getsockopt SO_REUSEADDR = false" label; false
33+
| Eio.Net.Sockopt.SO_KEEPALIVE -> traceln "%s: getsockopt SO_KEEPALIVE = false" label; false
34+
| Eio.Net.Sockopt.SO_DONTROUTE -> traceln "%s: getsockopt SO_DONTROUTE = false" label; false
35+
| Eio.Net.Sockopt.SO_OOBINLINE -> traceln "%s: getsockopt SO_OOBINLINE = false" label; false
36+
| Eio.Net.Sockopt.TCP_NODELAY -> traceln "%s: getsockopt TCP_NODELAY = false" label; false
37+
| Eio.Net.Sockopt.IPV6_ONLY -> traceln "%s: getsockopt IPV6_ONLY = false" label; false
38+
| Eio.Net.Sockopt.SO_REUSEPORT -> traceln "%s: getsockopt SO_REUSEPORT = false" label; false
39+
| Eio.Net.Sockopt.SO_SNDBUF -> traceln "%s: getsockopt SO_SNDBUF = 0" label; 0
40+
| Eio.Net.Sockopt.SO_RCVBUF -> traceln "%s: getsockopt SO_RCVBUF = 0" label; 0
41+
| Eio.Net.Sockopt.SO_TYPE -> traceln "%s: getsockopt SO_TYPE = 0" label; 0
42+
| Eio.Net.Sockopt.SO_RCVLOWAT -> traceln "%s: getsockopt SO_RCVLOWAT = 0" label; 0
43+
| Eio.Net.Sockopt.SO_SNDLOWAT -> traceln "%s: getsockopt SO_SNDLOWAT = 0" label; 0
44+
| Eio.Net.Sockopt.SO_LINGER -> traceln "%s: getsockopt SO_LINGER = None" label; None
45+
| Eio.Net.Sockopt.SO_RCVTIMEO -> traceln "%s: getsockopt SO_RCVTIMEO = 0.0" label; 0.0
46+
| Eio.Net.Sockopt.SO_SNDTIMEO -> traceln "%s: getsockopt SO_SNDTIMEO = 0.0" label; 0.0
47+
| _ -> raise (Failure "Mock getsockopt not implemented")

lib_eio/mock/sockopt.mli

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
(** Mock socket option helpers *)
2+
3+
val pp_sockopt_value : 'a Eio.Net.Sockopt.t -> 'a -> string
4+
(** [pp_sockopt_value opt v] formats socket option [opt] with value [v] as a string
5+
for trace output. Returns [unknown] for unrecognised options. *)
6+
7+
val setsockopt : string -> 'a Eio.Net.Sockopt.t -> 'a -> unit
8+
(** [setsockopt label opt v] simulates setting socket option [opt] to value [v].
9+
Outputs a trace message using [label] to identify the socket. *)
10+
11+
val getsockopt : string -> 'a Eio.Net.Sockopt.t -> 'a
12+
(** [getsockopt label opt] simulates getting the value of socket option [opt].
13+
Outputs a trace message using [label] to identify the socket.
14+
Returns default mock values for all standard options.
15+
16+
Default values:
17+
- Boolean options: [false]
18+
- Integer options: [0]
19+
- Timeout options: [0.0]
20+
21+
@raise Failure if the option is not recognized. *)

lib_eio/net.ml

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,29 @@ module Sockaddr = struct
159159
Format.fprintf f "udp:%a:%d" Ipaddr.pp_for_uri addr port
160160
end
161161

162+
module Sockopt = struct
163+
type _ t = ..
164+
165+
type _ t +=
166+
| SO_DEBUG : bool t
167+
| SO_BROADCAST : bool t
168+
| SO_REUSEADDR : bool t
169+
| SO_KEEPALIVE : bool t
170+
| SO_DONTROUTE : bool t
171+
| SO_OOBINLINE : bool t
172+
| TCP_NODELAY : bool t
173+
| IPV6_ONLY : bool t
174+
| SO_REUSEPORT : bool t
175+
| SO_SNDBUF : int t
176+
| SO_RCVBUF : int t
177+
| SO_TYPE : int t
178+
| SO_RCVLOWAT : int t
179+
| SO_SNDLOWAT : int t
180+
| SO_LINGER : int option t
181+
| SO_RCVTIMEO : float t
182+
| SO_SNDTIMEO : float t
183+
end
184+
162185
type socket_ty = [`Socket | `Close]
163186
type 'a socket = ([> socket_ty] as 'a) r
164187

@@ -181,22 +204,34 @@ type 'a t = 'a r
181204
constraint 'a = [> [> `Generic] ty]
182205

183206
module Pi = struct
207+
module type SOCKET = sig
208+
type t
209+
val setsockopt : t -> 'a Sockopt.t -> 'a -> unit
210+
val getsockopt : t -> 'a Sockopt.t -> 'a
211+
end
212+
213+
type (_, _, _) Resource.pi +=
214+
| Socket : ('t, (module SOCKET with type t = 't), [> `Socket]) Resource.pi
215+
184216
module type STREAM_SOCKET = sig
185217
type tag
186218
include Flow.Pi.SHUTDOWN
187219
include Flow.Pi.SOURCE with type t := t
188220
include Flow.Pi.SINK with type t := t
221+
include SOCKET with type t := t
189222
val close : t -> unit
190223
end
191224

192225
let stream_socket (type t tag) (module X : STREAM_SOCKET with type t = t and type tag = tag) =
193226
Resource.handler @@
194227
H (Resource.Close, X.close) ::
228+
H (Socket, (module X)) ::
195229
Resource.bindings (Flow.Pi.two_way (module X))
196230

197231
module type DATAGRAM_SOCKET = sig
198232
type tag
199233
include Flow.Pi.SHUTDOWN
234+
include SOCKET with type t := t
200235
val send : t -> ?dst:Sockaddr.datagram -> Cstruct.t list -> unit
201236
val recv : t -> Cstruct.t -> Sockaddr.datagram * int
202237
val close : t -> unit
@@ -208,14 +243,15 @@ module Pi = struct
208243
let datagram_socket (type t tag) (module X : DATAGRAM_SOCKET with type t = t and type tag = tag) =
209244
Resource.handler @@
210245
Resource.bindings (Flow.Pi.shutdown (module X)) @ [
246+
H (Socket, (module X));
211247
H (Datagram_socket, (module X));
212248
H (Resource.Close, X.close)
213249
]
214250

215251
module type LISTENING_SOCKET = sig
216252
type t
217253
type tag
218-
254+
include SOCKET with type t := t
219255
val accept : t -> sw:Switch.t -> tag stream_socket_ty r * Sockaddr.stream
220256
val close : t -> unit
221257
val listening_addr : t -> Sockaddr.stream
@@ -227,6 +263,7 @@ module Pi = struct
227263
let listening_socket (type t tag) (module X : LISTENING_SOCKET with type t = t and type tag = tag) =
228264
Resource.handler [
229265
H (Resource.Close, X.close);
266+
H (Socket, (module X));
230267
H (Listening_socket, (module X))
231268
]
232269

@@ -278,6 +315,14 @@ let accept_fork ~sw (t : [> 'a listening_socket_ty] r) ~on_error handle =
278315
)
279316
)
280317

318+
let setsockopt (Resource.T (t, ops)) opt v =
319+
let module X = (val (Resource.get ops Pi.Socket)) in
320+
X.setsockopt t opt v
321+
322+
let getsockopt (Resource.T (t, ops)) opt =
323+
let module X = (val (Resource.get ops Pi.Socket)) in
324+
X.getsockopt t opt
325+
281326
let listening_addr (type tag) (Resource.T (t, ops) : [> tag listening_socket_ty] r) =
282327
let module X = (val (Resource.get ops Pi.Listening_socket)) in
283328
X.listening_addr t

lib_eio/net.mli

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,33 @@ module Sockaddr : sig
102102
val pp : Format.formatter -> [< t] -> unit
103103
end
104104

105+
(** Socket options. *)
106+
module Sockopt : sig
107+
(** An extensible type for socket options. Portable options can be defined
108+
here, while platform-specific options can be added by backends. *)
109+
110+
type _ t = ..
111+
112+
type _ t +=
113+
| SO_DEBUG : bool t (** Enable socket debugging *)
114+
| SO_BROADCAST : bool t (** Permit sending of broadcast messages *)
115+
| SO_REUSEADDR : bool t (** Allow reuse of local addresses *)
116+
| SO_KEEPALIVE : bool t (** Keep TCP connection alive *)
117+
| SO_DONTROUTE : bool t (** Bypass routing tables *)
118+
| SO_OOBINLINE : bool t (** Leave out-of-band data in line *)
119+
| TCP_NODELAY : bool t (** Disable Nagle's algorithm *)
120+
| IPV6_ONLY : bool t (** Restrict to IPv6 only *)
121+
| SO_REUSEPORT : bool t (** Allow reuse of local port *)
122+
| SO_SNDBUF : int t (** Send buffer size *)
123+
| SO_RCVBUF : int t (** Receive buffer size *)
124+
| SO_TYPE : int t (** Socket type (get only) *)
125+
| SO_RCVLOWAT : int t (** Receive low water mark *)
126+
| SO_SNDLOWAT : int t (** Send low water mark *)
127+
| SO_LINGER : int option t (** Linger on close if data present *)
128+
| SO_RCVTIMEO : float t (** Receive timeout *)
129+
| SO_SNDTIMEO : float t (** Send timeout *)
130+
end
131+
105132
(** {2 Types} *)
106133

107134
type socket_ty = [`Socket | `Close]
@@ -127,6 +154,18 @@ type 'tag ty = [`Network | `Platform of 'tag]
127154
type 'a t = 'a r
128155
constraint 'a = [> [> `Generic] ty]
129156

157+
(** {2 Socket options} *)
158+
159+
val setsockopt : [> `Socket] r -> 'a Sockopt.t -> 'a -> unit
160+
(** [setsockopt s opt v] sets socket option [opt] to value [v] on socket [s].
161+
162+
@raise Invalid_argument if the socket option is not supported by the backend. *)
163+
164+
val getsockopt : [> `Socket] r -> 'a Sockopt.t -> 'a
165+
(** [getsockopt s opt] gets the value of socket option [opt] on socket [s].
166+
167+
@raise Invalid_argument if the socket option is not supported by the backend. *)
168+
130169
(** {2 Out-bound Connections} *)
131170

132171
val connect : sw:Switch.t -> [> 'tag ty] t -> Sockaddr.stream -> 'tag stream_socket_ty r
@@ -304,11 +343,18 @@ val close : [> `Close] r -> unit
304343
(** {2 Provider Interface} *)
305344

306345
module Pi : sig
346+
module type SOCKET = sig
347+
type t
348+
val setsockopt : t -> 'a Sockopt.t -> 'a -> unit
349+
val getsockopt : t -> 'a Sockopt.t -> 'a
350+
end
351+
307352
module type STREAM_SOCKET = sig
308353
type tag
309354
include Flow.Pi.SHUTDOWN
310355
include Flow.Pi.SOURCE with type t := t
311356
include Flow.Pi.SINK with type t := t
357+
include SOCKET with type t := t
312358
val close : t -> unit
313359
end
314360

@@ -319,6 +365,7 @@ module Pi : sig
319365
module type DATAGRAM_SOCKET = sig
320366
type tag
321367
include Flow.Pi.SHUTDOWN
368+
include SOCKET with type t := t
322369
val send : t -> ?dst:Sockaddr.datagram -> Cstruct.t list -> unit
323370
val recv : t -> Cstruct.t -> Sockaddr.datagram * int
324371
val close : t -> unit
@@ -331,7 +378,7 @@ module Pi : sig
331378
module type LISTENING_SOCKET = sig
332379
type t
333380
type tag
334-
381+
include SOCKET with type t := t
335382
val accept : t -> sw:Switch.t -> tag stream_socket_ty r * Sockaddr.stream
336383
val close : t -> unit
337384
val listening_addr : t -> Sockaddr.stream

lib_eio/unix/net.ml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,65 @@ let socketpair_datagram ~sw ?(domain=Unix.PF_UNIX) ?(protocol=0) () =
9191

9292
let fd socket =
9393
Option.get (Resource.fd_opt socket)
94+
95+
module Sockopt = struct
96+
type _ Eio.Net.Sockopt.t +=
97+
| Unix_bool : Unix.socket_bool_option -> bool Eio.Net.Sockopt.t
98+
| Unix_int : Unix.socket_int_option -> int Eio.Net.Sockopt.t
99+
| Unix_optint : Unix.socket_optint_option -> int option Eio.Net.Sockopt.t
100+
| Unix_float : Unix.socket_float_option -> float Eio.Net.Sockopt.t
101+
102+
let set : type a. Fd.t -> a Eio.Net.Sockopt.t -> a -> unit = fun fd opt v ->
103+
Fd.use_exn "setsockopt" fd @@ fun fd ->
104+
match opt with
105+
| Eio.Net.Sockopt.SO_DEBUG -> Unix.setsockopt fd Unix.SO_DEBUG v
106+
| Eio.Net.Sockopt.SO_BROADCAST -> Unix.setsockopt fd Unix.SO_BROADCAST v
107+
| Eio.Net.Sockopt.SO_REUSEADDR -> Unix.setsockopt fd Unix.SO_REUSEADDR v
108+
| Eio.Net.Sockopt.SO_KEEPALIVE -> Unix.setsockopt fd Unix.SO_KEEPALIVE v
109+
| Eio.Net.Sockopt.SO_DONTROUTE -> Unix.setsockopt fd Unix.SO_DONTROUTE v
110+
| Eio.Net.Sockopt.SO_OOBINLINE -> Unix.setsockopt fd Unix.SO_OOBINLINE v
111+
| Eio.Net.Sockopt.TCP_NODELAY -> Unix.setsockopt fd Unix.TCP_NODELAY v
112+
| Eio.Net.Sockopt.IPV6_ONLY -> Unix.setsockopt fd Unix.IPV6_ONLY v
113+
| Eio.Net.Sockopt.SO_REUSEPORT -> Unix.setsockopt fd Unix.SO_REUSEPORT v
114+
| Eio.Net.Sockopt.SO_SNDBUF -> Unix.setsockopt_int fd Unix.SO_SNDBUF v
115+
| Eio.Net.Sockopt.SO_RCVBUF -> Unix.setsockopt_int fd Unix.SO_RCVBUF v
116+
| Eio.Net.Sockopt.SO_TYPE -> invalid_arg "SO_TYPE is read-only"
117+
| Eio.Net.Sockopt.SO_RCVLOWAT -> Unix.setsockopt_int fd Unix.SO_RCVLOWAT v
118+
| Eio.Net.Sockopt.SO_SNDLOWAT -> Unix.setsockopt_int fd Unix.SO_SNDLOWAT v
119+
| Eio.Net.Sockopt.SO_LINGER -> Unix.setsockopt_optint fd Unix.SO_LINGER v
120+
| Eio.Net.Sockopt.SO_RCVTIMEO -> Unix.setsockopt_float fd Unix.SO_RCVTIMEO v
121+
| Eio.Net.Sockopt.SO_SNDTIMEO -> Unix.setsockopt_float fd Unix.SO_SNDTIMEO v
122+
| Unix_bool bo -> Unix.setsockopt fd bo v
123+
| Unix_int bo -> Unix.setsockopt_int fd bo v
124+
| Unix_optint bo -> Unix.setsockopt_optint fd bo v
125+
| Unix_float bo -> Unix.setsockopt_float fd bo v
126+
| _ -> raise (Invalid_argument "Unsupported socket option")
127+
128+
let get_descr : type a. Unix.file_descr -> a Eio.Net.Sockopt.t -> a = fun fd opt ->
129+
match opt with
130+
| Eio.Net.Sockopt.SO_DEBUG -> Unix.getsockopt fd Unix.SO_DEBUG
131+
| Eio.Net.Sockopt.SO_BROADCAST -> Unix.getsockopt fd Unix.SO_BROADCAST
132+
| Eio.Net.Sockopt.SO_REUSEADDR -> Unix.getsockopt fd Unix.SO_REUSEADDR
133+
| Eio.Net.Sockopt.SO_KEEPALIVE -> Unix.getsockopt fd Unix.SO_KEEPALIVE
134+
| Eio.Net.Sockopt.SO_DONTROUTE -> Unix.getsockopt fd Unix.SO_DONTROUTE
135+
| Eio.Net.Sockopt.SO_OOBINLINE -> Unix.getsockopt fd Unix.SO_OOBINLINE
136+
| Eio.Net.Sockopt.TCP_NODELAY -> Unix.getsockopt fd Unix.TCP_NODELAY
137+
| Eio.Net.Sockopt.IPV6_ONLY -> Unix.getsockopt fd Unix.IPV6_ONLY
138+
| Eio.Net.Sockopt.SO_REUSEPORT -> Unix.getsockopt fd Unix.SO_REUSEPORT
139+
| Eio.Net.Sockopt.SO_SNDBUF -> Unix.getsockopt_int fd Unix.SO_SNDBUF
140+
| Eio.Net.Sockopt.SO_RCVBUF -> Unix.getsockopt_int fd Unix.SO_RCVBUF
141+
| Eio.Net.Sockopt.SO_TYPE -> Unix.getsockopt_int fd Unix.SO_TYPE
142+
| Eio.Net.Sockopt.SO_RCVLOWAT -> Unix.getsockopt_int fd Unix.SO_RCVLOWAT
143+
| Eio.Net.Sockopt.SO_SNDLOWAT -> Unix.getsockopt_int fd Unix.SO_SNDLOWAT
144+
| Eio.Net.Sockopt.SO_LINGER -> Unix.getsockopt_optint fd Unix.SO_LINGER
145+
| Eio.Net.Sockopt.SO_RCVTIMEO -> Unix.getsockopt_float fd Unix.SO_RCVTIMEO
146+
| Eio.Net.Sockopt.SO_SNDTIMEO -> Unix.getsockopt_float fd Unix.SO_SNDTIMEO
147+
| Unix_bool bo -> Unix.getsockopt fd bo
148+
| Unix_int bo -> Unix.getsockopt_int fd bo
149+
| Unix_optint bo -> Unix.getsockopt_optint fd bo
150+
| Unix_float bo -> Unix.getsockopt_float fd bo
151+
| _ -> raise (Invalid_argument "Unsupported socket option")
152+
153+
let get : type a. Fd.t -> a Eio.Net.Sockopt.t -> a = fun fd opt ->
154+
Fd.use_exn "getsockopt" fd @@ fun fd -> get_descr fd opt
155+
end

lib_eio/unix/net.mli

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,47 @@ val socketpair_datagram :
9999
This creates OS-level resources using [socketpair(2)].
100100
Note that, like all FDs created by Eio, they are both marked as close-on-exec by default. *)
101101

102+
(** Socket options *)
103+
module Sockopt : sig
104+
(** Unix-specific socket options.
105+
106+
This module extends {!Eio.Net.Sockopt} with support for any Unix socket option. *)
107+
108+
(** Generic wrappers for Unix socket options *)
109+
type _ Eio.Net.Sockopt.t +=
110+
| Unix_bool : Unix.socket_bool_option -> bool Eio.Net.Sockopt.t
111+
(** Wrap any Unix boolean socket option *)
112+
| Unix_int : Unix.socket_int_option -> int Eio.Net.Sockopt.t
113+
(** Wrap any Unix integer socket option *)
114+
| Unix_optint : Unix.socket_optint_option -> int option Eio.Net.Sockopt.t
115+
(** Wrap any Unix optional integer socket option *)
116+
| Unix_float : Unix.socket_float_option -> float Eio.Net.Sockopt.t
117+
(** Wrap any Unix float socket option *)
118+
119+
val set : Fd.t -> 'a Eio.Net.Sockopt.t -> 'a -> unit
120+
(** [set fd opt v] sets socket option [opt] to value [v] on file descriptor [fd].
121+
122+
Supports both portable options from {!Eio.Net.Sockopt} and Unix-specific options
123+
wrapped with [Unix_bool], [Unix_int], [Unix_optint], or [Unix_float].
124+
125+
Example:
126+
{[
127+
(* Using portable options *)
128+
Eio.Net.setsockopt sock Eio.Net.Sockopt.SO_KEEPALIVE true;
129+
130+
(* Using Unix-specific options *)
131+
let fd = Eio_unix.Net.fd sock in
132+
Eio_unix.Net.Sockopt.set fd (Unix_int Unix.SO_SNDBUF) 65536;
133+
Eio_unix.Net.Sockopt.set fd (Unix_optint Unix.SO_LINGER) (Some 10);
134+
]} *)
135+
136+
val get : Fd.t -> 'a Eio.Net.Sockopt.t -> 'a
137+
(** [get fd opt] gets the value of socket option [opt] on file descriptor [fd].
138+
139+
Supports both portable options from {!Eio.Net.Sockopt} and Unix-specific options
140+
wrapped with [Unix_bool], [Unix_int], [Unix_optint], or [Unix_float]. *)
141+
end
142+
102143
(** {2 Private API for backends} *)
103144

104145
val getnameinfo : Eio.Net.Sockaddr.t -> (string * string)

0 commit comments

Comments
 (0)