net2/
ext.rs

1// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11#![allow(bad_style, dead_code)]
12
13use std::io;
14use std::mem;
15use std::net::{TcpStream, TcpListener, UdpSocket, Ipv4Addr, Ipv6Addr};
16use std::net::ToSocketAddrs;
17
18use {TcpBuilder, UdpBuilder, FromInner};
19use sys;
20use sys::c;
21use socket;
22
23cfg_if! {
24    if #[cfg(any(target_os = "dragonfly",
25                 target_os = "freebsd",
26                 target_os = "haiku",
27                 target_os = "ios",
28                 target_os = "macos",
29                 target_os = "netbsd",
30                 target_os = "openbsd",
31                 target_os = "solaris",
32                 target_os = "illumos",
33                 target_env = "uclibc"))] {
34        use libc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
35        use libc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
36    } else {
37        // ...
38    }
39}
40
41use std::time::Duration;
42
43#[cfg(any(unix, target_os = "wasi"))] use libc::*;
44#[cfg(any(unix))] use std::os::unix::prelude::*;
45#[cfg(target_os = "wasi")] use std::os::wasi::prelude::*;
46#[cfg(unix)] pub type Socket = c_int;
47#[cfg(target_os = "wasi")] pub type Socket = std::os::wasi::io::RawFd;
48#[cfg(windows)] pub type Socket = SOCKET;
49#[cfg(windows)] use std::os::windows::prelude::*;
50#[cfg(any(windows, target_os = "wasi"))] use sys::c::*;
51
52#[cfg(windows)] const SIO_KEEPALIVE_VALS: DWORD = 0x98000004;
53#[cfg(windows)]
54#[repr(C)]
55struct tcp_keepalive {
56    onoff: c_ulong,
57    keepalivetime: c_ulong,
58    keepaliveinterval: c_ulong,
59}
60
61#[cfg(any(unix, target_os = "wasi"))] fn v(opt: c_int) -> c_int { opt }
62#[cfg(windows)] fn v(opt: IPPROTO) -> c_int { opt as c_int }
63
64#[cfg(target_os = "wasi")]
65pub fn set_opt<T: Copy>(_sock: Socket, _opt: c_int, _val: c_int,
66                       _payload: T) -> io::Result<()> {
67    Ok(())
68}
69
70#[cfg(not(target_os = "wasi"))]
71pub fn set_opt<T: Copy>(sock: Socket, opt: c_int, val: c_int,
72                       payload: T) -> io::Result<()> {
73    unsafe {
74        let payload = &payload as *const T as *const c_void;
75        try!(::cvt(setsockopt(sock, opt, val, payload as *const _,
76                              mem::size_of::<T>() as socklen_t)));
77    }
78    Ok(())
79}
80
81#[cfg(target_os = "wasi")]
82pub fn get_opt<T: Copy>(_sock: Socket, _opt: c_int, _val: c_int) -> io::Result<T> {
83    unimplemented!()
84}
85#[cfg(not(target_os = "wasi"))]
86pub fn get_opt<T: Copy>(sock: Socket, opt: c_int, val: c_int) -> io::Result<T> {
87    unsafe {
88        let mut slot: T = mem::zeroed();
89        let mut len = mem::size_of::<T>() as socklen_t;
90        try!(::cvt(getsockopt(sock, opt, val,
91                              &mut slot as *mut _ as *mut _,
92                              &mut len)));
93        assert_eq!(len as usize, mem::size_of::<T>());
94        Ok(slot)
95    }
96}
97
98/// Extension methods for the standard [`TcpStream` type][link] in `std::net`.
99///
100/// [link]: https://doc.rust-lang.org/std/net/struct.TcpStream.html
101pub trait TcpStreamExt {
102    /// Sets the value of the `TCP_NODELAY` option on this socket.
103    ///
104    /// If set, this option disables the Nagle algorithm. This means that
105    /// segments are always sent as soon as possible, even if there is only a
106    /// small amount of data. When not set, data is buffered until there is a
107    /// sufficient amount to send out, thereby avoiding the frequent sending of
108    /// small packets.
109    fn set_nodelay(&self, nodelay: bool) -> io::Result<()>;
110
111    /// Gets the value of the `TCP_NODELAY` option on this socket.
112    ///
113    /// For more information about this option, see [`set_nodelay`][link].
114    ///
115    /// [link]: #tymethod.set_nodelay
116    fn nodelay(&self) -> io::Result<bool>;
117
118    /// Sets the value of the `SO_RCVBUF` option on this socket.
119    ///
120    /// Changes the size of the operating system's receive buffer associated with the socket.
121    fn set_recv_buffer_size(&self, size: usize) -> io::Result<()>;
122
123    /// Gets the value of the `SO_RCVBUF` option on this socket.
124    ///
125    /// For more information about this option, see [`set_recv_buffer_size`][link].
126    ///
127    /// [link]: #tymethod.set_recv_buffer_size
128    fn recv_buffer_size(&self) -> io::Result<usize>;
129
130    /// Sets the value of the `SO_SNDBUF` option on this socket.
131    ///
132    /// Changes the size of the operating system's send buffer associated with the socket.
133    fn set_send_buffer_size(&self, size: usize) -> io::Result<()>;
134
135    /// Gets the value of the `SO_SNDBUF` option on this socket.
136    ///
137    /// For more information about this option, see [`set_send_buffer`][link].
138    ///
139    /// [link]: #tymethod.set_send_buffer
140    fn send_buffer_size(&self) -> io::Result<usize>;
141
142    /// Sets whether keepalive messages are enabled to be sent on this socket.
143    ///
144    /// On Unix, this option will set the `SO_KEEPALIVE` as well as the
145    /// `TCP_KEEPALIVE` or `TCP_KEEPIDLE` option (depending on your platform).
146    /// On Windows, this will set the `SIO_KEEPALIVE_VALS` option.
147    ///
148    /// If `None` is specified then keepalive messages are disabled, otherwise
149    /// the number of milliseconds specified will be the time to remain idle
150    /// before sending a TCP keepalive probe.
151    ///
152    /// Some platforms specify this value in seconds, so sub-second millisecond
153    /// specifications may be omitted.
154    fn set_keepalive_ms(&self, keepalive: Option<u32>) -> io::Result<()>;
155
156    /// Returns whether keepalive messages are enabled on this socket, and if so
157    /// the amount of milliseconds between them.
158    ///
159    /// For more information about this option, see [`set_keepalive_ms`][link].
160    ///
161    /// [link]: #tymethod.set_keepalive_ms
162    fn keepalive_ms(&self) -> io::Result<Option<u32>>;
163
164    /// Sets whether keepalive messages are enabled to be sent on this socket.
165    ///
166    /// On Unix, this option will set the `SO_KEEPALIVE` as well as the
167    /// `TCP_KEEPALIVE` or `TCP_KEEPIDLE` option (depending on your platform).
168    /// On Windows, this will set the `SIO_KEEPALIVE_VALS` option.
169    ///
170    /// If `None` is specified then keepalive messages are disabled, otherwise
171    /// the duration specified will be the time to remain idle before sending a
172    /// TCP keepalive probe.
173    ///
174    /// Some platforms specify this value in seconds, so sub-second
175    /// specifications may be omitted.
176    fn set_keepalive(&self, keepalive: Option<Duration>) -> io::Result<()>;
177
178    /// Returns whether keepalive messages are enabled on this socket, and if so
179    /// the duration of time between them.
180    ///
181    /// For more information about this option, see [`set_keepalive`][link].
182    ///
183    /// [link]: #tymethod.set_keepalive
184    fn keepalive(&self) -> io::Result<Option<Duration>>;
185
186    /// Sets the `SO_RCVTIMEO` option for this socket.
187    ///
188    /// This option specifies the timeout, in milliseconds, of how long calls to
189    /// this socket's `read` function will wait before returning a timeout. A
190    /// value of `None` means that no read timeout should be specified and
191    /// otherwise `Some` indicates the number of milliseconds for the timeout.
192    fn set_read_timeout_ms(&self, val: Option<u32>) -> io::Result<()>;
193
194    /// Sets the `SO_RCVTIMEO` option for this socket.
195    ///
196    /// This option specifies the timeout of how long calls to this socket's
197    /// `read` function will wait before returning a timeout. A value of `None`
198    /// means that no read timeout should be specified and otherwise `Some`
199    /// indicates the number of duration of the timeout.
200    fn set_read_timeout(&self, val: Option<Duration>) -> io::Result<()>;
201
202    /// Gets the value of the `SO_RCVTIMEO` option for this socket.
203    ///
204    /// For more information about this option, see [`set_read_timeout_ms`][link].
205    ///
206    /// [link]: #tymethod.set_read_timeout_ms
207    fn read_timeout_ms(&self) -> io::Result<Option<u32>>;
208
209    /// Gets the value of the `SO_RCVTIMEO` option for this socket.
210    ///
211    /// For more information about this option, see [`set_read_timeout`][link].
212    ///
213    /// [link]: #tymethod.set_read_timeout
214    fn read_timeout(&self) -> io::Result<Option<Duration>>;
215
216    /// Sets the `SO_SNDTIMEO` option for this socket.
217    ///
218    /// This option specifies the timeout, in milliseconds, of how long calls to
219    /// this socket's `write` function will wait before returning a timeout. A
220    /// value of `None` means that no read timeout should be specified and
221    /// otherwise `Some` indicates the number of milliseconds for the timeout.
222    fn set_write_timeout_ms(&self, val: Option<u32>) -> io::Result<()>;
223
224    /// Sets the `SO_SNDTIMEO` option for this socket.
225    ///
226    /// This option specifies the timeout of how long calls to this socket's
227    /// `write` function will wait before returning a timeout. A value of `None`
228    /// means that no read timeout should be specified and otherwise `Some`
229    /// indicates the duration of the timeout.
230    fn set_write_timeout(&self, val: Option<Duration>) -> io::Result<()>;
231
232    /// Gets the value of the `SO_SNDTIMEO` option for this socket.
233    ///
234    /// For more information about this option, see [`set_write_timeout_ms`][link].
235    ///
236    /// [link]: #tymethod.set_write_timeout_ms
237    fn write_timeout_ms(&self) -> io::Result<Option<u32>>;
238
239    /// Gets the value of the `SO_SNDTIMEO` option for this socket.
240    ///
241    /// For more information about this option, see [`set_write_timeout`][link].
242    ///
243    /// [link]: #tymethod.set_write_timeout
244    fn write_timeout(&self) -> io::Result<Option<Duration>>;
245
246    /// Sets the value for the `IP_TTL` option on this socket.
247    ///
248    /// This value sets the time-to-live field that is used in every packet sent
249    /// from this socket.
250    fn set_ttl(&self, ttl: u32) -> io::Result<()>;
251
252    /// Gets the value of the `IP_TTL` option for this socket.
253    ///
254    /// For more information about this option, see [`set_ttl`][link].
255    ///
256    /// [link]: #tymethod.set_ttl
257    fn ttl(&self) -> io::Result<u32>;
258
259    /// Sets the value for the `IPV6_V6ONLY` option on this socket.
260    ///
261    /// If this is set to `true` then the socket is restricted to sending and
262    /// receiving IPv6 packets only. In this case two IPv4 and IPv6 applications
263    /// can bind the same port at the same time.
264    ///
265    /// If this is set to `false` then the socket can be used to send and
266    /// receive packets from an IPv4-mapped IPv6 address.
267    fn set_only_v6(&self, only_v6: bool) -> io::Result<()>;
268
269    /// Gets the value of the `IPV6_V6ONLY` option for this socket.
270    ///
271    /// For more information about this option, see [`set_only_v6`][link].
272    ///
273    /// [link]: #tymethod.set_only_v6
274    fn only_v6(&self) -> io::Result<bool>;
275
276    /// Executes a `connect` operation on this socket, establishing a connection
277    /// to the host specified by `addr`.
278    ///
279    /// Note that this normally does not need to be called on a `TcpStream`,
280    /// it's typically automatically done as part of a normal
281    /// `TcpStream::connect` function call or `TcpBuilder::connect` method call.
282    ///
283    /// This should only be necessary if an unconnected socket was extracted
284    /// from a `TcpBuilder` and then needs to be connected.
285    fn connect<T: ToSocketAddrs>(&self, addr: T) -> io::Result<()>;
286
287    /// Get the value of the `SO_ERROR` option on this socket.
288    ///
289    /// This will retrieve the stored error in the underlying socket, clearing
290    /// the field in the process. This can be useful for checking errors between
291    /// calls.
292    fn take_error(&self) -> io::Result<Option<io::Error>>;
293
294    /// Moves this TCP stream into or out of nonblocking mode.
295    ///
296    /// On Unix this corresponds to calling fcntl, and on Windows this
297    /// corresponds to calling ioctlsocket.
298    fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()>;
299
300    /// Sets the linger duration of this socket by setting the SO_LINGER option
301    fn set_linger(&self, dur: Option<Duration>) -> io::Result<()>;
302
303    /// reads the linger duration for this socket by getting the SO_LINGER option
304    fn linger(&self) -> io::Result<Option<Duration>>;
305}
306
307/// Extension methods for the standard [`TcpListener` type][link] in `std::net`.
308///
309/// [link]: https://doc.rust-lang.org/std/net/struct.TcpListener.html
310pub trait TcpListenerExt {
311    /// Sets the value for the `IP_TTL` option on this socket.
312    ///
313    /// This is the same as [`TcpStreamExt::set_ttl`][other].
314    ///
315    /// [other]: trait.TcpStreamExt.html#tymethod.set_ttl
316    fn set_ttl(&self, ttl: u32) -> io::Result<()>;
317
318    /// Gets the value of the `IP_TTL` option for this socket.
319    ///
320    /// For more information about this option, see
321    /// [`TcpStreamExt::set_ttl`][link].
322    ///
323    /// [link]: trait.TcpStreamExt.html#tymethod.set_ttl
324    fn ttl(&self) -> io::Result<u32>;
325
326    /// Sets the value for the `IPV6_V6ONLY` option on this socket.
327    ///
328    /// For more information about this option, see
329    /// [`TcpStreamExt::set_only_v6`][link].
330    ///
331    /// [link]: trait.TcpStreamExt.html#tymethod.set_only_v6
332    fn set_only_v6(&self, only_v6: bool) -> io::Result<()>;
333
334    /// Gets the value of the `IPV6_V6ONLY` option for this socket.
335    ///
336    /// For more information about this option, see
337    /// [`TcpStreamExt::set_only_v6`][link].
338    ///
339    /// [link]: trait.TcpStreamExt.html#tymethod.set_only_v6
340    fn only_v6(&self) -> io::Result<bool>;
341
342    /// Get the value of the `SO_ERROR` option on this socket.
343    ///
344    /// This will retrieve the stored error in the underlying socket, clearing
345    /// the field in the process. This can be useful for checking errors between
346    /// calls.
347    fn take_error(&self) -> io::Result<Option<io::Error>>;
348
349    /// Moves this TCP listener into or out of nonblocking mode.
350    ///
351    /// For more information about this option, see
352    /// [`TcpStreamExt::set_nonblocking`][link].
353    ///
354    /// [link]: trait.TcpStreamExt.html#tymethod.set_nonblocking
355    fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()>;
356
357    /// Sets the linger duration of this socket by setting the SO_LINGER option
358    fn set_linger(&self, dur: Option<Duration>) -> io::Result<()>;
359
360    /// reads the linger duration for this socket by getting the SO_LINGER option
361    fn linger(&self) -> io::Result<Option<Duration>>;
362}
363
364/// Extension methods for the standard [`UdpSocket` type][link] in `std::net`.
365///
366/// [link]: https://doc.rust-lang.org/std/net/struct.UdpSocket.html
367pub trait UdpSocketExt {
368    /// Sets the value of the `SO_RCVBUF` option on this socket.
369    ///
370    /// Changes the size of the operating system's receive buffer associated with the socket.
371    fn set_recv_buffer_size(&self, size: usize) -> io::Result<()>;
372
373    /// Gets the value of the `SO_RCVBUF` option on this socket.
374    ///
375    /// For more information about this option, see [`set_recv_buffer_size`][link].
376    ///
377    /// [link]: #tymethod.set_recv_buffer_size
378    fn recv_buffer_size(&self) -> io::Result<usize>;
379
380    /// Sets the value of the `SO_SNDBUF` option on this socket.
381    ///
382    /// Changes the size of the operating system's send buffer associated with the socket.
383    fn set_send_buffer_size(&self, size: usize) -> io::Result<()>;
384
385    /// Gets the value of the `SO_SNDBUF` option on this socket.
386    ///
387    /// For more information about this option, see [`set_send_buffer`][link].
388    ///
389    /// [link]: #tymethod.set_send_buffer
390    fn send_buffer_size(&self) -> io::Result<usize>;
391
392    /// Sets the value of the `SO_BROADCAST` option for this socket.
393    ///
394    /// When enabled, this socket is allowed to send packets to a broadcast
395    /// address.
396    fn set_broadcast(&self, broadcast: bool) -> io::Result<()>;
397
398    /// Gets the value of the `SO_BROADCAST` option for this socket.
399    ///
400    /// For more information about this option, see
401    /// [`set_broadcast`][link].
402    ///
403    /// [link]: #tymethod.set_broadcast
404    fn broadcast(&self) -> io::Result<bool>;
405
406    /// Sets the value of the `IP_MULTICAST_LOOP` option for this socket.
407    ///
408    /// If enabled, multicast packets will be looped back to the local socket.
409    /// Note that this may not have any affect on IPv6 sockets.
410    fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()>;
411
412    /// Gets the value of the `IP_MULTICAST_LOOP` option for this socket.
413    ///
414    /// For more information about this option, see
415    /// [`set_multicast_loop_v4`][link].
416    ///
417    /// [link]: #tymethod.set_multicast_loop_v4
418    fn multicast_loop_v4(&self) -> io::Result<bool>;
419
420    /// Sets the value of the `IP_MULTICAST_TTL` option for this socket.
421    ///
422    /// Indicates the time-to-live value of outgoing multicast packets for
423    /// this socket. The default value is 1 which means that multicast packets
424    /// don't leave the local network unless explicitly requested.
425    ///
426    /// Note that this may not have any affect on IPv6 sockets.
427    fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()>;
428
429    /// Gets the value of the `IP_MULTICAST_TTL` option for this socket.
430    ///
431    /// For more information about this option, see
432    /// [`set_multicast_ttl_v4`][link].
433    ///
434    /// [link]: #tymethod.set_multicast_ttl_v4
435    fn multicast_ttl_v4(&self) -> io::Result<u32>;
436
437    /// Sets the value of the `IPV6_MULTICAST_HOPS` option for this socket
438    fn set_multicast_hops_v6(&self, hops: u32) -> io::Result<()>;
439
440    /// Gets the value of the `IPV6_MULTICAST_HOPS` option for this socket
441    fn multicast_hops_v6(&self) -> io::Result<u32>;
442
443    /// Sets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
444    ///
445    /// Controls whether this socket sees the multicast packets it sends itself.
446    /// Note that this may not have any affect on IPv4 sockets.
447    fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()>;
448
449    /// Gets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
450    ///
451    /// For more information about this option, see
452    /// [`set_multicast_loop_v6`][link].
453    ///
454    /// [link]: #tymethod.set_multicast_loop_v6
455    fn multicast_loop_v6(&self) -> io::Result<bool>;
456
457    /// Sets the value of the `IP_MULTICAST_IF` option for this socket.
458    ///
459    /// Specifies the interface to use for routing multicast packets.
460    fn set_multicast_if_v4(&self, interface: &Ipv4Addr) -> io::Result<()>;
461
462    /// Gets the value of the `IP_MULTICAST_IF` option for this socket.
463    ///
464    /// Returns the interface to use for routing multicast packets.
465    fn multicast_if_v4(&self) -> io::Result<Ipv4Addr>;
466
467
468    /// Sets the value of the `IPV6_MULTICAST_IF` option for this socket.
469    ///
470    /// Specifies the interface to use for routing multicast packets.
471    fn set_multicast_if_v6(&self, interface: u32) -> io::Result<()>;
472
473    /// Gets the value of the `IPV6_MULTICAST_IF` option for this socket.
474    ///
475    /// Returns the interface to use for routing multicast packets.
476    fn multicast_if_v6(&self) -> io::Result<u32>;
477
478    /// Sets the value for the `IP_TTL` option on this socket.
479    ///
480    /// This is the same as [`TcpStreamExt::set_ttl`][other].
481    ///
482    /// [other]: trait.TcpStreamExt.html#tymethod.set_ttl
483    fn set_ttl(&self, ttl: u32) -> io::Result<()>;
484
485    /// Gets the value of the `IP_TTL` option for this socket.
486    ///
487    /// For more information about this option, see
488    /// [`TcpStreamExt::set_ttl`][link].
489    ///
490    /// [link]: trait.TcpStreamExt.html#tymethod.set_ttl
491    fn ttl(&self) -> io::Result<u32>;
492
493    /// Sets the value for the `IPV6_UNICAST_HOPS` option on this socket.
494    ///
495    /// Specifies the hop limit for ipv6 unicast packets
496    fn set_unicast_hops_v6(&self, ttl: u32) -> io::Result<()>;
497
498    /// Gets the value of the `IPV6_UNICAST_HOPS` option for this socket.
499    ///
500    /// Specifies the hop limit for ipv6 unicast packets
501    fn unicast_hops_v6(&self) -> io::Result<u32>;
502
503    /// Sets the value for the `IPV6_V6ONLY` option on this socket.
504    ///
505    /// For more information about this option, see
506    /// [`TcpStreamExt::set_only_v6`][link].
507    ///
508    /// [link]: trait.TcpStreamExt.html#tymethod.set_only_v6
509    fn set_only_v6(&self, only_v6: bool) -> io::Result<()>;
510
511    /// Gets the value of the `IPV6_V6ONLY` option for this socket.
512    ///
513    /// For more information about this option, see
514    /// [`TcpStreamExt::set_only_v6`][link].
515    ///
516    /// [link]: trait.TcpStreamExt.html#tymethod.set_only_v6
517    fn only_v6(&self) -> io::Result<bool>;
518
519    /// Executes an operation of the `IP_ADD_MEMBERSHIP` type.
520    ///
521    /// This function specifies a new multicast group for this socket to join.
522    /// The address must be a valid multicast address, and `interface` is the
523    /// address of the local interface with which the system should join the
524    /// multicast group. If it's equal to `INADDR_ANY` then an appropriate
525    /// interface is chosen by the system.
526    fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr)
527                         -> io::Result<()>;
528
529    /// Executes an operation of the `IPV6_ADD_MEMBERSHIP` type.
530    ///
531    /// This function specifies a new multicast group for this socket to join.
532    /// The address must be a valid multicast address, and `interface` is the
533    /// index of the interface to join/leave (or 0 to indicate any interface).
534    fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32)
535                         -> io::Result<()>;
536
537    /// Executes an operation of the `IP_DROP_MEMBERSHIP` type.
538    ///
539    /// For more information about this option, see
540    /// [`join_multicast_v4`][link].
541    ///
542    /// [link]: #tymethod.join_multicast_v4
543    fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr)
544                          -> io::Result<()>;
545
546    /// Executes an operation of the `IPV6_DROP_MEMBERSHIP` type.
547    ///
548    /// For more information about this option, see
549    /// [`join_multicast_v6`][link].
550    ///
551    /// [link]: #tymethod.join_multicast_v6
552    fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32)
553                          -> io::Result<()>;
554
555    /// Sets the `SO_RCVTIMEO` option for this socket.
556    ///
557    /// This option specifies the timeout, in milliseconds, of how long calls to
558    /// this socket's `read` function will wait before returning a timeout. A
559    /// value of `None` means that no read timeout should be specified and
560    /// otherwise `Some` indicates the number of milliseconds for the timeout.
561    fn set_read_timeout_ms(&self, val: Option<u32>) -> io::Result<()>;
562
563    /// Sets the `SO_RCVTIMEO` option for this socket.
564    ///
565    /// This option specifies the timeout of how long calls to this socket's
566    /// `read` function will wait before returning a timeout. A value of `None`
567    /// means that no read timeout should be specified and otherwise `Some`
568    /// indicates the number of duration of the timeout.
569    fn set_read_timeout(&self, val: Option<Duration>) -> io::Result<()>;
570
571    /// Gets the value of the `SO_RCVTIMEO` option for this socket.
572    ///
573    /// For more information about this option, see [`set_read_timeout_ms`][link].
574    ///
575    /// [link]: #tymethod.set_read_timeout_ms
576    fn read_timeout_ms(&self) -> io::Result<Option<u32>>;
577
578    /// Gets the value of the `SO_RCVTIMEO` option for this socket.
579    ///
580    /// For more information about this option, see [`set_read_timeout`][link].
581    ///
582    /// [link]: #tymethod.set_read_timeout
583    fn read_timeout(&self) -> io::Result<Option<Duration>>;
584
585    /// Sets the `SO_SNDTIMEO` option for this socket.
586    ///
587    /// This option specifies the timeout, in milliseconds, of how long calls to
588    /// this socket's `write` function will wait before returning a timeout. A
589    /// value of `None` means that no read timeout should be specified and
590    /// otherwise `Some` indicates the number of milliseconds for the timeout.
591    fn set_write_timeout_ms(&self, val: Option<u32>) -> io::Result<()>;
592
593    /// Sets the `SO_SNDTIMEO` option for this socket.
594    ///
595    /// This option specifies the timeout of how long calls to this socket's
596    /// `write` function will wait before returning a timeout. A value of `None`
597    /// means that no read timeout should be specified and otherwise `Some`
598    /// indicates the duration of the timeout.
599    fn set_write_timeout(&self, val: Option<Duration>) -> io::Result<()>;
600
601    /// Gets the value of the `SO_SNDTIMEO` option for this socket.
602    ///
603    /// For more information about this option, see [`set_write_timeout_ms`][link].
604    ///
605    /// [link]: #tymethod.set_write_timeout_ms
606    fn write_timeout_ms(&self) -> io::Result<Option<u32>>;
607
608    /// Gets the value of the `SO_SNDTIMEO` option for this socket.
609    ///
610    /// For more information about this option, see [`set_write_timeout`][link].
611    ///
612    /// [link]: #tymethod.set_write_timeout
613    fn write_timeout(&self) -> io::Result<Option<Duration>>;
614
615    /// Get the value of the `SO_ERROR` option on this socket.
616    ///
617    /// This will retrieve the stored error in the underlying socket, clearing
618    /// the field in the process. This can be useful for checking errors between
619    /// calls.
620    fn take_error(&self) -> io::Result<Option<io::Error>>;
621
622    /// Connects this UDP socket to a remote address, allowing the `send` and
623    /// `recv` syscalls to be used to send data and also applies filters to only
624    /// receive data from the specified address.
625    fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()>;
626
627    /// Sends data on the socket to the remote address to which it is connected.
628    ///
629    /// The `connect` method will connect this socket to a remote address. This
630    /// method will fail if the socket is not connected.
631    fn send(&self, buf: &[u8]) -> io::Result<usize>;
632
633    /// Receives data on the socket from the remote address to which it is
634    /// connected.
635    ///
636    /// The `connect` method will connect this socket to a remote address. This
637    /// method will fail if the socket is not connected.
638    fn recv(&self, buf: &mut [u8]) -> io::Result<usize>;
639
640    /// Moves this UDP socket into or out of nonblocking mode.
641    ///
642    /// For more information about this option, see
643    /// [`TcpStreamExt::set_nonblocking`][link].
644    ///
645    /// [link]: trait.TcpStreamExt.html#tymethod.set_nonblocking
646    fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()>;
647}
648
649#[doc(hidden)]
650pub trait AsSock {
651    fn as_sock(&self) -> Socket;
652}
653
654#[cfg(any(unix, target_os = "wasi"))]
655impl<T: AsRawFd> AsSock for T {
656    fn as_sock(&self) -> Socket { self.as_raw_fd() }
657}
658#[cfg(windows)]
659impl<T: AsRawSocket> AsSock for T {
660    fn as_sock(&self) -> Socket { self.as_raw_socket() as Socket }
661}
662
663cfg_if! {
664    if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "nto"))] {
665        use libc::TCP_KEEPALIVE as KEEPALIVE_OPTION;
666    } else if #[cfg(any(target_os = "haiku", target_os = "netbsd", target_os = "openbsd"))] {
667        use libc::SO_KEEPALIVE as KEEPALIVE_OPTION;
668    } else if #[cfg(unix)] {
669        use libc::TCP_KEEPIDLE as KEEPALIVE_OPTION;
670    } else {
671        // ...
672    }
673}
674
675impl TcpStreamExt for TcpStream {
676
677    fn set_recv_buffer_size(&self, size: usize) -> io::Result<()> {
678        // TODO: casting usize to a c_int should be a checked cast
679        set_opt(self.as_sock(), SOL_SOCKET, SO_RCVBUF, size as c_int)
680    }
681
682    fn recv_buffer_size(&self) -> io::Result<usize> {
683        get_opt(self.as_sock(), SOL_SOCKET, SO_RCVBUF).map(int2usize)
684    }
685
686    fn set_send_buffer_size(&self, size: usize) -> io::Result<()> {
687        set_opt(self.as_sock(), SOL_SOCKET, SO_SNDBUF, size as c_int)
688    }
689
690    fn send_buffer_size(&self) -> io::Result<usize> {
691        get_opt(self.as_sock(), SOL_SOCKET, SO_SNDBUF).map(int2usize)
692    }
693
694    fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
695        set_opt(self.as_sock(), v(IPPROTO_TCP), TCP_NODELAY,
696               nodelay as c_int)
697    }
698    fn nodelay(&self) -> io::Result<bool> {
699        get_opt(self.as_sock(), v(IPPROTO_TCP), TCP_NODELAY)
700            .map(int2bool)
701    }
702
703    fn set_keepalive(&self, keepalive: Option<Duration>) -> io::Result<()> {
704        self.set_keepalive_ms(keepalive.map(dur2ms))
705    }
706
707    fn keepalive(&self) -> io::Result<Option<Duration>> {
708        self.keepalive_ms().map(|o| o.map(ms2dur))
709    }
710
711    #[cfg(unix)]
712    fn set_keepalive_ms(&self, keepalive: Option<u32>) -> io::Result<()> {
713        try!(set_opt(self.as_sock(), SOL_SOCKET, SO_KEEPALIVE,
714                    keepalive.is_some() as c_int));
715        if let Some(dur) = keepalive {
716            try!(set_opt(self.as_sock(), v(IPPROTO_TCP), KEEPALIVE_OPTION,
717                        (dur / 1000) as c_int));
718        }
719        Ok(())
720    }
721
722    #[cfg(unix)]
723    fn keepalive_ms(&self) -> io::Result<Option<u32>> {
724        let keepalive = try!(get_opt::<c_int>(self.as_sock(), SOL_SOCKET,
725                                             SO_KEEPALIVE));
726        if keepalive == 0 {
727            return Ok(None)
728        }
729        let secs = try!(get_opt::<c_int>(self.as_sock(), v(IPPROTO_TCP),
730                                        KEEPALIVE_OPTION));
731        Ok(Some((secs as u32) * 1000))
732    }
733
734     #[cfg(target_os = "wasi")]
735    fn set_keepalive_ms(&self, _keepalive: Option<u32>) -> io::Result<()> {
736        unimplemented!()
737    }
738
739    #[cfg(target_os = "wasi")]
740    fn keepalive_ms(&self) -> io::Result<Option<u32>> {
741        unimplemented!()
742    }
743
744    #[cfg(windows)]
745    fn set_keepalive_ms(&self, keepalive: Option<u32>) -> io::Result<()> {
746        let ms = keepalive.unwrap_or(INFINITE);
747        let ka = tcp_keepalive {
748            onoff: keepalive.is_some() as c_ulong,
749            keepalivetime: ms as c_ulong,
750            keepaliveinterval: ms as c_ulong,
751        };
752        unsafe {
753            ::cvt_win(WSAIoctl(self.as_sock(),
754                               SIO_KEEPALIVE_VALS,
755                               &ka as *const _ as *mut _,
756                               mem::size_of_val(&ka) as DWORD,
757                               0 as *mut _,
758                               0,
759                               0 as *mut _,
760                               0 as *mut _,
761                               None)).map(|_| ())
762        }
763    }
764
765    #[cfg(windows)]
766    fn keepalive_ms(&self) -> io::Result<Option<u32>> {
767        let mut ka = tcp_keepalive {
768            onoff: 0,
769            keepalivetime: 0,
770            keepaliveinterval: 0,
771        };
772        unsafe {
773            try!(::cvt_win(WSAIoctl(self.as_sock(),
774                                    SIO_KEEPALIVE_VALS,
775                                    0 as *mut _,
776                                    0,
777                                    &mut ka as *mut _ as *mut _,
778                                    mem::size_of_val(&ka) as DWORD,
779                                    0 as *mut _,
780                                    0 as *mut _,
781                                    None)));
782        }
783        Ok({
784            if ka.onoff == 0 {
785                None
786            } else {
787                timeout2ms(ka.keepaliveinterval as DWORD)
788            }
789        })
790    }
791
792    fn set_read_timeout_ms(&self, dur: Option<u32>) -> io::Result<()> {
793        set_opt(self.as_sock(), SOL_SOCKET, SO_RCVTIMEO,
794               ms2timeout(dur))
795    }
796
797    fn read_timeout_ms(&self) -> io::Result<Option<u32>> {
798        get_opt(self.as_sock(), SOL_SOCKET, SO_RCVTIMEO)
799            .map(timeout2ms)
800    }
801
802    fn set_write_timeout_ms(&self, dur: Option<u32>) -> io::Result<()> {
803        set_opt(self.as_sock(), SOL_SOCKET, SO_SNDTIMEO,
804               ms2timeout(dur))
805    }
806
807    fn write_timeout_ms(&self) -> io::Result<Option<u32>> {
808        get_opt(self.as_sock(), SOL_SOCKET, SO_SNDTIMEO)
809            .map(timeout2ms)
810    }
811
812    fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
813        self.set_read_timeout_ms(dur.map(dur2ms))
814    }
815
816    fn read_timeout(&self) -> io::Result<Option<Duration>> {
817        self.read_timeout_ms().map(|o| o.map(ms2dur))
818    }
819
820    fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
821        self.set_write_timeout_ms(dur.map(dur2ms))
822    }
823
824    fn write_timeout(&self) -> io::Result<Option<Duration>> {
825        self.write_timeout_ms().map(|o| o.map(ms2dur))
826    }
827
828    fn set_ttl(&self, ttl: u32) -> io::Result<()> {
829        set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int)
830    }
831
832    fn ttl(&self) -> io::Result<u32> {
833        get_opt::<c_int>(self.as_sock(), IPPROTO_IP, IP_TTL)
834            .map(|b| b as u32)
835    }
836
837    fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
838        set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int)
839    }
840
841    fn only_v6(&self) -> io::Result<bool> {
842        get_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY).map(int2bool)
843    }
844
845    fn connect<T: ToSocketAddrs>(&self, addr: T) -> io::Result<()> {
846        do_connect(self.as_sock(), addr)
847    }
848
849    fn take_error(&self) -> io::Result<Option<io::Error>> {
850        get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err)
851    }
852
853    fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
854        set_nonblocking(self.as_sock(), nonblocking)
855    }
856
857    fn set_linger(&self, dur: Option<Duration>) -> io::Result<()> {
858        set_opt(self.as_sock(), SOL_SOCKET, SO_LINGER, dur2linger(dur))
859    }
860
861    fn linger(&self) -> io::Result<Option<Duration>> {
862        get_opt(self.as_sock(), SOL_SOCKET, SO_LINGER).map(linger2dur)
863    }
864}
865
866#[cfg(any(unix, target_os = "wasi"))]
867fn ms2timeout(dur: Option<u32>) -> timeval {
868    // TODO: be more rigorous
869    match dur {
870        Some(d) => timeval {
871            tv_sec: (d / 1000) as time_t,
872            tv_usec: (d % 1000) as suseconds_t,
873        },
874        None => timeval { tv_sec: 0, tv_usec: 0 },
875    }
876}
877
878#[cfg(any(unix, target_os = "wasi"))]
879fn timeout2ms(dur: timeval) -> Option<u32> {
880    if dur.tv_sec == 0 && dur.tv_usec == 0 {
881        None
882    } else {
883        Some(dur.tv_sec as u32 * 1000 + dur.tv_usec as u32 / 1000)
884    }
885}
886
887#[cfg(windows)]
888fn ms2timeout(dur: Option<u32>) -> DWORD {
889    dur.unwrap_or(0)
890}
891
892#[cfg(windows)]
893fn timeout2ms(dur: DWORD) -> Option<u32> {
894    if dur == 0 {
895        None
896    } else {
897        Some(dur)
898    }
899}
900
901fn linger2dur(linger_opt: linger) -> Option<Duration> {
902    if linger_opt.l_onoff == 0 {
903        None
904    }
905    else {
906        Some(Duration::from_secs(linger_opt.l_linger as u64))
907    }
908}
909
910#[cfg(windows)]
911fn dur2linger(dur: Option<Duration>) -> linger {
912    match dur {
913        Some(d) => {
914            linger {
915                l_onoff: 1,
916                l_linger: d.as_secs() as u16,
917            }
918        },
919        None => linger { l_onoff: 0, l_linger: 0 },
920    }
921}
922
923#[cfg(any(unix, target_os = "wasi"))]
924fn dur2linger(dur: Option<Duration>) -> linger {
925    match dur {
926        Some(d) => {
927            linger {
928                l_onoff: 1,
929                l_linger: d.as_secs() as c_int,
930            }
931        },
932        None => linger { l_onoff: 0, l_linger: 0 },
933    }
934}
935
936fn ms2dur(ms: u32) -> Duration {
937    Duration::new((ms as u64) / 1000, (ms as u32) % 1000 * 1_000_000)
938}
939
940fn dur2ms(dur: Duration) -> u32 {
941    (dur.as_secs() as u32 * 1000) + (dur.subsec_nanos() / 1_000_000)
942}
943
944pub fn int2bool(n: c_int) -> bool {
945    if n == 0 {false} else {true}
946}
947
948pub fn int2usize(n: c_int) -> usize {
949    // TODO: casting c_int to a usize should be a checked cast
950    n as usize
951}
952
953pub fn int2err(n: c_int) -> Option<io::Error> {
954    if n == 0 {
955        None
956    } else {
957        Some(io::Error::from_raw_os_error(n as i32))
958    }
959}
960
961impl UdpSocketExt for UdpSocket {
962
963    fn set_recv_buffer_size(&self, size: usize) -> io::Result<()> {
964        set_opt(self.as_sock(), SOL_SOCKET, SO_RCVBUF, size as c_int)
965    }
966
967    fn recv_buffer_size(&self) -> io::Result<usize> {
968        get_opt(self.as_sock(), SOL_SOCKET, SO_RCVBUF).map(int2usize)
969    }
970
971    fn set_send_buffer_size(&self, size: usize) -> io::Result<()> {
972        set_opt(self.as_sock(), SOL_SOCKET, SO_SNDBUF, size as c_int)
973    }
974
975    fn send_buffer_size(&self) -> io::Result<usize> {
976        get_opt(self.as_sock(), SOL_SOCKET, SO_SNDBUF).map(int2usize)
977    }
978
979    fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
980        set_opt(self.as_sock(), SOL_SOCKET, SO_BROADCAST,
981               broadcast as c_int)
982    }
983    fn broadcast(&self) -> io::Result<bool> {
984        get_opt(self.as_sock(), SOL_SOCKET, SO_BROADCAST)
985            .map(int2bool)
986    }
987    fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
988        set_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_LOOP,
989               multicast_loop_v4 as c_int)
990    }
991    fn multicast_loop_v4(&self) -> io::Result<bool> {
992        get_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_LOOP)
993            .map(int2bool)
994    }
995
996    fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
997        set_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_TTL,
998               multicast_ttl_v4 as c_int)
999    }
1000
1001    fn multicast_ttl_v4(&self) -> io::Result<u32> {
1002        get_opt::<c_int>(self.as_sock(), IPPROTO_IP, IP_MULTICAST_TTL)
1003            .map(|b| b as u32)
1004    }
1005
1006    fn set_multicast_hops_v6(&self, _hops: u32) -> io::Result<()> {
1007        set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_HOPS,
1008               _hops as c_int)
1009    }
1010
1011    fn multicast_hops_v6(&self) -> io::Result<u32> {
1012        get_opt::<c_int>(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_HOPS)
1013            .map(|b| b as u32)
1014    }
1015
1016    fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
1017        set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_LOOP,
1018               multicast_loop_v6 as c_int)
1019    }
1020    fn multicast_loop_v6(&self) -> io::Result<bool> {
1021        get_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_LOOP)
1022            .map(int2bool)
1023    }
1024
1025    fn set_multicast_if_v4(&self, _interface: &Ipv4Addr) -> io::Result<()> {
1026        set_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_IF, ip2in_addr(_interface))
1027    }
1028
1029    fn multicast_if_v4(&self) -> io::Result<Ipv4Addr> {
1030        get_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_IF).map(in_addr2ip)
1031    }
1032
1033    fn set_multicast_if_v6(&self, _interface: u32) -> io::Result<()> {
1034        set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_IF, to_ipv6mr_interface(_interface))
1035    }
1036
1037    fn multicast_if_v6(&self) -> io::Result<u32> {
1038        get_opt::<c_int>(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_IF).map(|b| b as u32)
1039    }
1040
1041    fn set_ttl(&self, ttl: u32) -> io::Result<()> {
1042        set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int)
1043    }
1044
1045    fn ttl(&self) -> io::Result<u32> {
1046        get_opt::<c_int>(self.as_sock(), IPPROTO_IP, IP_TTL)
1047            .map(|b| b as u32)
1048    }
1049
1050    fn set_unicast_hops_v6(&self, _ttl: u32) -> io::Result<()> {
1051        set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_UNICAST_HOPS, _ttl as c_int)
1052    }
1053
1054    fn unicast_hops_v6(&self) -> io::Result<u32> {
1055        get_opt::<c_int>(self.as_sock(), IPPROTO_IP, IPV6_UNICAST_HOPS)
1056            .map(|b| b as u32)
1057    }
1058
1059    fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
1060        set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int)
1061    }
1062
1063    fn only_v6(&self) -> io::Result<bool> {
1064        get_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY).map(int2bool)
1065    }
1066
1067    fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr)
1068                         -> io::Result<()> {
1069        let mreq = ip_mreq {
1070            imr_multiaddr: ip2in_addr(multiaddr),
1071            imr_interface: ip2in_addr(interface),
1072        };
1073        set_opt(self.as_sock(), IPPROTO_IP, IP_ADD_MEMBERSHIP, mreq)
1074    }
1075
1076    #[cfg(not(target_os = "nto"))]
1077    fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32)
1078                         -> io::Result<()> {
1079        let mreq = ipv6_mreq {
1080            ipv6mr_multiaddr: ip2in6_addr(multiaddr),
1081            ipv6mr_interface: to_ipv6mr_interface(interface),
1082        };
1083        set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_ADD_MEMBERSHIP,
1084               mreq)
1085    }
1086
1087    #[cfg(target_os = "nto")]
1088    fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32)
1089                         -> io::Result<()> {
1090        Err(io::Error::new(io::ErrorKind::Unsupported, "not supported by platform"))
1091    }
1092
1093    fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr)
1094                          -> io::Result<()> {
1095        let mreq = ip_mreq {
1096            imr_multiaddr: ip2in_addr(multiaddr),
1097            imr_interface: ip2in_addr(interface),
1098        };
1099        set_opt(self.as_sock(), IPPROTO_IP, IP_DROP_MEMBERSHIP, mreq)
1100    }
1101
1102    #[cfg(not(target_os = "nto"))]
1103    fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32)
1104                          -> io::Result<()> {
1105        let mreq = ipv6_mreq {
1106            ipv6mr_multiaddr: ip2in6_addr(multiaddr),
1107            ipv6mr_interface: to_ipv6mr_interface(interface),
1108        };
1109        set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_DROP_MEMBERSHIP,
1110               mreq)
1111    }
1112
1113    #[cfg(target_os = "nto")]
1114    fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32)
1115                          -> io::Result<()> {
1116        Err(io::Error::new(io::ErrorKind::Unsupported, "not supported by platform"))
1117    }
1118
1119    fn set_read_timeout_ms(&self, dur: Option<u32>) -> io::Result<()> {
1120        set_opt(self.as_sock(), SOL_SOCKET, SO_RCVTIMEO,
1121               ms2timeout(dur))
1122    }
1123
1124    fn read_timeout_ms(&self) -> io::Result<Option<u32>> {
1125        get_opt(self.as_sock(), SOL_SOCKET, SO_RCVTIMEO)
1126            .map(timeout2ms)
1127    }
1128
1129    fn set_write_timeout_ms(&self, dur: Option<u32>) -> io::Result<()> {
1130        set_opt(self.as_sock(), SOL_SOCKET, SO_SNDTIMEO,
1131               ms2timeout(dur))
1132    }
1133
1134    fn write_timeout_ms(&self) -> io::Result<Option<u32>> {
1135        get_opt(self.as_sock(), SOL_SOCKET, SO_SNDTIMEO)
1136            .map(timeout2ms)
1137    }
1138
1139    fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
1140        self.set_read_timeout_ms(dur.map(dur2ms))
1141    }
1142
1143    fn read_timeout(&self) -> io::Result<Option<Duration>> {
1144        self.read_timeout_ms().map(|o| o.map(ms2dur))
1145    }
1146
1147    fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
1148        self.set_write_timeout_ms(dur.map(dur2ms))
1149    }
1150
1151    fn write_timeout(&self) -> io::Result<Option<Duration>> {
1152        self.write_timeout_ms().map(|o| o.map(ms2dur))
1153    }
1154
1155    fn take_error(&self) -> io::Result<Option<io::Error>> {
1156        get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err)
1157    }
1158
1159    fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
1160        do_connect(self.as_sock(), addr)
1161    }
1162
1163    #[cfg(unix)]
1164    fn send(&self, buf: &[u8]) -> io::Result<usize> {
1165        unsafe {
1166            ::cvt(send(self.as_sock() as c_int, buf.as_ptr() as *const _, buf.len(), 0)).map(|n| n as usize)
1167        }
1168    }
1169
1170     #[cfg(target_os = "wasi")]
1171    fn send(&self, buf: &[u8]) -> io::Result<usize> {
1172        let _so_datalen: *mut sys::c::size_t = &mut 0;
1173        unsafe {
1174            let _errno = libc::__wasi_sock_send(
1175                self.as_sock() as libc::__wasi_fd_t,
1176                buf.as_ptr() as *const _,
1177                buf.len(),
1178                0,
1179                _so_datalen,
1180            );
1181            // TODO: handle errno
1182            Ok((*_so_datalen) as usize)
1183        }
1184    }
1185
1186    #[cfg(windows)]
1187    fn send(&self, buf: &[u8]) -> io::Result<usize> {
1188        let len = ::std::cmp::min(buf.len(), c_int::max_value() as usize);
1189        let buf = &buf[..len];
1190        unsafe {
1191            ::cvt(send(self.as_sock(), buf.as_ptr() as *const _, len as c_int, 0))
1192                .map(|n| n as usize)
1193        }
1194    }
1195
1196    #[cfg(unix)]
1197    fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
1198        unsafe {
1199            ::cvt(recv(self.as_sock(), buf.as_mut_ptr() as *mut _, buf.len(), 0))
1200                .map(|n| n as usize)
1201        }
1202    }
1203
1204    #[cfg(target_os = "wasi")]
1205    fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
1206        let _ro_datalen: *mut sys::c::size_t = &mut 0;
1207        let _ro_flags: *mut sys::c::__wasi_roflags_t = &mut 0;
1208        unsafe {
1209            let _errno = __wasi_sock_recv(
1210                self.as_sock(),
1211                buf.as_mut_ptr() as *mut _,
1212                buf.len(),
1213                0,
1214                _ro_datalen,
1215                _ro_flags,
1216            );
1217            // TODO: handle errno
1218            Ok((*_ro_datalen) as usize)
1219        }
1220    }
1221
1222    #[cfg(windows)]
1223    fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
1224        let len = ::std::cmp::min(buf.len(), c_int::max_value() as usize);
1225        let buf = &mut buf[..len];
1226        unsafe {
1227            ::cvt(recv(self.as_sock(), buf.as_mut_ptr() as *mut _, buf.len() as c_int, 0))
1228                .map(|n| n as usize)
1229        }
1230    }
1231
1232    fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
1233        set_nonblocking(self.as_sock(), nonblocking)
1234    }
1235}
1236
1237fn do_connect<A: ToSocketAddrs>(sock: Socket, addr: A) -> io::Result<()> {
1238    let err = io::Error::new(io::ErrorKind::Other,
1239                             "no socket addresses resolved");
1240    let addrs = try!(addr.to_socket_addrs());
1241    let sys = sys::Socket::from_inner(sock);
1242    let sock = socket::Socket::from_inner(sys);
1243    let ret = addrs.fold(Err(err), |prev, addr| {
1244        prev.or_else(|_| sock.connect(&addr))
1245    });
1246    mem::forget(sock);
1247    return ret
1248}
1249
1250#[cfg(unix)]
1251fn set_nonblocking(sock: Socket, nonblocking: bool) -> io::Result<()> {
1252    let mut nonblocking = nonblocking as c_ulong;
1253    ::cvt(unsafe {
1254        ioctl(sock, FIONBIO, &mut nonblocking)
1255    }).map(|_| ())
1256}
1257
1258#[cfg(target_os = "wasi")]
1259fn set_nonblocking(_sock: Socket, _nonblocking: bool) -> io::Result<()> {
1260    Ok(())
1261}
1262
1263#[cfg(windows)]
1264fn set_nonblocking(sock: Socket, nonblocking: bool) -> io::Result<()> {
1265    let mut nonblocking = nonblocking as c_ulong;
1266    ::cvt(unsafe {
1267        ioctlsocket(sock, FIONBIO as c_int, &mut nonblocking)
1268    }).map(|_| ())
1269}
1270
1271#[cfg(any(unix, target_os = "wasi"))]
1272fn ip2in_addr(ip: &Ipv4Addr) -> in_addr {
1273    let oct = ip.octets();
1274    in_addr {
1275        s_addr: ::hton(((oct[0] as u32) << 24) |
1276                       ((oct[1] as u32) << 16) |
1277                       ((oct[2] as u32) <<  8) |
1278                       ((oct[3] as u32) <<  0)),
1279    }
1280}
1281
1282#[cfg(windows)]
1283fn ip2in_addr(ip: &Ipv4Addr) -> in_addr {
1284    let oct = ip.octets();
1285    unsafe {
1286        let mut S_un: in_addr_S_un = mem::zeroed();
1287        *S_un.S_addr_mut() = ::hton(((oct[0] as u32) << 24) |
1288                                ((oct[1] as u32) << 16) |
1289                                ((oct[2] as u32) <<  8) |
1290                                ((oct[3] as u32) <<  0));
1291        in_addr {
1292            S_un: S_un,
1293        }
1294    }
1295}
1296
1297fn in_addr2ip(ip: &in_addr) -> Ipv4Addr {
1298    let h_addr = c::in_addr_to_u32(ip);
1299
1300    let a: u8 = (h_addr >> 24) as u8;
1301    let b: u8 = (h_addr >> 16) as u8;
1302    let c: u8 = (h_addr >> 8) as u8;
1303    let d: u8 = (h_addr >> 0) as u8;
1304
1305    Ipv4Addr::new(a,b,c,d)
1306}
1307
1308#[cfg(target_os = "android")]
1309fn to_ipv6mr_interface(value: u32) -> c_int {
1310    value as c_int
1311}
1312
1313#[cfg(not(target_os = "android"))]
1314fn to_ipv6mr_interface(value: u32) -> c_uint {
1315    value as c_uint
1316}
1317
1318fn ip2in6_addr(ip: &Ipv6Addr) -> in6_addr {
1319    let mut ret: in6_addr = unsafe { mem::zeroed() };
1320    let seg = ip.segments();
1321    let bytes = [
1322        (seg[0] >> 8) as u8,
1323        (seg[0] >> 0) as u8,
1324        (seg[1] >> 8) as u8,
1325        (seg[1] >> 0) as u8,
1326        (seg[2] >> 8) as u8,
1327        (seg[2] >> 0) as u8,
1328        (seg[3] >> 8) as u8,
1329        (seg[3] >> 0) as u8,
1330        (seg[4] >> 8) as u8,
1331        (seg[4] >> 0) as u8,
1332        (seg[5] >> 8) as u8,
1333        (seg[5] >> 0) as u8,
1334        (seg[6] >> 8) as u8,
1335        (seg[6] >> 0) as u8,
1336        (seg[7] >> 8) as u8,
1337        (seg[7] >> 0) as u8,
1338    ];
1339    #[cfg(windows)] unsafe { *ret.u.Byte_mut() = bytes; }
1340    #[cfg(not(windows))]   { ret.s6_addr = bytes; }
1341
1342    return ret
1343}
1344
1345impl TcpListenerExt for TcpListener {
1346    fn set_ttl(&self, ttl: u32) -> io::Result<()> {
1347        set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int)
1348    }
1349
1350    fn ttl(&self) -> io::Result<u32> {
1351        get_opt::<c_int>(self.as_sock(), IPPROTO_IP, IP_TTL)
1352            .map(|b| b as u32)
1353    }
1354
1355    fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
1356        set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int)
1357    }
1358
1359    fn only_v6(&self) -> io::Result<bool> {
1360        get_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY).map(int2bool)
1361    }
1362
1363    fn take_error(&self) -> io::Result<Option<io::Error>> {
1364        get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err)
1365    }
1366
1367    fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
1368        set_nonblocking(self.as_sock(), nonblocking)
1369    }
1370
1371    fn set_linger(&self, dur: Option<Duration>) -> io::Result<()> {
1372        set_opt(self.as_sock(), SOL_SOCKET, SO_LINGER, dur2linger(dur))
1373    }
1374
1375    fn linger(&self) -> io::Result<Option<Duration>> {
1376        get_opt(self.as_sock(), SOL_SOCKET, SO_LINGER).map(linger2dur)
1377    }
1378}
1379
1380impl TcpBuilder {
1381    /// Sets the value for the `IP_TTL` option on this socket.
1382    ///
1383    /// This is the same as [`TcpStreamExt::set_ttl`][other].
1384    ///
1385    /// [other]: trait.TcpStreamExt.html#tymethod.set_ttl
1386    pub fn ttl(&self, ttl: u32) -> io::Result<&Self> {
1387        set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int)
1388            .map(|()| self)
1389    }
1390
1391    /// Sets the value for the `IPV6_V6ONLY` option on this socket.
1392    ///
1393    /// This is the same as [`TcpStreamExt::set_only_v6`][other].
1394    ///
1395    /// [other]: trait.TcpStreamExt.html#tymethod.set_only_v6
1396    pub fn only_v6(&self, only_v6: bool) -> io::Result<&Self> {
1397        set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int)
1398            .map(|()| self)
1399    }
1400
1401    /// Set value for the `SO_REUSEADDR` option on this socket.
1402    ///
1403    /// This indicates that further calls to `bind` may allow reuse of local
1404    /// addresses. For IPv4 sockets this means that a socket may bind even when
1405    /// there's a socket already listening on this port.
1406    pub fn reuse_address(&self, reuse: bool) -> io::Result<&Self> {
1407        set_opt(self.as_sock(), SOL_SOCKET, SO_REUSEADDR,
1408               reuse as c_int).map(|()| self)
1409    }
1410
1411    /// Check the `SO_REUSEADDR` option on this socket.
1412    pub fn get_reuse_address(&self) -> io::Result<bool> {
1413        get_opt(self.as_sock(), SOL_SOCKET, SO_REUSEADDR).map(int2bool)
1414    }
1415
1416    /// Get the value of the `SO_ERROR` option on this socket.
1417    ///
1418    /// This will retrieve the stored error in the underlying socket, clearing
1419    /// the field in the process. This can be useful for checking errors between
1420    /// calls.
1421    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
1422        get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err)
1423    }
1424
1425    /// Sets the linger option for this socket
1426    fn set_linger(&self, dur: Option<Duration>) -> io::Result<()> {
1427        set_opt(self.as_sock(), SOL_SOCKET, SO_LINGER, dur2linger(dur))
1428    }
1429
1430    /// Gets the linger option for this socket
1431    fn linger(&self) -> io::Result<Option<Duration>> {
1432        get_opt(self.as_sock(), SOL_SOCKET, SO_LINGER).map(linger2dur)
1433    }
1434}
1435
1436impl UdpBuilder {
1437    /// Sets the value for the `IP_TTL` option on this socket.
1438    ///
1439    /// This is the same as [`TcpStreamExt::set_ttl`][other].
1440    ///
1441    /// [other]: trait.TcpStreamExt.html#tymethod.set_ttl
1442    pub fn ttl(&self, ttl: u32) -> io::Result<&Self> {
1443        set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int)
1444            .map(|()| self)
1445    }
1446
1447    /// Sets the value for the `IPV6_V6ONLY` option on this socket.
1448    ///
1449    /// This is the same as [`TcpStream::only_v6`][other].
1450    ///
1451    /// [other]: struct.TcpBuilder.html#method.only_v6
1452    pub fn only_v6(&self, only_v6: bool) -> io::Result<&Self> {
1453        set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int)
1454            .map(|()| self)
1455    }
1456
1457    /// Set value for the `SO_REUSEADDR` option on this socket.
1458    ///
1459    /// This is the same as [`TcpBuilder::reuse_address`][other].
1460    ///
1461    /// [other]: struct.TcpBuilder.html#method.reuse_address
1462    pub fn reuse_address(&self, reuse: bool) -> io::Result<&Self> {
1463        set_opt(self.as_sock(), SOL_SOCKET, SO_REUSEADDR,
1464               reuse as c_int).map(|()| self)
1465    }
1466
1467    /// Check the `SO_REUSEADDR` option on this socket.
1468    pub fn get_reuse_address(&self) -> io::Result<bool> {
1469        get_opt(self.as_sock(), SOL_SOCKET, SO_REUSEADDR).map(int2bool)
1470    }
1471
1472    /// Get the value of the `SO_ERROR` option on this socket.
1473    ///
1474    /// This will retrieve the stored error in the underlying socket, clearing
1475    /// the field in the process. This can be useful for checking errors between
1476    /// calls.
1477    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
1478        get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err)
1479    }
1480}