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