@@ -22,22 +22,45 @@ pub struct TcpSocket {
22
22
sys : sys:: tcp:: TcpSocket ,
23
23
}
24
24
25
+ /// Configures a socket's TCP keepalive parameters.
26
+ #[ derive( Debug , Default , Clone ) ]
27
+ pub struct TcpKeepalive {
28
+ pub ( crate ) time : Option < Duration > ,
29
+ #[ cfg( any(
30
+ target_os = "linux" ,
31
+ target_os = "macos" ,
32
+ target_os = "ios" ,
33
+ target_os = "freebsd" ,
34
+ target_os = "netbsd" ,
35
+ target_os = "windows" ,
36
+ ) ) ]
37
+ pub ( crate ) interval : Option < Duration > ,
38
+ #[ cfg( any(
39
+ target_os = "linux" ,
40
+ target_os = "macos" ,
41
+ target_os = "ios" ,
42
+ target_os = "freebsd" ,
43
+ target_os = "netbsd" ,
44
+ ) ) ]
45
+ pub ( crate ) retries : Option < u32 > ,
46
+ }
47
+
25
48
impl TcpSocket {
26
49
/// Create a new IPv4 TCP socket.
27
50
///
28
51
/// This calls `socket(2)`.
29
52
pub fn new_v4 ( ) -> io:: Result < TcpSocket > {
30
- sys:: tcp:: new_v4_socket ( ) . map ( |sys| TcpSocket {
31
- sys
53
+ sys:: tcp:: new_v4_socket ( ) . map ( |sys| {
54
+ TcpSocket { sys }
32
55
} )
33
56
}
34
57
35
58
/// Create a new IPv6 TCP socket.
36
59
///
37
60
/// This calls `socket(2)`.
38
61
pub fn new_v6 ( ) -> io:: Result < TcpSocket > {
39
- sys:: tcp:: new_v6_socket ( ) . map ( |sys| TcpSocket {
40
- sys
62
+ sys:: tcp:: new_v6_socket ( ) . map ( |sys| {
63
+ TcpSocket { sys }
41
64
} )
42
65
}
43
66
@@ -168,7 +191,133 @@ impl TcpSocket {
168
191
pub fn get_send_buffer_size ( & self ) -> io:: Result < u32 > {
169
192
sys:: tcp:: get_send_buffer_size ( self . sys )
170
193
}
171
-
194
+
195
+ /// Sets whether keepalive messages are enabled to be sent on this socket.
196
+ ///
197
+ /// This will set the `SO_KEEPALIVE` option on this socket.
198
+ pub fn set_keepalive ( & self , keepalive : bool ) -> io:: Result < ( ) > {
199
+ sys:: tcp:: set_keepalive ( self . sys , keepalive)
200
+ }
201
+
202
+ /// Returns whether or not TCP keepalive probes will be sent by this socket.
203
+ pub fn get_keepalive ( & self ) -> io:: Result < bool > {
204
+ sys:: tcp:: get_keepalive ( self . sys )
205
+ }
206
+
207
+ /// Sets parameters configuring TCP keepalive probes for this socket.
208
+ ///
209
+ /// The supported parameters depend on the operating system, and are
210
+ /// configured using the [`TcpKeepalive`] struct. At a minimum, all systems
211
+ /// support configuring the [keepalive time]: the time after which the OS
212
+ /// will start sending keepalive messages on an idle connection.
213
+ ///
214
+ /// # Notes
215
+ ///
216
+ /// * This will enable TCP keepalive on this socket, if it is not already
217
+ /// enabled.
218
+ /// * On some platforms, such as Windows, any keepalive parameters *not*
219
+ /// configured by the `TcpKeepalive` struct passed to this function may be
220
+ /// overwritten with their default values. Therefore, this function should
221
+ /// either only be called once per socket, or the same parameters should
222
+ /// be passed every time it is called.
223
+ ///
224
+ /// # Examples
225
+ /// ```
226
+ /// use mio::net::{TcpSocket, TcpKeepalive};
227
+ /// use std::time::Duration;
228
+ ///
229
+ /// # fn main() -> Result<(), std::io::Error> {
230
+ /// let socket = TcpSocket::new_v6()?;
231
+ /// let keepalive = TcpKeepalive::default()
232
+ /// .with_time(Duration::from_secs(4));
233
+ /// // Depending on the target operating system, we may also be able to
234
+ /// // configure the keepalive probe interval and/or the number of retries
235
+ /// // here as well.
236
+ ///
237
+ /// socket.set_keepalive_params(keepalive)?;
238
+ /// # Ok(()) }
239
+ /// ```
240
+ ///
241
+ /// [`TcpKeepalive`]: ../struct.TcpKeepalive.html
242
+ /// [keepalive time]: ../struct.TcpKeepalive.html#method.with_time
243
+ pub fn set_keepalive_params ( & self , keepalive : TcpKeepalive ) -> io:: Result < ( ) > {
244
+ self . set_keepalive ( true ) ?;
245
+ sys:: tcp:: set_keepalive_params ( self . sys , keepalive)
246
+ }
247
+
248
+ /// Returns the amount of time after which TCP keepalive probes will be sent
249
+ /// on idle connections.
250
+ ///
251
+ /// If `None`, then keepalive messages are disabled.
252
+ ///
253
+ /// This returns the value of `SO_KEEPALIVE` + `IPPROTO_TCP` on OpenBSD,
254
+ /// NetBSD, and Haiku, `TCP_KEEPALIVE` on macOS and iOS, and `TCP_KEEPIDLE`
255
+ /// on all other Unix operating systems. On Windows, it is not possible to
256
+ /// access the value of TCP keepalive parameters after they have been set.
257
+ ///
258
+ /// Some platforms specify this value in seconds, so sub-second
259
+ /// specifications may be omitted.
260
+ #[ cfg_attr( docsrs, doc( cfg( not( target_os = "windows" ) ) ) ) ]
261
+ #[ cfg( not( target_os = "windows" ) ) ]
262
+ pub fn get_keepalive_time ( & self ) -> io:: Result < Option < Duration > > {
263
+ sys:: tcp:: get_keepalive_time ( self . sys )
264
+ }
265
+
266
+ /// Returns the time interval between TCP keepalive probes, if TCP keepalive is
267
+ /// enabled on this socket.
268
+ ///
269
+ /// If `None`, then keepalive messages are disabled.
270
+ ///
271
+ /// This returns the value of `TCP_KEEPINTVL` on supported Unix operating
272
+ /// systems. On Windows, it is not possible to access the value of TCP
273
+ /// keepalive parameters after they have been set..
274
+ ///
275
+ /// Some platforms specify this value in seconds, so sub-second
276
+ /// specifications may be omitted.
277
+ #[ cfg_attr( docsrs, doc( cfg( any(
278
+ target_os = "linux" ,
279
+ target_os = "macos" ,
280
+ target_os = "ios" ,
281
+ target_os = "freebsd" ,
282
+ target_os = "netbsd" ,
283
+ ) ) ) ) ]
284
+ #[ cfg( any(
285
+ target_os = "linux" ,
286
+ target_os = "macos" ,
287
+ target_os = "ios" ,
288
+ target_os = "freebsd" ,
289
+ target_os = "netbsd" ,
290
+ ) ) ]
291
+ pub fn get_keepalive_interval ( & self ) -> io:: Result < Option < Duration > > {
292
+ sys:: tcp:: get_keepalive_interval ( self . sys )
293
+ }
294
+
295
+ /// Returns the maximum number of TCP keepalive probes that will be sent before
296
+ /// dropping a connection, if TCP keepalive is enabled on this socket.
297
+ ///
298
+ /// If `None`, then keepalive messages are disabled.
299
+ ///
300
+ /// This returns the value of `TCP_KEEPCNT` on Unix operating systems that
301
+ /// support this option. On Windows, it is not possible to access the value
302
+ /// of TCP keepalive parameters after they have been set.
303
+ #[ cfg_attr( docsrs, doc( cfg( any(
304
+ target_os = "linux" ,
305
+ target_os = "macos" ,
306
+ target_os = "ios" ,
307
+ target_os = "freebsd" ,
308
+ target_os = "netbsd" ,
309
+ ) ) ) ) ]
310
+ #[ cfg( any(
311
+ target_os = "linux" ,
312
+ target_os = "macos" ,
313
+ target_os = "ios" ,
314
+ target_os = "freebsd" ,
315
+ target_os = "netbsd" ,
316
+ ) ) ]
317
+ pub fn get_keepalive_retries ( & self ) -> io:: Result < Option < u32 > > {
318
+ sys:: tcp:: get_keepalive_retries ( self . sys )
319
+ }
320
+
172
321
/// Returns the local address of this socket
173
322
///
174
323
/// Will return `Err` result in windows if called before calling `bind`
@@ -238,3 +387,83 @@ impl FromRawSocket for TcpSocket {
238
387
TcpSocket { sys : socket as sys:: tcp:: TcpSocket }
239
388
}
240
389
}
390
+
391
+ impl TcpKeepalive {
392
+ // Sets the amount of time after which TCP keepalive probes will be sent
393
+ /// on idle connections.
394
+ ///
395
+ /// This will set the value of `SO_KEEPALIVE` + `IPPROTO_TCP` on OpenBSD,
396
+ /// NetBSD, and Haiku, `TCP_KEEPALIVE` on macOS and iOS, and `TCP_KEEPIDLE`
397
+ /// on all other Unix operating systems. On Windows, this sets the value of
398
+ /// the `tcp_keepalive` struct's `keepalivetime` field.
399
+ ///
400
+ /// Some platforms specify this value in seconds, so sub-second
401
+ /// specifications may be omitted.
402
+ pub fn with_time ( self , time : Duration ) -> Self {
403
+ Self {
404
+ time : Some ( time) ,
405
+ ..self
406
+ }
407
+ }
408
+
409
+ /// Sets the time interval between TCP keepalive probes.
410
+ /// This sets the value of `TCP_KEEPINTVL` on supported Unix operating
411
+ /// systems. On Windows, this sets the value of the `tcp_keepalive` struct's
412
+ /// `keepaliveinterval` field.
413
+ ///
414
+ /// Some platforms specify this value in seconds, so sub-second
415
+ /// specifications may be omitted.
416
+ #[ cfg_attr( docsrs, doc( cfg( any(
417
+ target_os = "linux" ,
418
+ target_os = "macos" ,
419
+ target_os = "ios" ,
420
+ target_os = "freebsd" ,
421
+ target_os = "netbsd" ,
422
+ target_os = "windows"
423
+ ) ) ) ) ]
424
+ #[ cfg( any(
425
+ target_os = "linux" ,
426
+ target_os = "macos" ,
427
+ target_os = "ios" ,
428
+ target_os = "freebsd" ,
429
+ target_os = "netbsd" ,
430
+ target_os = "windows"
431
+ ) ) ]
432
+ pub fn with_interval ( self , interval : Duration ) -> Self {
433
+ Self {
434
+ interval : Some ( interval) ,
435
+ ..self
436
+ }
437
+ }
438
+
439
+ /// Sets the maximum number of TCP keepalive probes that will be sent before
440
+ /// dropping a connection, if TCP keepalive is enabled on this socket.
441
+ ///
442
+ /// This will set the value of `TCP_KEEPCNT` on Unix operating systems that
443
+ /// support this option.
444
+ #[ cfg_attr( docsrs, doc( cfg( any(
445
+ target_os = "linux" ,
446
+ target_os = "macos" ,
447
+ target_os = "ios" ,
448
+ target_os = "freebsd" ,
449
+ target_os = "netbsd" ,
450
+ ) ) ) ) ]
451
+ #[ cfg( any(
452
+ target_os = "linux" ,
453
+ target_os = "macos" ,
454
+ target_os = "ios" ,
455
+ target_os = "freebsd" ,
456
+ target_os = "netbsd" ,
457
+ ) ) ]
458
+ pub fn with_retries ( self , retries : u32 ) -> Self {
459
+ Self {
460
+ retries : Some ( retries) ,
461
+ ..self
462
+ }
463
+ }
464
+
465
+ /// Returns a new, empty set of TCP keepalive parameters.
466
+ pub fn new ( ) -> Self {
467
+ Self :: default ( )
468
+ }
469
+ }
0 commit comments