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