summaryrefslogtreecommitdiffstats
path: root/third_party/rust/net2/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/net2/src
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/net2/src')
-rw-r--r--third_party/rust/net2/src/ext.rs1466
-rw-r--r--third_party/rust/net2/src/lib.rs126
-rw-r--r--third_party/rust/net2/src/socket.rs260
-rw-r--r--third_party/rust/net2/src/sys/unix/impls.rs44
-rw-r--r--third_party/rust/net2/src/sys/unix/mod.rs104
-rw-r--r--third_party/rust/net2/src/sys/wasi/impls.rs33
-rw-r--r--third_party/rust/net2/src/sys/wasi/mod.rs185
-rw-r--r--third_party/rust/net2/src/sys/windows/impls.rs44
-rw-r--r--third_party/rust/net2/src/sys/windows/mod.rs125
-rw-r--r--third_party/rust/net2/src/tcp.rs161
-rw-r--r--third_party/rust/net2/src/udp.rs89
-rw-r--r--third_party/rust/net2/src/unix.rs57
-rw-r--r--third_party/rust/net2/src/utils.rs51
13 files changed, 2745 insertions, 0 deletions
diff --git a/third_party/rust/net2/src/ext.rs b/third_party/rust/net2/src/ext.rs
new file mode 100644
index 0000000000..76e58d9b79
--- /dev/null
+++ b/third_party/rust/net2/src/ext.rs
@@ -0,0 +1,1466 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(bad_style, dead_code)]
+
+use std::io;
+use std::mem;
+use std::net::{TcpStream, TcpListener, UdpSocket, Ipv4Addr, Ipv6Addr};
+use std::net::ToSocketAddrs;
+
+use {TcpBuilder, UdpBuilder, FromInner};
+use sys;
+use sys::c;
+use socket;
+
+cfg_if! {
+ if #[cfg(any(target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "haiku",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "solaris",
+ target_os = "illumos",
+ target_env = "uclibc"))] {
+ use libc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
+ use libc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
+ } else {
+ // ...
+ }
+}
+
+use std::time::Duration;
+
+#[cfg(any(unix, target_os = "wasi"))] use libc::*;
+#[cfg(any(unix))] use std::os::unix::prelude::*;
+#[cfg(target_os = "wasi")] use std::os::wasi::prelude::*;
+#[cfg(unix)] pub type Socket = c_int;
+#[cfg(target_os = "wasi")] pub type Socket = std::os::wasi::io::RawFd;
+#[cfg(windows)] pub type Socket = SOCKET;
+#[cfg(windows)] use std::os::windows::prelude::*;
+#[cfg(any(windows, target_os = "wasi"))] use sys::c::*;
+
+#[cfg(windows)] const SIO_KEEPALIVE_VALS: DWORD = 0x98000004;
+#[cfg(windows)]
+#[repr(C)]
+struct tcp_keepalive {
+ onoff: c_ulong,
+ keepalivetime: c_ulong,
+ keepaliveinterval: c_ulong,
+}
+
+#[cfg(any(unix, target_os = "wasi"))] fn v(opt: c_int) -> c_int { opt }
+#[cfg(windows)] fn v(opt: IPPROTO) -> c_int { opt as c_int }
+
+#[cfg(target_os = "wasi")]
+pub fn set_opt<T: Copy>(_sock: Socket, _opt: c_int, _val: c_int,
+ _payload: T) -> io::Result<()> {
+ Ok(())
+}
+
+#[cfg(not(target_os = "wasi"))]
+pub fn set_opt<T: Copy>(sock: Socket, opt: c_int, val: c_int,
+ payload: T) -> io::Result<()> {
+ unsafe {
+ let payload = &payload as *const T as *const c_void;
+ try!(::cvt(setsockopt(sock, opt, val, payload as *const _,
+ mem::size_of::<T>() as socklen_t)));
+ }
+ Ok(())
+}
+
+#[cfg(target_os = "wasi")]
+pub fn get_opt<T: Copy>(_sock: Socket, _opt: c_int, _val: c_int) -> io::Result<T> {
+ unimplemented!()
+}
+#[cfg(not(target_os = "wasi"))]
+pub fn get_opt<T: Copy>(sock: Socket, opt: c_int, val: c_int) -> io::Result<T> {
+ unsafe {
+ let mut slot: T = mem::zeroed();
+ let mut len = mem::size_of::<T>() as socklen_t;
+ try!(::cvt(getsockopt(sock, opt, val,
+ &mut slot as *mut _ as *mut _,
+ &mut len)));
+ assert_eq!(len as usize, mem::size_of::<T>());
+ Ok(slot)
+ }
+}
+
+/// Extension methods for the standard [`TcpStream` type][link] in `std::net`.
+///
+/// [link]: https://doc.rust-lang.org/std/net/struct.TcpStream.html
+pub trait TcpStreamExt {
+ /// Sets the value of the `TCP_NODELAY` option on this socket.
+ ///
+ /// If set, this option disables the Nagle algorithm. This means that
+ /// segments are always sent as soon as possible, even if there is only a
+ /// small amount of data. When not set, data is buffered until there is a
+ /// sufficient amount to send out, thereby avoiding the frequent sending of
+ /// small packets.
+ fn set_nodelay(&self, nodelay: bool) -> io::Result<()>;
+
+ /// Gets the value of the `TCP_NODELAY` option on this socket.
+ ///
+ /// For more information about this option, see [`set_nodelay`][link].
+ ///
+ /// [link]: #tymethod.set_nodelay
+ fn nodelay(&self) -> io::Result<bool>;
+
+ /// Sets the value of the `SO_RCVBUF` option on this socket.
+ ///
+ /// Changes the size of the operating system's receive buffer associated with the socket.
+ fn set_recv_buffer_size(&self, size: usize) -> io::Result<()>;
+
+ /// Gets the value of the `SO_RCVBUF` option on this socket.
+ ///
+ /// For more information about this option, see [`set_recv_buffer_size`][link].
+ ///
+ /// [link]: #tymethod.set_recv_buffer_size
+ fn recv_buffer_size(&self) -> io::Result<usize>;
+
+ /// Sets the value of the `SO_SNDBUF` option on this socket.
+ ///
+ /// Changes the size of the operating system's send buffer associated with the socket.
+ fn set_send_buffer_size(&self, size: usize) -> io::Result<()>;
+
+ /// Gets the value of the `SO_SNDBUF` option on this socket.
+ ///
+ /// For more information about this option, see [`set_send_buffer`][link].
+ ///
+ /// [link]: #tymethod.set_send_buffer
+ fn send_buffer_size(&self) -> io::Result<usize>;
+
+ /// Sets whether keepalive messages are enabled to be sent on this socket.
+ ///
+ /// On Unix, this option will set the `SO_KEEPALIVE` as well as the
+ /// `TCP_KEEPALIVE` or `TCP_KEEPIDLE` option (depending on your platform).
+ /// On Windows, this will set the `SIO_KEEPALIVE_VALS` option.
+ ///
+ /// If `None` is specified then keepalive messages are disabled, otherwise
+ /// the number of milliseconds specified will be the time to remain idle
+ /// before sending a TCP keepalive probe.
+ ///
+ /// Some platforms specify this value in seconds, so sub-second millisecond
+ /// specifications may be omitted.
+ fn set_keepalive_ms(&self, keepalive: Option<u32>) -> io::Result<()>;
+
+ /// Returns whether keepalive messages are enabled on this socket, and if so
+ /// the amount of milliseconds between them.
+ ///
+ /// For more information about this option, see [`set_keepalive_ms`][link].
+ ///
+ /// [link]: #tymethod.set_keepalive_ms
+ fn keepalive_ms(&self) -> io::Result<Option<u32>>;
+
+ /// Sets whether keepalive messages are enabled to be sent on this socket.
+ ///
+ /// On Unix, this option will set the `SO_KEEPALIVE` as well as the
+ /// `TCP_KEEPALIVE` or `TCP_KEEPIDLE` option (depending on your platform).
+ /// On Windows, this will set the `SIO_KEEPALIVE_VALS` option.
+ ///
+ /// If `None` is specified then keepalive messages are disabled, otherwise
+ /// the duration specified will be the time to remain idle before sending a
+ /// TCP keepalive probe.
+ ///
+ /// Some platforms specify this value in seconds, so sub-second
+ /// specifications may be omitted.
+ fn set_keepalive(&self, keepalive: Option<Duration>) -> io::Result<()>;
+
+ /// Returns whether keepalive messages are enabled on this socket, and if so
+ /// the duration of time between them.
+ ///
+ /// For more information about this option, see [`set_keepalive`][link].
+ ///
+ /// [link]: #tymethod.set_keepalive
+ fn keepalive(&self) -> io::Result<Option<Duration>>;
+
+ /// Sets the `SO_RCVTIMEO` option for this socket.
+ ///
+ /// This option specifies the timeout, in milliseconds, of how long calls to
+ /// this socket's `read` function will wait before returning a timeout. A
+ /// value of `None` means that no read timeout should be specified and
+ /// otherwise `Some` indicates the number of milliseconds for the timeout.
+ fn set_read_timeout_ms(&self, val: Option<u32>) -> io::Result<()>;
+
+ /// Sets the `SO_RCVTIMEO` option for this socket.
+ ///
+ /// This option specifies the timeout of how long calls to this socket's
+ /// `read` function will wait before returning a timeout. A value of `None`
+ /// means that no read timeout should be specified and otherwise `Some`
+ /// indicates the number of duration of the timeout.
+ fn set_read_timeout(&self, val: Option<Duration>) -> io::Result<()>;
+
+ /// Gets the value of the `SO_RCVTIMEO` option for this socket.
+ ///
+ /// For more information about this option, see [`set_read_timeout_ms`][link].
+ ///
+ /// [link]: #tymethod.set_read_timeout_ms
+ fn read_timeout_ms(&self) -> io::Result<Option<u32>>;
+
+ /// Gets the value of the `SO_RCVTIMEO` option for this socket.
+ ///
+ /// For more information about this option, see [`set_read_timeout`][link].
+ ///
+ /// [link]: #tymethod.set_read_timeout
+ fn read_timeout(&self) -> io::Result<Option<Duration>>;
+
+ /// Sets the `SO_SNDTIMEO` option for this socket.
+ ///
+ /// This option specifies the timeout, in milliseconds, of how long calls to
+ /// this socket's `write` function will wait before returning a timeout. A
+ /// value of `None` means that no read timeout should be specified and
+ /// otherwise `Some` indicates the number of milliseconds for the timeout.
+ fn set_write_timeout_ms(&self, val: Option<u32>) -> io::Result<()>;
+
+ /// Sets the `SO_SNDTIMEO` option for this socket.
+ ///
+ /// This option specifies the timeout of how long calls to this socket's
+ /// `write` function will wait before returning a timeout. A value of `None`
+ /// means that no read timeout should be specified and otherwise `Some`
+ /// indicates the duration of the timeout.
+ fn set_write_timeout(&self, val: Option<Duration>) -> io::Result<()>;
+
+ /// Gets the value of the `SO_SNDTIMEO` option for this socket.
+ ///
+ /// For more information about this option, see [`set_write_timeout_ms`][link].
+ ///
+ /// [link]: #tymethod.set_write_timeout_ms
+ fn write_timeout_ms(&self) -> io::Result<Option<u32>>;
+
+ /// Gets the value of the `SO_SNDTIMEO` option for this socket.
+ ///
+ /// For more information about this option, see [`set_write_timeout`][link].
+ ///
+ /// [link]: #tymethod.set_write_timeout
+ fn write_timeout(&self) -> io::Result<Option<Duration>>;
+
+ /// Sets the value for the `IP_TTL` option on this socket.
+ ///
+ /// This value sets the time-to-live field that is used in every packet sent
+ /// from this socket.
+ fn set_ttl(&self, ttl: u32) -> io::Result<()>;
+
+ /// Gets the value of the `IP_TTL` option for this socket.
+ ///
+ /// For more information about this option, see [`set_ttl`][link].
+ ///
+ /// [link]: #tymethod.set_ttl
+ fn ttl(&self) -> io::Result<u32>;
+
+ /// Sets the value for the `IPV6_V6ONLY` option on this socket.
+ ///
+ /// If this is set to `true` then the socket is restricted to sending and
+ /// receiving IPv6 packets only. In this case two IPv4 and IPv6 applications
+ /// can bind the same port at the same time.
+ ///
+ /// If this is set to `false` then the socket can be used to send and
+ /// receive packets from an IPv4-mapped IPv6 address.
+ fn set_only_v6(&self, only_v6: bool) -> io::Result<()>;
+
+ /// Gets the value of the `IPV6_V6ONLY` option for this socket.
+ ///
+ /// For more information about this option, see [`set_only_v6`][link].
+ ///
+ /// [link]: #tymethod.set_only_v6
+ fn only_v6(&self) -> io::Result<bool>;
+
+ /// Executes a `connect` operation on this socket, establishing a connection
+ /// to the host specified by `addr`.
+ ///
+ /// Note that this normally does not need to be called on a `TcpStream`,
+ /// it's typically automatically done as part of a normal
+ /// `TcpStream::connect` function call or `TcpBuilder::connect` method call.
+ ///
+ /// This should only be necessary if an unconnected socket was extracted
+ /// from a `TcpBuilder` and then needs to be connected.
+ fn connect<T: ToSocketAddrs>(&self, addr: T) -> io::Result<()>;
+
+ /// Get the value of the `SO_ERROR` option on this socket.
+ ///
+ /// This will retrieve the stored error in the underlying socket, clearing
+ /// the field in the process. This can be useful for checking errors between
+ /// calls.
+ fn take_error(&self) -> io::Result<Option<io::Error>>;
+
+ /// Moves this TCP stream into or out of nonblocking mode.
+ ///
+ /// On Unix this corresponds to calling fcntl, and on Windows this
+ /// corresponds to calling ioctlsocket.
+ fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()>;
+
+ /// Sets the linger duration of this socket by setting the SO_LINGER option
+ fn set_linger(&self, dur: Option<Duration>) -> io::Result<()>;
+
+ /// reads the linger duration for this socket by getting the SO_LINGER option
+ fn linger(&self) -> io::Result<Option<Duration>>;
+}
+
+/// Extension methods for the standard [`TcpListener` type][link] in `std::net`.
+///
+/// [link]: https://doc.rust-lang.org/std/net/struct.TcpListener.html
+pub trait TcpListenerExt {
+ /// Sets the value for the `IP_TTL` option on this socket.
+ ///
+ /// This is the same as [`TcpStreamExt::set_ttl`][other].
+ ///
+ /// [other]: trait.TcpStreamExt.html#tymethod.set_ttl
+ fn set_ttl(&self, ttl: u32) -> io::Result<()>;
+
+ /// Gets the value of the `IP_TTL` option for this socket.
+ ///
+ /// For more information about this option, see
+ /// [`TcpStreamExt::set_ttl`][link].
+ ///
+ /// [link]: trait.TcpStreamExt.html#tymethod.set_ttl
+ fn ttl(&self) -> io::Result<u32>;
+
+ /// Sets the value for the `IPV6_V6ONLY` option on this socket.
+ ///
+ /// For more information about this option, see
+ /// [`TcpStreamExt::set_only_v6`][link].
+ ///
+ /// [link]: trait.TcpStreamExt.html#tymethod.set_only_v6
+ fn set_only_v6(&self, only_v6: bool) -> io::Result<()>;
+
+ /// Gets the value of the `IPV6_V6ONLY` option for this socket.
+ ///
+ /// For more information about this option, see
+ /// [`TcpStreamExt::set_only_v6`][link].
+ ///
+ /// [link]: trait.TcpStreamExt.html#tymethod.set_only_v6
+ fn only_v6(&self) -> io::Result<bool>;
+
+ /// Get the value of the `SO_ERROR` option on this socket.
+ ///
+ /// This will retrieve the stored error in the underlying socket, clearing
+ /// the field in the process. This can be useful for checking errors between
+ /// calls.
+ fn take_error(&self) -> io::Result<Option<io::Error>>;
+
+ /// Moves this TCP listener into or out of nonblocking mode.
+ ///
+ /// For more information about this option, see
+ /// [`TcpStreamExt::set_nonblocking`][link].
+ ///
+ /// [link]: trait.TcpStreamExt.html#tymethod.set_nonblocking
+ fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()>;
+
+ /// Sets the linger duration of this socket by setting the SO_LINGER option
+ fn set_linger(&self, dur: Option<Duration>) -> io::Result<()>;
+
+ /// reads the linger duration for this socket by getting the SO_LINGER option
+ fn linger(&self) -> io::Result<Option<Duration>>;
+}
+
+/// Extension methods for the standard [`UdpSocket` type][link] in `std::net`.
+///
+/// [link]: https://doc.rust-lang.org/std/net/struct.UdpSocket.html
+pub trait UdpSocketExt {
+ /// Sets the value of the `SO_RCVBUF` option on this socket.
+ ///
+ /// Changes the size of the operating system's receive buffer associated with the socket.
+ fn set_recv_buffer_size(&self, size: usize) -> io::Result<()>;
+
+ /// Gets the value of the `SO_RCVBUF` option on this socket.
+ ///
+ /// For more information about this option, see [`set_recv_buffer_size`][link].
+ ///
+ /// [link]: #tymethod.set_recv_buffer_size
+ fn recv_buffer_size(&self) -> io::Result<usize>;
+
+ /// Sets the value of the `SO_SNDBUF` option on this socket.
+ ///
+ /// Changes the size of the operating system's send buffer associated with the socket.
+ fn set_send_buffer_size(&self, size: usize) -> io::Result<()>;
+
+ /// Gets the value of the `SO_SNDBUF` option on this socket.
+ ///
+ /// For more information about this option, see [`set_send_buffer`][link].
+ ///
+ /// [link]: #tymethod.set_send_buffer
+ fn send_buffer_size(&self) -> io::Result<usize>;
+
+ /// Sets the value of the `SO_BROADCAST` option for this socket.
+ ///
+ /// When enabled, this socket is allowed to send packets to a broadcast
+ /// address.
+ fn set_broadcast(&self, broadcast: bool) -> io::Result<()>;
+
+ /// Gets the value of the `SO_BROADCAST` option for this socket.
+ ///
+ /// For more information about this option, see
+ /// [`set_broadcast`][link].
+ ///
+ /// [link]: #tymethod.set_broadcast
+ fn broadcast(&self) -> io::Result<bool>;
+
+ /// Sets the value of the `IP_MULTICAST_LOOP` option for this socket.
+ ///
+ /// If enabled, multicast packets will be looped back to the local socket.
+ /// Note that this may not have any affect on IPv6 sockets.
+ fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()>;
+
+ /// Gets the value of the `IP_MULTICAST_LOOP` option for this socket.
+ ///
+ /// For more information about this option, see
+ /// [`set_multicast_loop_v4`][link].
+ ///
+ /// [link]: #tymethod.set_multicast_loop_v4
+ fn multicast_loop_v4(&self) -> io::Result<bool>;
+
+ /// Sets the value of the `IP_MULTICAST_TTL` option for this socket.
+ ///
+ /// Indicates the time-to-live value of outgoing multicast packets for
+ /// this socket. The default value is 1 which means that multicast packets
+ /// don't leave the local network unless explicitly requested.
+ ///
+ /// Note that this may not have any affect on IPv6 sockets.
+ fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()>;
+
+ /// Gets the value of the `IP_MULTICAST_TTL` option for this socket.
+ ///
+ /// For more information about this option, see
+ /// [`set_multicast_ttl_v4`][link].
+ ///
+ /// [link]: #tymethod.set_multicast_ttl_v4
+ fn multicast_ttl_v4(&self) -> io::Result<u32>;
+
+ /// Sets the value of the `IPV6_MULTICAST_HOPS` option for this socket
+ fn set_multicast_hops_v6(&self, hops: u32) -> io::Result<()>;
+
+ /// Gets the value of the `IPV6_MULTICAST_HOPS` option for this socket
+ fn multicast_hops_v6(&self) -> io::Result<u32>;
+
+ /// Sets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
+ ///
+ /// Controls whether this socket sees the multicast packets it sends itself.
+ /// Note that this may not have any affect on IPv4 sockets.
+ fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()>;
+
+ /// Gets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
+ ///
+ /// For more information about this option, see
+ /// [`set_multicast_loop_v6`][link].
+ ///
+ /// [link]: #tymethod.set_multicast_loop_v6
+ fn multicast_loop_v6(&self) -> io::Result<bool>;
+
+ /// Sets the value of the `IP_MULTICAST_IF` option for this socket.
+ ///
+ /// Specifies the interface to use for routing multicast packets.
+ fn set_multicast_if_v4(&self, interface: &Ipv4Addr) -> io::Result<()>;
+
+ /// Gets the value of the `IP_MULTICAST_IF` option for this socket.
+ ///
+ /// Returns the interface to use for routing multicast packets.
+ fn multicast_if_v4(&self) -> io::Result<Ipv4Addr>;
+
+
+ /// Sets the value of the `IPV6_MULTICAST_IF` option for this socket.
+ ///
+ /// Specifies the interface to use for routing multicast packets.
+ fn set_multicast_if_v6(&self, interface: u32) -> io::Result<()>;
+
+ /// Gets the value of the `IPV6_MULTICAST_IF` option for this socket.
+ ///
+ /// Returns the interface to use for routing multicast packets.
+ fn multicast_if_v6(&self) -> io::Result<u32>;
+
+ /// Sets the value for the `IP_TTL` option on this socket.
+ ///
+ /// This is the same as [`TcpStreamExt::set_ttl`][other].
+ ///
+ /// [other]: trait.TcpStreamExt.html#tymethod.set_ttl
+ fn set_ttl(&self, ttl: u32) -> io::Result<()>;
+
+ /// Gets the value of the `IP_TTL` option for this socket.
+ ///
+ /// For more information about this option, see
+ /// [`TcpStreamExt::set_ttl`][link].
+ ///
+ /// [link]: trait.TcpStreamExt.html#tymethod.set_ttl
+ fn ttl(&self) -> io::Result<u32>;
+
+ /// Sets the value for the `IPV6_UNICAST_HOPS` option on this socket.
+ ///
+ /// Specifies the hop limit for ipv6 unicast packets
+ fn set_unicast_hops_v6(&self, ttl: u32) -> io::Result<()>;
+
+ /// Gets the value of the `IPV6_UNICAST_HOPS` option for this socket.
+ ///
+ /// Specifies the hop limit for ipv6 unicast packets
+ fn unicast_hops_v6(&self) -> io::Result<u32>;
+
+ /// Sets the value for the `IPV6_V6ONLY` option on this socket.
+ ///
+ /// For more information about this option, see
+ /// [`TcpStreamExt::set_only_v6`][link].
+ ///
+ /// [link]: trait.TcpStreamExt.html#tymethod.set_only_v6
+ fn set_only_v6(&self, only_v6: bool) -> io::Result<()>;
+
+ /// Gets the value of the `IPV6_V6ONLY` option for this socket.
+ ///
+ /// For more information about this option, see
+ /// [`TcpStreamExt::set_only_v6`][link].
+ ///
+ /// [link]: trait.TcpStreamExt.html#tymethod.set_only_v6
+ fn only_v6(&self) -> io::Result<bool>;
+
+ /// Executes an operation of the `IP_ADD_MEMBERSHIP` type.
+ ///
+ /// This function specifies a new multicast group for this socket to join.
+ /// The address must be a valid multicast address, and `interface` is the
+ /// address of the local interface with which the system should join the
+ /// multicast group. If it's equal to `INADDR_ANY` then an appropriate
+ /// interface is chosen by the system.
+ fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr)
+ -> io::Result<()>;
+
+ /// Executes an operation of the `IPV6_ADD_MEMBERSHIP` type.
+ ///
+ /// This function specifies a new multicast group for this socket to join.
+ /// The address must be a valid multicast address, and `interface` is the
+ /// index of the interface to join/leave (or 0 to indicate any interface).
+ fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32)
+ -> io::Result<()>;
+
+ /// Executes an operation of the `IP_DROP_MEMBERSHIP` type.
+ ///
+ /// For more information about this option, see
+ /// [`join_multicast_v4`][link].
+ ///
+ /// [link]: #tymethod.join_multicast_v4
+ fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr)
+ -> io::Result<()>;
+
+ /// Executes an operation of the `IPV6_DROP_MEMBERSHIP` type.
+ ///
+ /// For more information about this option, see
+ /// [`join_multicast_v6`][link].
+ ///
+ /// [link]: #tymethod.join_multicast_v6
+ fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32)
+ -> io::Result<()>;
+
+ /// Sets the `SO_RCVTIMEO` option for this socket.
+ ///
+ /// This option specifies the timeout, in milliseconds, of how long calls to
+ /// this socket's `read` function will wait before returning a timeout. A
+ /// value of `None` means that no read timeout should be specified and
+ /// otherwise `Some` indicates the number of milliseconds for the timeout.
+ fn set_read_timeout_ms(&self, val: Option<u32>) -> io::Result<()>;
+
+ /// Sets the `SO_RCVTIMEO` option for this socket.
+ ///
+ /// This option specifies the timeout of how long calls to this socket's
+ /// `read` function will wait before returning a timeout. A value of `None`
+ /// means that no read timeout should be specified and otherwise `Some`
+ /// indicates the number of duration of the timeout.
+ fn set_read_timeout(&self, val: Option<Duration>) -> io::Result<()>;
+
+ /// Gets the value of the `SO_RCVTIMEO` option for this socket.
+ ///
+ /// For more information about this option, see [`set_read_timeout_ms`][link].
+ ///
+ /// [link]: #tymethod.set_read_timeout_ms
+ fn read_timeout_ms(&self) -> io::Result<Option<u32>>;
+
+ /// Gets the value of the `SO_RCVTIMEO` option for this socket.
+ ///
+ /// For more information about this option, see [`set_read_timeout`][link].
+ ///
+ /// [link]: #tymethod.set_read_timeout
+ fn read_timeout(&self) -> io::Result<Option<Duration>>;
+
+ /// Sets the `SO_SNDTIMEO` option for this socket.
+ ///
+ /// This option specifies the timeout, in milliseconds, of how long calls to
+ /// this socket's `write` function will wait before returning a timeout. A
+ /// value of `None` means that no read timeout should be specified and
+ /// otherwise `Some` indicates the number of milliseconds for the timeout.
+ fn set_write_timeout_ms(&self, val: Option<u32>) -> io::Result<()>;
+
+ /// Sets the `SO_SNDTIMEO` option for this socket.
+ ///
+ /// This option specifies the timeout of how long calls to this socket's
+ /// `write` function will wait before returning a timeout. A value of `None`
+ /// means that no read timeout should be specified and otherwise `Some`
+ /// indicates the duration of the timeout.
+ fn set_write_timeout(&self, val: Option<Duration>) -> io::Result<()>;
+
+ /// Gets the value of the `SO_SNDTIMEO` option for this socket.
+ ///
+ /// For more information about this option, see [`set_write_timeout_ms`][link].
+ ///
+ /// [link]: #tymethod.set_write_timeout_ms
+ fn write_timeout_ms(&self) -> io::Result<Option<u32>>;
+
+ /// Gets the value of the `SO_SNDTIMEO` option for this socket.
+ ///
+ /// For more information about this option, see [`set_write_timeout`][link].
+ ///
+ /// [link]: #tymethod.set_write_timeout
+ fn write_timeout(&self) -> io::Result<Option<Duration>>;
+
+ /// Get the value of the `SO_ERROR` option on this socket.
+ ///
+ /// This will retrieve the stored error in the underlying socket, clearing
+ /// the field in the process. This can be useful for checking errors between
+ /// calls.
+ fn take_error(&self) -> io::Result<Option<io::Error>>;
+
+ /// Connects this UDP socket to a remote address, allowing the `send` and
+ /// `recv` syscalls to be used to send data and also applies filters to only
+ /// receive data from the specified address.
+ fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()>;
+
+ /// Sends data on the socket to the remote address to which it is connected.
+ ///
+ /// The `connect` method will connect this socket to a remote address. This
+ /// method will fail if the socket is not connected.
+ fn send(&self, buf: &[u8]) -> io::Result<usize>;
+
+ /// Receives data on the socket from the remote address to which it is
+ /// connected.
+ ///
+ /// The `connect` method will connect this socket to a remote address. This
+ /// method will fail if the socket is not connected.
+ fn recv(&self, buf: &mut [u8]) -> io::Result<usize>;
+
+ /// Moves this UDP socket into or out of nonblocking mode.
+ ///
+ /// For more information about this option, see
+ /// [`TcpStreamExt::set_nonblocking`][link].
+ ///
+ /// [link]: trait.TcpStreamExt.html#tymethod.set_nonblocking
+ fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()>;
+}
+
+#[doc(hidden)]
+pub trait AsSock {
+ fn as_sock(&self) -> Socket;
+}
+
+#[cfg(any(unix, target_os = "wasi"))]
+impl<T: AsRawFd> AsSock for T {
+ fn as_sock(&self) -> Socket { self.as_raw_fd() }
+}
+#[cfg(windows)]
+impl<T: AsRawSocket> AsSock for T {
+ fn as_sock(&self) -> Socket { self.as_raw_socket() as Socket }
+}
+
+cfg_if! {
+ if #[cfg(any(target_os = "macos", target_os = "ios"))] {
+ use libc::TCP_KEEPALIVE as KEEPALIVE_OPTION;
+ } else if #[cfg(any(target_os = "haiku", target_os = "netbsd", target_os = "openbsd"))] {
+ use libc::SO_KEEPALIVE as KEEPALIVE_OPTION;
+ } else if #[cfg(unix)] {
+ use libc::TCP_KEEPIDLE as KEEPALIVE_OPTION;
+ } else {
+ // ...
+ }
+}
+
+impl TcpStreamExt for TcpStream {
+
+ fn set_recv_buffer_size(&self, size: usize) -> io::Result<()> {
+ // TODO: casting usize to a c_int should be a checked cast
+ set_opt(self.as_sock(), SOL_SOCKET, SO_RCVBUF, size as c_int)
+ }
+
+ fn recv_buffer_size(&self) -> io::Result<usize> {
+ get_opt(self.as_sock(), SOL_SOCKET, SO_RCVBUF).map(int2usize)
+ }
+
+ fn set_send_buffer_size(&self, size: usize) -> io::Result<()> {
+ set_opt(self.as_sock(), SOL_SOCKET, SO_SNDBUF, size as c_int)
+ }
+
+ fn send_buffer_size(&self) -> io::Result<usize> {
+ get_opt(self.as_sock(), SOL_SOCKET, SO_SNDBUF).map(int2usize)
+ }
+
+ fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
+ set_opt(self.as_sock(), v(IPPROTO_TCP), TCP_NODELAY,
+ nodelay as c_int)
+ }
+ fn nodelay(&self) -> io::Result<bool> {
+ get_opt(self.as_sock(), v(IPPROTO_TCP), TCP_NODELAY)
+ .map(int2bool)
+ }
+
+ fn set_keepalive(&self, keepalive: Option<Duration>) -> io::Result<()> {
+ self.set_keepalive_ms(keepalive.map(dur2ms))
+ }
+
+ fn keepalive(&self) -> io::Result<Option<Duration>> {
+ self.keepalive_ms().map(|o| o.map(ms2dur))
+ }
+
+ #[cfg(unix)]
+ fn set_keepalive_ms(&self, keepalive: Option<u32>) -> io::Result<()> {
+ try!(set_opt(self.as_sock(), SOL_SOCKET, SO_KEEPALIVE,
+ keepalive.is_some() as c_int));
+ if let Some(dur) = keepalive {
+ try!(set_opt(self.as_sock(), v(IPPROTO_TCP), KEEPALIVE_OPTION,
+ (dur / 1000) as c_int));
+ }
+ Ok(())
+ }
+
+ #[cfg(unix)]
+ fn keepalive_ms(&self) -> io::Result<Option<u32>> {
+ let keepalive = try!(get_opt::<c_int>(self.as_sock(), SOL_SOCKET,
+ SO_KEEPALIVE));
+ if keepalive == 0 {
+ return Ok(None)
+ }
+ let secs = try!(get_opt::<c_int>(self.as_sock(), v(IPPROTO_TCP),
+ KEEPALIVE_OPTION));
+ Ok(Some((secs as u32) * 1000))
+ }
+
+ #[cfg(target_os = "wasi")]
+ fn set_keepalive_ms(&self, _keepalive: Option<u32>) -> io::Result<()> {
+ unimplemented!()
+ }
+
+ #[cfg(target_os = "wasi")]
+ fn keepalive_ms(&self) -> io::Result<Option<u32>> {
+ unimplemented!()
+ }
+
+ #[cfg(windows)]
+ fn set_keepalive_ms(&self, keepalive: Option<u32>) -> io::Result<()> {
+ let ms = keepalive.unwrap_or(INFINITE);
+ let ka = tcp_keepalive {
+ onoff: keepalive.is_some() as c_ulong,
+ keepalivetime: ms as c_ulong,
+ keepaliveinterval: ms as c_ulong,
+ };
+ unsafe {
+ ::cvt_win(WSAIoctl(self.as_sock(),
+ SIO_KEEPALIVE_VALS,
+ &ka as *const _ as *mut _,
+ mem::size_of_val(&ka) as DWORD,
+ 0 as *mut _,
+ 0,
+ 0 as *mut _,
+ 0 as *mut _,
+ None)).map(|_| ())
+ }
+ }
+
+ #[cfg(windows)]
+ fn keepalive_ms(&self) -> io::Result<Option<u32>> {
+ let mut ka = tcp_keepalive {
+ onoff: 0,
+ keepalivetime: 0,
+ keepaliveinterval: 0,
+ };
+ unsafe {
+ try!(::cvt_win(WSAIoctl(self.as_sock(),
+ SIO_KEEPALIVE_VALS,
+ 0 as *mut _,
+ 0,
+ &mut ka as *mut _ as *mut _,
+ mem::size_of_val(&ka) as DWORD,
+ 0 as *mut _,
+ 0 as *mut _,
+ None)));
+ }
+ Ok({
+ if ka.onoff == 0 {
+ None
+ } else {
+ timeout2ms(ka.keepaliveinterval as DWORD)
+ }
+ })
+ }
+
+ fn set_read_timeout_ms(&self, dur: Option<u32>) -> io::Result<()> {
+ set_opt(self.as_sock(), SOL_SOCKET, SO_RCVTIMEO,
+ ms2timeout(dur))
+ }
+
+ fn read_timeout_ms(&self) -> io::Result<Option<u32>> {
+ get_opt(self.as_sock(), SOL_SOCKET, SO_RCVTIMEO)
+ .map(timeout2ms)
+ }
+
+ fn set_write_timeout_ms(&self, dur: Option<u32>) -> io::Result<()> {
+ set_opt(self.as_sock(), SOL_SOCKET, SO_SNDTIMEO,
+ ms2timeout(dur))
+ }
+
+ fn write_timeout_ms(&self) -> io::Result<Option<u32>> {
+ get_opt(self.as_sock(), SOL_SOCKET, SO_SNDTIMEO)
+ .map(timeout2ms)
+ }
+
+ fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
+ self.set_read_timeout_ms(dur.map(dur2ms))
+ }
+
+ fn read_timeout(&self) -> io::Result<Option<Duration>> {
+ self.read_timeout_ms().map(|o| o.map(ms2dur))
+ }
+
+ fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
+ self.set_write_timeout_ms(dur.map(dur2ms))
+ }
+
+ fn write_timeout(&self) -> io::Result<Option<Duration>> {
+ self.write_timeout_ms().map(|o| o.map(ms2dur))
+ }
+
+ fn set_ttl(&self, ttl: u32) -> io::Result<()> {
+ set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int)
+ }
+
+ fn ttl(&self) -> io::Result<u32> {
+ get_opt::<c_int>(self.as_sock(), IPPROTO_IP, IP_TTL)
+ .map(|b| b as u32)
+ }
+
+ fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
+ set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int)
+ }
+
+ fn only_v6(&self) -> io::Result<bool> {
+ get_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY).map(int2bool)
+ }
+
+ fn connect<T: ToSocketAddrs>(&self, addr: T) -> io::Result<()> {
+ do_connect(self.as_sock(), addr)
+ }
+
+ fn take_error(&self) -> io::Result<Option<io::Error>> {
+ get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err)
+ }
+
+ fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
+ set_nonblocking(self.as_sock(), nonblocking)
+ }
+
+ fn set_linger(&self, dur: Option<Duration>) -> io::Result<()> {
+ set_opt(self.as_sock(), SOL_SOCKET, SO_LINGER, dur2linger(dur))
+ }
+
+ fn linger(&self) -> io::Result<Option<Duration>> {
+ get_opt(self.as_sock(), SOL_SOCKET, SO_LINGER).map(linger2dur)
+ }
+}
+
+#[cfg(any(unix, target_os = "wasi"))]
+fn ms2timeout(dur: Option<u32>) -> timeval {
+ // TODO: be more rigorous
+ match dur {
+ Some(d) => timeval {
+ tv_sec: (d / 1000) as time_t,
+ tv_usec: (d % 1000) as suseconds_t,
+ },
+ None => timeval { tv_sec: 0, tv_usec: 0 },
+ }
+}
+
+#[cfg(any(unix, target_os = "wasi"))]
+fn timeout2ms(dur: timeval) -> Option<u32> {
+ if dur.tv_sec == 0 && dur.tv_usec == 0 {
+ None
+ } else {
+ Some(dur.tv_sec as u32 * 1000 + dur.tv_usec as u32 / 1000)
+ }
+}
+
+#[cfg(windows)]
+fn ms2timeout(dur: Option<u32>) -> DWORD {
+ dur.unwrap_or(0)
+}
+
+#[cfg(windows)]
+fn timeout2ms(dur: DWORD) -> Option<u32> {
+ if dur == 0 {
+ None
+ } else {
+ Some(dur)
+ }
+}
+
+fn linger2dur(linger_opt: linger) -> Option<Duration> {
+ if linger_opt.l_onoff == 0 {
+ None
+ }
+ else {
+ Some(Duration::from_secs(linger_opt.l_linger as u64))
+ }
+}
+
+#[cfg(windows)]
+fn dur2linger(dur: Option<Duration>) -> linger {
+ match dur {
+ Some(d) => {
+ linger {
+ l_onoff: 1,
+ l_linger: d.as_secs() as u16,
+ }
+ },
+ None => linger { l_onoff: 0, l_linger: 0 },
+ }
+}
+
+#[cfg(any(unix, target_os = "wasi"))]
+fn dur2linger(dur: Option<Duration>) -> linger {
+ match dur {
+ Some(d) => {
+ linger {
+ l_onoff: 1,
+ l_linger: d.as_secs() as c_int,
+ }
+ },
+ None => linger { l_onoff: 0, l_linger: 0 },
+ }
+}
+
+fn ms2dur(ms: u32) -> Duration {
+ Duration::new((ms as u64) / 1000, (ms as u32) % 1000 * 1_000_000)
+}
+
+fn dur2ms(dur: Duration) -> u32 {
+ (dur.as_secs() as u32 * 1000) + (dur.subsec_nanos() / 1_000_000)
+}
+
+pub fn int2bool(n: c_int) -> bool {
+ if n == 0 {false} else {true}
+}
+
+pub fn int2usize(n: c_int) -> usize {
+ // TODO: casting c_int to a usize should be a checked cast
+ n as usize
+}
+
+pub fn int2err(n: c_int) -> Option<io::Error> {
+ if n == 0 {
+ None
+ } else {
+ Some(io::Error::from_raw_os_error(n as i32))
+ }
+}
+
+impl UdpSocketExt for UdpSocket {
+
+ fn set_recv_buffer_size(&self, size: usize) -> io::Result<()> {
+ set_opt(self.as_sock(), SOL_SOCKET, SO_RCVBUF, size as c_int)
+ }
+
+ fn recv_buffer_size(&self) -> io::Result<usize> {
+ get_opt(self.as_sock(), SOL_SOCKET, SO_RCVBUF).map(int2usize)
+ }
+
+ fn set_send_buffer_size(&self, size: usize) -> io::Result<()> {
+ set_opt(self.as_sock(), SOL_SOCKET, SO_SNDBUF, size as c_int)
+ }
+
+ fn send_buffer_size(&self) -> io::Result<usize> {
+ get_opt(self.as_sock(), SOL_SOCKET, SO_SNDBUF).map(int2usize)
+ }
+
+ fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
+ set_opt(self.as_sock(), SOL_SOCKET, SO_BROADCAST,
+ broadcast as c_int)
+ }
+ fn broadcast(&self) -> io::Result<bool> {
+ get_opt(self.as_sock(), SOL_SOCKET, SO_BROADCAST)
+ .map(int2bool)
+ }
+ fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
+ set_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_LOOP,
+ multicast_loop_v4 as c_int)
+ }
+ fn multicast_loop_v4(&self) -> io::Result<bool> {
+ get_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_LOOP)
+ .map(int2bool)
+ }
+
+ fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
+ set_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_TTL,
+ multicast_ttl_v4 as c_int)
+ }
+
+ fn multicast_ttl_v4(&self) -> io::Result<u32> {
+ get_opt::<c_int>(self.as_sock(), IPPROTO_IP, IP_MULTICAST_TTL)
+ .map(|b| b as u32)
+ }
+
+ fn set_multicast_hops_v6(&self, _hops: u32) -> io::Result<()> {
+ set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_HOPS,
+ _hops as c_int)
+ }
+
+ fn multicast_hops_v6(&self) -> io::Result<u32> {
+ get_opt::<c_int>(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_HOPS)
+ .map(|b| b as u32)
+ }
+
+ fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
+ set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_LOOP,
+ multicast_loop_v6 as c_int)
+ }
+ fn multicast_loop_v6(&self) -> io::Result<bool> {
+ get_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_LOOP)
+ .map(int2bool)
+ }
+
+ fn set_multicast_if_v4(&self, _interface: &Ipv4Addr) -> io::Result<()> {
+ set_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_IF, ip2in_addr(_interface))
+ }
+
+ fn multicast_if_v4(&self) -> io::Result<Ipv4Addr> {
+ get_opt(self.as_sock(), IPPROTO_IP, IP_MULTICAST_IF).map(in_addr2ip)
+ }
+
+ fn set_multicast_if_v6(&self, _interface: u32) -> io::Result<()> {
+ set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_IF, to_ipv6mr_interface(_interface))
+ }
+
+ fn multicast_if_v6(&self) -> io::Result<u32> {
+ get_opt::<c_int>(self.as_sock(), v(IPPROTO_IPV6), IPV6_MULTICAST_IF).map(|b| b as u32)
+ }
+
+ fn set_ttl(&self, ttl: u32) -> io::Result<()> {
+ set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int)
+ }
+
+ fn ttl(&self) -> io::Result<u32> {
+ get_opt::<c_int>(self.as_sock(), IPPROTO_IP, IP_TTL)
+ .map(|b| b as u32)
+ }
+
+ fn set_unicast_hops_v6(&self, _ttl: u32) -> io::Result<()> {
+ set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_UNICAST_HOPS, _ttl as c_int)
+ }
+
+ fn unicast_hops_v6(&self) -> io::Result<u32> {
+ get_opt::<c_int>(self.as_sock(), IPPROTO_IP, IPV6_UNICAST_HOPS)
+ .map(|b| b as u32)
+ }
+
+ fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
+ set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int)
+ }
+
+ fn only_v6(&self) -> io::Result<bool> {
+ get_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY).map(int2bool)
+ }
+
+ fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr)
+ -> io::Result<()> {
+ let mreq = ip_mreq {
+ imr_multiaddr: ip2in_addr(multiaddr),
+ imr_interface: ip2in_addr(interface),
+ };
+ set_opt(self.as_sock(), IPPROTO_IP, IP_ADD_MEMBERSHIP, mreq)
+ }
+
+ fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32)
+ -> io::Result<()> {
+ let mreq = ipv6_mreq {
+ ipv6mr_multiaddr: ip2in6_addr(multiaddr),
+ ipv6mr_interface: to_ipv6mr_interface(interface),
+ };
+ set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_ADD_MEMBERSHIP,
+ mreq)
+ }
+
+ fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr)
+ -> io::Result<()> {
+ let mreq = ip_mreq {
+ imr_multiaddr: ip2in_addr(multiaddr),
+ imr_interface: ip2in_addr(interface),
+ };
+ set_opt(self.as_sock(), IPPROTO_IP, IP_DROP_MEMBERSHIP, mreq)
+ }
+
+ fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32)
+ -> io::Result<()> {
+ let mreq = ipv6_mreq {
+ ipv6mr_multiaddr: ip2in6_addr(multiaddr),
+ ipv6mr_interface: to_ipv6mr_interface(interface),
+ };
+ set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_DROP_MEMBERSHIP,
+ mreq)
+ }
+
+ fn set_read_timeout_ms(&self, dur: Option<u32>) -> io::Result<()> {
+ set_opt(self.as_sock(), SOL_SOCKET, SO_RCVTIMEO,
+ ms2timeout(dur))
+ }
+
+ fn read_timeout_ms(&self) -> io::Result<Option<u32>> {
+ get_opt(self.as_sock(), SOL_SOCKET, SO_RCVTIMEO)
+ .map(timeout2ms)
+ }
+
+ fn set_write_timeout_ms(&self, dur: Option<u32>) -> io::Result<()> {
+ set_opt(self.as_sock(), SOL_SOCKET, SO_SNDTIMEO,
+ ms2timeout(dur))
+ }
+
+ fn write_timeout_ms(&self) -> io::Result<Option<u32>> {
+ get_opt(self.as_sock(), SOL_SOCKET, SO_SNDTIMEO)
+ .map(timeout2ms)
+ }
+
+ fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
+ self.set_read_timeout_ms(dur.map(dur2ms))
+ }
+
+ fn read_timeout(&self) -> io::Result<Option<Duration>> {
+ self.read_timeout_ms().map(|o| o.map(ms2dur))
+ }
+
+ fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
+ self.set_write_timeout_ms(dur.map(dur2ms))
+ }
+
+ fn write_timeout(&self) -> io::Result<Option<Duration>> {
+ self.write_timeout_ms().map(|o| o.map(ms2dur))
+ }
+
+ fn take_error(&self) -> io::Result<Option<io::Error>> {
+ get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err)
+ }
+
+ fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
+ do_connect(self.as_sock(), addr)
+ }
+
+ #[cfg(unix)]
+ fn send(&self, buf: &[u8]) -> io::Result<usize> {
+ unsafe {
+ ::cvt(send(self.as_sock() as c_int, buf.as_ptr() as *const _, buf.len(), 0)).map(|n| n as usize)
+ }
+ }
+
+ #[cfg(target_os = "wasi")]
+ fn send(&self, buf: &[u8]) -> io::Result<usize> {
+ let _so_datalen: *mut sys::c::size_t = &mut 0;
+ unsafe {
+ let _errno = libc::__wasi_sock_send(
+ self.as_sock() as libc::__wasi_fd_t,
+ buf.as_ptr() as *const _,
+ buf.len(),
+ 0,
+ _so_datalen,
+ );
+ // TODO: handle errno
+ Ok((*_so_datalen) as usize)
+ }
+ }
+
+ #[cfg(windows)]
+ fn send(&self, buf: &[u8]) -> io::Result<usize> {
+ let len = ::std::cmp::min(buf.len(), c_int::max_value() as usize);
+ let buf = &buf[..len];
+ unsafe {
+ ::cvt(send(self.as_sock(), buf.as_ptr() as *const _, len as c_int, 0))
+ .map(|n| n as usize)
+ }
+ }
+
+ #[cfg(unix)]
+ fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
+ unsafe {
+ ::cvt(recv(self.as_sock(), buf.as_mut_ptr() as *mut _, buf.len(), 0))
+ .map(|n| n as usize)
+ }
+ }
+
+ #[cfg(target_os = "wasi")]
+ fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
+ let _ro_datalen: *mut sys::c::size_t = &mut 0;
+ let _ro_flags: *mut sys::c::__wasi_roflags_t = &mut 0;
+ unsafe {
+ let _errno = __wasi_sock_recv(
+ self.as_sock(),
+ buf.as_mut_ptr() as *mut _,
+ buf.len(),
+ 0,
+ _ro_datalen,
+ _ro_flags,
+ );
+ // TODO: handle errno
+ Ok((*_ro_datalen) as usize)
+ }
+ }
+
+ #[cfg(windows)]
+ fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
+ let len = ::std::cmp::min(buf.len(), c_int::max_value() as usize);
+ let buf = &mut buf[..len];
+ unsafe {
+ ::cvt(recv(self.as_sock(), buf.as_mut_ptr() as *mut _, buf.len() as c_int, 0))
+ .map(|n| n as usize)
+ }
+ }
+
+ fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
+ set_nonblocking(self.as_sock(), nonblocking)
+ }
+}
+
+fn do_connect<A: ToSocketAddrs>(sock: Socket, addr: A) -> io::Result<()> {
+ let err = io::Error::new(io::ErrorKind::Other,
+ "no socket addresses resolved");
+ let addrs = try!(addr.to_socket_addrs());
+ let sys = sys::Socket::from_inner(sock);
+ let sock = socket::Socket::from_inner(sys);
+ let ret = addrs.fold(Err(err), |prev, addr| {
+ prev.or_else(|_| sock.connect(&addr))
+ });
+ mem::forget(sock);
+ return ret
+}
+
+#[cfg(unix)]
+fn set_nonblocking(sock: Socket, nonblocking: bool) -> io::Result<()> {
+ let mut nonblocking = nonblocking as c_ulong;
+ ::cvt(unsafe {
+ ioctl(sock, FIONBIO, &mut nonblocking)
+ }).map(|_| ())
+}
+
+#[cfg(target_os = "wasi")]
+fn set_nonblocking(_sock: Socket, _nonblocking: bool) -> io::Result<()> {
+ Ok(())
+}
+
+#[cfg(windows)]
+fn set_nonblocking(sock: Socket, nonblocking: bool) -> io::Result<()> {
+ let mut nonblocking = nonblocking as c_ulong;
+ ::cvt(unsafe {
+ ioctlsocket(sock, FIONBIO as c_int, &mut nonblocking)
+ }).map(|_| ())
+}
+
+#[cfg(any(unix, target_os = "wasi"))]
+fn ip2in_addr(ip: &Ipv4Addr) -> in_addr {
+ let oct = ip.octets();
+ in_addr {
+ s_addr: ::hton(((oct[0] as u32) << 24) |
+ ((oct[1] as u32) << 16) |
+ ((oct[2] as u32) << 8) |
+ ((oct[3] as u32) << 0)),
+ }
+}
+
+#[cfg(windows)]
+fn ip2in_addr(ip: &Ipv4Addr) -> in_addr {
+ let oct = ip.octets();
+ unsafe {
+ let mut S_un: in_addr_S_un = mem::zeroed();
+ *S_un.S_addr_mut() = ::hton(((oct[0] as u32) << 24) |
+ ((oct[1] as u32) << 16) |
+ ((oct[2] as u32) << 8) |
+ ((oct[3] as u32) << 0));
+ in_addr {
+ S_un: S_un,
+ }
+ }
+}
+
+fn in_addr2ip(ip: &in_addr) -> Ipv4Addr {
+ let h_addr = c::in_addr_to_u32(ip);
+
+ let a: u8 = (h_addr >> 24) as u8;
+ let b: u8 = (h_addr >> 16) as u8;
+ let c: u8 = (h_addr >> 8) as u8;
+ let d: u8 = (h_addr >> 0) as u8;
+
+ Ipv4Addr::new(a,b,c,d)
+}
+
+#[cfg(target_os = "android")]
+fn to_ipv6mr_interface(value: u32) -> c_int {
+ value as c_int
+}
+
+#[cfg(not(target_os = "android"))]
+fn to_ipv6mr_interface(value: u32) -> c_uint {
+ value as c_uint
+}
+
+fn ip2in6_addr(ip: &Ipv6Addr) -> in6_addr {
+ let mut ret: in6_addr = unsafe { mem::zeroed() };
+ let seg = ip.segments();
+ let bytes = [
+ (seg[0] >> 8) as u8,
+ (seg[0] >> 0) as u8,
+ (seg[1] >> 8) as u8,
+ (seg[1] >> 0) as u8,
+ (seg[2] >> 8) as u8,
+ (seg[2] >> 0) as u8,
+ (seg[3] >> 8) as u8,
+ (seg[3] >> 0) as u8,
+ (seg[4] >> 8) as u8,
+ (seg[4] >> 0) as u8,
+ (seg[5] >> 8) as u8,
+ (seg[5] >> 0) as u8,
+ (seg[6] >> 8) as u8,
+ (seg[6] >> 0) as u8,
+ (seg[7] >> 8) as u8,
+ (seg[7] >> 0) as u8,
+ ];
+ #[cfg(windows)] unsafe { *ret.u.Byte_mut() = bytes; }
+ #[cfg(not(windows))] { ret.s6_addr = bytes; }
+
+ return ret
+}
+
+impl TcpListenerExt for TcpListener {
+ fn set_ttl(&self, ttl: u32) -> io::Result<()> {
+ set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int)
+ }
+
+ fn ttl(&self) -> io::Result<u32> {
+ get_opt::<c_int>(self.as_sock(), IPPROTO_IP, IP_TTL)
+ .map(|b| b as u32)
+ }
+
+ fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
+ set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int)
+ }
+
+ fn only_v6(&self) -> io::Result<bool> {
+ get_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY).map(int2bool)
+ }
+
+ fn take_error(&self) -> io::Result<Option<io::Error>> {
+ get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err)
+ }
+
+ fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
+ set_nonblocking(self.as_sock(), nonblocking)
+ }
+
+ fn set_linger(&self, dur: Option<Duration>) -> io::Result<()> {
+ set_opt(self.as_sock(), SOL_SOCKET, SO_LINGER, dur2linger(dur))
+ }
+
+ fn linger(&self) -> io::Result<Option<Duration>> {
+ get_opt(self.as_sock(), SOL_SOCKET, SO_LINGER).map(linger2dur)
+ }
+}
+
+impl TcpBuilder {
+ /// Sets the value for the `IP_TTL` option on this socket.
+ ///
+ /// This is the same as [`TcpStreamExt::set_ttl`][other].
+ ///
+ /// [other]: trait.TcpStreamExt.html#tymethod.set_ttl
+ pub fn ttl(&self, ttl: u32) -> io::Result<&Self> {
+ set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int)
+ .map(|()| self)
+ }
+
+ /// Sets the value for the `IPV6_V6ONLY` option on this socket.
+ ///
+ /// This is the same as [`TcpStreamExt::set_only_v6`][other].
+ ///
+ /// [other]: trait.TcpStreamExt.html#tymethod.set_only_v6
+ pub fn only_v6(&self, only_v6: bool) -> io::Result<&Self> {
+ set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int)
+ .map(|()| self)
+ }
+
+ /// Set value for the `SO_REUSEADDR` option on this socket.
+ ///
+ /// This indicates that further calls to `bind` may allow reuse of local
+ /// addresses. For IPv4 sockets this means that a socket may bind even when
+ /// there's a socket already listening on this port.
+ pub fn reuse_address(&self, reuse: bool) -> io::Result<&Self> {
+ set_opt(self.as_sock(), SOL_SOCKET, SO_REUSEADDR,
+ reuse as c_int).map(|()| self)
+ }
+
+ /// Check the `SO_REUSEADDR` option on this socket.
+ pub fn get_reuse_address(&self) -> io::Result<bool> {
+ get_opt(self.as_sock(), SOL_SOCKET, SO_REUSEADDR).map(int2bool)
+ }
+
+ /// Get the value of the `SO_ERROR` option on this socket.
+ ///
+ /// This will retrieve the stored error in the underlying socket, clearing
+ /// the field in the process. This can be useful for checking errors between
+ /// calls.
+ pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+ get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err)
+ }
+
+ /// Sets the linger option for this socket
+ fn set_linger(&self, dur: Option<Duration>) -> io::Result<()> {
+ set_opt(self.as_sock(), SOL_SOCKET, SO_LINGER, dur2linger(dur))
+ }
+
+ /// Gets the linger option for this socket
+ fn linger(&self) -> io::Result<Option<Duration>> {
+ get_opt(self.as_sock(), SOL_SOCKET, SO_LINGER).map(linger2dur)
+ }
+}
+
+impl UdpBuilder {
+ /// Sets the value for the `IP_TTL` option on this socket.
+ ///
+ /// This is the same as [`TcpStreamExt::set_ttl`][other].
+ ///
+ /// [other]: trait.TcpStreamExt.html#tymethod.set_ttl
+ pub fn ttl(&self, ttl: u32) -> io::Result<&Self> {
+ set_opt(self.as_sock(), IPPROTO_IP, IP_TTL, ttl as c_int)
+ .map(|()| self)
+ }
+
+ /// Sets the value for the `IPV6_V6ONLY` option on this socket.
+ ///
+ /// This is the same as [`TcpStream::only_v6`][other].
+ ///
+ /// [other]: struct.TcpBuilder.html#method.only_v6
+ pub fn only_v6(&self, only_v6: bool) -> io::Result<&Self> {
+ set_opt(self.as_sock(), v(IPPROTO_IPV6), IPV6_V6ONLY, only_v6 as c_int)
+ .map(|()| self)
+ }
+
+ /// Set value for the `SO_REUSEADDR` option on this socket.
+ ///
+ /// This is the same as [`TcpBuilder::reuse_address`][other].
+ ///
+ /// [other]: struct.TcpBuilder.html#method.reuse_address
+ pub fn reuse_address(&self, reuse: bool) -> io::Result<&Self> {
+ set_opt(self.as_sock(), SOL_SOCKET, SO_REUSEADDR,
+ reuse as c_int).map(|()| self)
+ }
+
+ /// Check the `SO_REUSEADDR` option on this socket.
+ pub fn get_reuse_address(&self) -> io::Result<bool> {
+ get_opt(self.as_sock(), SOL_SOCKET, SO_REUSEADDR).map(int2bool)
+ }
+
+ /// Get the value of the `SO_ERROR` option on this socket.
+ ///
+ /// This will retrieve the stored error in the underlying socket, clearing
+ /// the field in the process. This can be useful for checking errors between
+ /// calls.
+ pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+ get_opt(self.as_sock(), SOL_SOCKET, SO_ERROR).map(int2err)
+ }
+}
diff --git a/third_party/rust/net2/src/lib.rs b/third_party/rust/net2/src/lib.rs
new file mode 100644
index 0000000000..a4b460e255
--- /dev/null
+++ b/third_party/rust/net2/src/lib.rs
@@ -0,0 +1,126 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Extensions to `std::net` networking types.
+//!
+//! This crate implements a number of extensions to the standard `std::net`
+//! networking types, hopefully being slated for inclusion into the standard
+//! library in the future. The goal of this crate is to expose all sorts of
+//! cross-platform and platform-specific configuration options of UDP/TCP
+//! sockets. System APIs are wrapped with as thin a layer as possible instead of
+//! bundling multiple actions into one API call.
+//!
+//! More information about the design of this crate can be found in the
+//! [associated rfc][rfc]
+//!
+//! [rfc]: https://github.com/rust-lang/rfcs/pull/1158
+//!
+//! # Examples
+//!
+//! ```no_run
+//! use net2::TcpBuilder;
+//!
+//! let tcp = TcpBuilder::new_v4().unwrap();
+//! tcp.reuse_address(true).unwrap()
+//! .only_v6(false).unwrap();
+//!
+//! let mut stream = tcp.connect("127.0.0.1:80").unwrap();
+//!
+//! // use `stream` as a TcpStream
+//! ```
+
+#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+ html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
+ html_root_url = "https://doc.rust-lang.org/net2-rs")]
+#![deny(missing_docs, warnings)]
+
+// Silence warnings about deprecated try!() usage
+#![allow(deprecated)]
+
+#![cfg_attr(target_os = "wasi", feature(wasi_ext))]
+
+#[cfg(any(target_os = "wasi", unix))] extern crate libc;
+
+#[cfg(windows)] extern crate winapi;
+
+#[macro_use] extern crate cfg_if;
+
+use std::io;
+use std::ops::Neg;
+use std::net::{ToSocketAddrs, SocketAddr};
+
+use utils::{One, NetInt};
+
+mod tcp;
+mod udp;
+mod socket;
+mod ext;
+mod utils;
+
+#[cfg(unix)] #[path = "sys/unix/mod.rs"] mod sys;
+#[cfg(windows)] #[path = "sys/windows/mod.rs"] mod sys;
+#[cfg(target_os = "wasi")] #[path = "sys/wasi/mod.rs"] mod sys;
+#[cfg(all(unix, not(any(target_os = "solaris", target_os = "illumos"))))] pub mod unix;
+
+pub use tcp::TcpBuilder;
+pub use udp::UdpBuilder;
+pub use ext::{TcpStreamExt, TcpListenerExt, UdpSocketExt};
+
+fn one_addr<T: ToSocketAddrs>(tsa: T) -> io::Result<SocketAddr> {
+ let mut addrs = try!(tsa.to_socket_addrs());
+ let addr = match addrs.next() {
+ Some(addr) => addr,
+ None => return Err(io::Error::new(io::ErrorKind::Other,
+ "no socket addresses could be resolved"))
+ };
+ if addrs.next().is_none() {
+ Ok(addr)
+ } else {
+ Err(io::Error::new(io::ErrorKind::Other,
+ "more than one address resolved"))
+ }
+}
+
+fn cvt<T: One + PartialEq + Neg<Output=T>>(t: T) -> io::Result<T> {
+ let one: T = T::one();
+ if t == -one {
+ Err(io::Error::last_os_error())
+ } else {
+ Ok(t)
+ }
+}
+
+#[cfg(windows)]
+fn cvt_win<T: PartialEq + utils::Zero>(t: T) -> io::Result<T> {
+ if t == T::zero() {
+ Err(io::Error::last_os_error())
+ } else {
+ Ok(t)
+ }
+}
+
+fn hton<I: NetInt>(i: I) -> I { i.to_be() }
+
+fn ntoh<I: NetInt>(i: I) -> I { I::from_be(i) }
+
+trait AsInner {
+ type Inner;
+ fn as_inner(&self) -> &Self::Inner;
+}
+
+trait FromInner {
+ type Inner;
+ fn from_inner(inner: Self::Inner) -> Self;
+}
+
+trait IntoInner {
+ type Inner;
+ fn into_inner(self) -> Self::Inner;
+}
diff --git a/third_party/rust/net2/src/socket.rs b/third_party/rust/net2/src/socket.rs
new file mode 100644
index 0000000000..5b0f4935a9
--- /dev/null
+++ b/third_party/rust/net2/src/socket.rs
@@ -0,0 +1,260 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::fmt;
+use std::io;
+use std::mem;
+use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
+#[cfg(any(unix, target_os = "wasi"))]
+use libc::c_int;
+#[cfg(windows)]
+use winapi::ctypes::c_int;
+
+use sys;
+use sys::c;
+
+pub struct Socket {
+ inner: sys::Socket,
+}
+
+impl Socket {
+ pub fn new(family: c_int, ty: c_int) -> io::Result<Socket> {
+ Ok(Socket { inner: try!(sys::Socket::new(family, ty)) })
+ }
+
+ pub fn bind(&self, addr: &SocketAddr) -> io::Result<()> {
+ let (addr, len) = addr2raw(addr);
+ unsafe {
+ ::cvt(c::bind(self.inner.raw(), addr.as_ptr(), len as c::socklen_t)).map(|_| ())
+ }
+ }
+
+ pub fn listen(&self, backlog: i32) -> io::Result<()> {
+ unsafe {
+ ::cvt(c::listen(self.inner.raw(), backlog)).map(|_| ())
+ }
+ }
+
+ pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> {
+ let (addr, len) = addr2raw(addr);
+ unsafe {
+ ::cvt(c::connect(self.inner.raw(), addr.as_ptr(), len)).map(|_| ())
+ }
+ }
+
+ pub fn getsockname(&self) -> io::Result<SocketAddr> {
+ unsafe {
+ let mut storage: c::sockaddr_storage = mem::zeroed();
+ let mut len = mem::size_of_val(&storage) as c::socklen_t;
+ try!(::cvt(c::getsockname(self.inner.raw(),
+ &mut storage as *mut _ as *mut _,
+ &mut len)));
+ raw2addr(&storage, len)
+ }
+ }
+}
+
+impl fmt::Debug for Socket {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ self.inner.raw().fmt(f)
+ }
+}
+
+impl ::AsInner for Socket {
+ type Inner = sys::Socket;
+ fn as_inner(&self) -> &sys::Socket { &self.inner }
+}
+
+impl ::FromInner for Socket {
+ type Inner = sys::Socket;
+ fn from_inner(sock: sys::Socket) -> Socket {
+ Socket { inner: sock }
+ }
+}
+
+impl ::IntoInner for Socket {
+ type Inner = sys::Socket;
+ fn into_inner(self) -> sys::Socket { self.inner }
+}
+
+/// A type with the same memory layout as `c::sockaddr`. Used in converting Rust level
+/// SocketAddr* types into their system representation. The benefit of this specific
+/// type over using `c::sockaddr_storage` is that this type is exactly as large as it
+/// needs to be and not a lot larger.
+#[repr(C)]
+pub(crate) union SocketAddrCRepr {
+ v4: c::sockaddr_in,
+ v6: c::sockaddr_in6,
+}
+
+impl SocketAddrCRepr {
+ pub(crate) fn as_ptr(&self) -> *const c::sockaddr {
+ self as *const _ as *const c::sockaddr
+ }
+}
+
+fn addr2raw(addr: &SocketAddr) -> (SocketAddrCRepr, c::socklen_t) {
+ match addr {
+ &SocketAddr::V4(ref v4) => addr2raw_v4(v4),
+ &SocketAddr::V6(ref v6) => addr2raw_v6(v6),
+ }
+}
+
+#[cfg(unix)]
+fn addr2raw_v4(addr: &SocketAddrV4) -> (SocketAddrCRepr, c::socklen_t) {
+ let sin_addr = c::in_addr {
+ s_addr: u32::from(*addr.ip()).to_be(),
+ };
+
+ let sockaddr = SocketAddrCRepr {
+ v4: c::sockaddr_in {
+ sin_family: c::AF_INET as c::sa_family_t,
+ sin_port: addr.port().to_be(),
+ sin_addr,
+ #[cfg(not(target_os = "haiku"))]
+ sin_zero: [0; 8],
+ #[cfg(target_os = "haiku")]
+ sin_zero: [0; 24],
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "haiku",
+ ))]
+ sin_len: 0,
+ },
+ };
+ (sockaddr, mem::size_of::<c::sockaddr_in>() as c::socklen_t)
+}
+
+#[cfg(windows)]
+fn addr2raw_v4(addr: &SocketAddrV4) -> (SocketAddrCRepr, c::socklen_t) {
+ let sin_addr = unsafe {
+ let mut s_un = mem::zeroed::<c::in_addr_S_un>();
+ *s_un.S_addr_mut() = u32::from(*addr.ip()).to_be();
+ c::IN_ADDR { S_un: s_un }
+ };
+
+ let sockaddr = SocketAddrCRepr {
+ v4: c::sockaddr_in {
+ sin_family: c::AF_INET as c::sa_family_t,
+ sin_port: addr.port().to_be(),
+ sin_addr,
+ sin_zero: [0; 8],
+ },
+ };
+ (sockaddr, mem::size_of::<c::sockaddr_in>() as c::socklen_t)
+}
+
+#[cfg(unix)]
+fn addr2raw_v6(addr: &SocketAddrV6) -> (SocketAddrCRepr, c::socklen_t) {
+ let sin6_addr = {
+ let mut sin6_addr = unsafe { mem::zeroed::<c::in6_addr>() };
+ sin6_addr.s6_addr = addr.ip().octets();
+ sin6_addr
+ };
+
+ let sockaddr = SocketAddrCRepr {
+ v6: c::sockaddr_in6 {
+ sin6_family: c::AF_INET6 as c::sa_family_t,
+ sin6_port: addr.port().to_be(),
+ sin6_addr,
+ sin6_flowinfo: addr.flowinfo(),
+ sin6_scope_id: addr.scope_id(),
+ #[cfg(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "haiku",
+ ))]
+ sin6_len: 0,
+ #[cfg(any(target_os = "solaris", target_os = "illumos"))]
+ __sin6_src_id: 0,
+ },
+ };
+ (sockaddr, mem::size_of::<c::sockaddr_in6>() as c::socklen_t)
+}
+
+#[cfg(windows)]
+fn addr2raw_v6(addr: &SocketAddrV6) -> (SocketAddrCRepr, c::socklen_t) {
+ let sin6_addr = unsafe {
+ let mut u = mem::zeroed::<c::in6_addr_u>();
+ *u.Byte_mut() = addr.ip().octets();
+ c::IN6_ADDR { u }
+ };
+ let scope_id = unsafe {
+ let mut u = mem::zeroed::<c::SOCKADDR_IN6_LH_u>();
+ *u.sin6_scope_id_mut() = addr.scope_id();
+ u
+ };
+
+ let sockaddr = SocketAddrCRepr {
+ v6: c::sockaddr_in6 {
+ sin6_family: c::AF_INET6 as c::sa_family_t,
+ sin6_port: addr.port().to_be(),
+ sin6_addr,
+ sin6_flowinfo: addr.flowinfo(),
+ u: scope_id,
+ },
+ };
+ (sockaddr, mem::size_of::<c::sockaddr_in6>() as c::socklen_t)
+}
+
+fn raw2addr(storage: &c::sockaddr_storage, len: c::socklen_t) -> io::Result<SocketAddr> {
+ match storage.ss_family as c_int {
+ c::AF_INET => {
+ unsafe {
+ assert!(len as usize >= mem::size_of::<c::sockaddr_in>());
+ let sa = storage as *const _ as *const c::sockaddr_in;
+ let bits = c::sockaddr_in_u32(&(*sa));
+ let ip = Ipv4Addr::new((bits >> 24) as u8,
+ (bits >> 16) as u8,
+ (bits >> 8) as u8,
+ bits as u8);
+ Ok(SocketAddr::V4(SocketAddrV4::new(ip, ::ntoh((*sa).sin_port))))
+ }
+ }
+ c::AF_INET6 => {
+ unsafe {
+ assert!(len as usize >= mem::size_of::<c::sockaddr_in6>());
+
+ let sa = storage as *const _ as *const c::sockaddr_in6;
+ #[cfg(windows)] let arr = (*sa).sin6_addr.u.Byte();
+ #[cfg(not(windows))] let arr = (*sa).sin6_addr.s6_addr;
+
+ let ip = Ipv6Addr::new(
+ (arr[0] as u16) << 8 | (arr[1] as u16),
+ (arr[2] as u16) << 8 | (arr[3] as u16),
+ (arr[4] as u16) << 8 | (arr[5] as u16),
+ (arr[6] as u16) << 8 | (arr[7] as u16),
+ (arr[8] as u16) << 8 | (arr[9] as u16),
+ (arr[10] as u16) << 8 | (arr[11] as u16),
+ (arr[12] as u16) << 8 | (arr[13] as u16),
+ (arr[14] as u16) << 8 | (arr[15] as u16),
+ );
+
+ #[cfg(windows)] let sin6_scope_id = *(*sa).u.sin6_scope_id();
+ #[cfg(not(windows))] let sin6_scope_id = (*sa).sin6_scope_id;
+
+ Ok(SocketAddr::V6(SocketAddrV6::new(ip,
+ ::ntoh((*sa).sin6_port),
+ (*sa).sin6_flowinfo,
+ sin6_scope_id)))
+ }
+ }
+ _ => Err(io::Error::new(io::ErrorKind::InvalidInput, "invalid argument")),
+ }
+}
diff --git a/third_party/rust/net2/src/sys/unix/impls.rs b/third_party/rust/net2/src/sys/unix/impls.rs
new file mode 100644
index 0000000000..95c2fb8081
--- /dev/null
+++ b/third_party/rust/net2/src/sys/unix/impls.rs
@@ -0,0 +1,44 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::os::unix::io::{FromRawFd, AsRawFd};
+use libc::c_int;
+
+use {TcpBuilder, UdpBuilder, FromInner, AsInner};
+use socket::Socket;
+use sys;
+
+impl FromRawFd for TcpBuilder {
+ unsafe fn from_raw_fd(fd: c_int) -> TcpBuilder {
+ let sock = sys::Socket::from_inner(fd);
+ TcpBuilder::from_inner(Socket::from_inner(sock))
+ }
+}
+
+impl AsRawFd for TcpBuilder {
+ fn as_raw_fd(&self) -> c_int {
+ // TODO: this unwrap() is very bad
+ self.as_inner().borrow().as_ref().unwrap().as_inner().raw()
+ }
+}
+
+impl FromRawFd for UdpBuilder {
+ unsafe fn from_raw_fd(fd: c_int) -> UdpBuilder {
+ let sock = sys::Socket::from_inner(fd);
+ UdpBuilder::from_inner(Socket::from_inner(sock))
+ }
+}
+
+impl AsRawFd for UdpBuilder {
+ fn as_raw_fd(&self) -> c_int {
+ // TODO: this unwrap() is very bad
+ self.as_inner().borrow().as_ref().unwrap().as_inner().raw()
+ }
+}
diff --git a/third_party/rust/net2/src/sys/unix/mod.rs b/third_party/rust/net2/src/sys/unix/mod.rs
new file mode 100644
index 0000000000..cc8a60d01e
--- /dev/null
+++ b/third_party/rust/net2/src/sys/unix/mod.rs
@@ -0,0 +1,104 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+use std::io;
+use std::mem;
+use std::net::{TcpListener, TcpStream, UdpSocket};
+use std::os::unix::io::FromRawFd;
+use libc::{self, c_int};
+#[cfg(not(any(target_os = "emscripten", target_os = "haiku", target_os = "illumos", target_os = "solaris")))]
+use libc::{ioctl, FIOCLEX};
+
+mod impls;
+
+pub mod c {
+ pub use libc::*;
+
+ pub fn sockaddr_in_u32(sa: &sockaddr_in) -> u32 {
+ ::ntoh((*sa).sin_addr.s_addr)
+ }
+
+ pub fn in_addr_to_u32(addr: &in_addr) -> u32 {
+ ::ntoh(addr.s_addr)
+ }
+}
+
+pub struct Socket {
+ fd: c_int,
+}
+
+impl Socket {
+ #[cfg(not(any(target_os = "emscripten", target_os = "haiku", target_os = "illumos", target_os = "solaris")))]
+ pub fn new(family: c_int, ty: c_int) -> io::Result<Socket> {
+ unsafe {
+ // Linux >2.6.26 overloads the type argument to accept SOCK_CLOEXEC,
+ // avoiding a race with another thread running fork/exec between
+ // socket() and ioctl()
+ #[cfg(any(target_os = "linux", target_os = "android"))]
+ match ::cvt(libc::socket(family, ty | libc::SOCK_CLOEXEC, 0)) {
+ Ok(fd) => return Ok(Socket { fd: fd }),
+ // Older versions of Linux return EINVAL; fall back to ioctl
+ Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => {}
+ Err(e) => return Err(e),
+ }
+
+ let fd = try!(::cvt(libc::socket(family, ty, 0)));
+ ioctl(fd, FIOCLEX);
+ Ok(Socket { fd: fd })
+ }
+ }
+
+ // ioctl(FIOCLEX) is not supported by Solaris/illumos or emscripten,
+ // use fcntl(FD_CLOEXEC) instead
+ #[cfg(any(target_os = "emscripten", target_os = "haiku", target_os = "illumos", target_os = "solaris"))]
+ pub fn new(family: c_int, ty: c_int) -> io::Result<Socket> {
+ unsafe {
+ let fd = try!(::cvt(libc::socket(family, ty, 0)));
+ libc::fcntl(fd, libc::FD_CLOEXEC);
+ Ok(Socket { fd: fd })
+ }
+ }
+
+ pub fn raw(&self) -> c_int { self.fd }
+
+ fn into_fd(self) -> c_int {
+ let fd = self.fd;
+ mem::forget(self);
+ fd
+ }
+
+ pub fn into_tcp_listener(self) -> TcpListener {
+ unsafe { TcpListener::from_raw_fd(self.into_fd()) }
+ }
+
+ pub fn into_tcp_stream(self) -> TcpStream {
+ unsafe { TcpStream::from_raw_fd(self.into_fd()) }
+ }
+
+ pub fn into_udp_socket(self) -> UdpSocket {
+ unsafe { UdpSocket::from_raw_fd(self.into_fd()) }
+ }
+}
+
+impl ::FromInner for Socket {
+ type Inner = c_int;
+ fn from_inner(fd: c_int) -> Socket {
+ Socket { fd: fd }
+ }
+}
+
+impl Drop for Socket {
+ fn drop(&mut self) {
+ unsafe {
+ let _ = libc::close(self.fd);
+ }
+ }
+}
diff --git a/third_party/rust/net2/src/sys/wasi/impls.rs b/third_party/rust/net2/src/sys/wasi/impls.rs
new file mode 100644
index 0000000000..eef8094b60
--- /dev/null
+++ b/third_party/rust/net2/src/sys/wasi/impls.rs
@@ -0,0 +1,33 @@
+use std::os::wasi::io::{FromRawFd, AsRawFd};
+
+use {TcpBuilder, UdpBuilder, FromInner, AsInner};
+use socket::Socket;
+use sys::{self, c::__wasi_fd_t};
+
+impl FromRawFd for TcpBuilder {
+ unsafe fn from_raw_fd(fd: __wasi_fd_t) -> TcpBuilder {
+ let sock = sys::Socket::from_inner(fd);
+ TcpBuilder::from_inner(Socket::from_inner(sock))
+ }
+}
+
+impl AsRawFd for TcpBuilder {
+ fn as_raw_fd(&self) -> __wasi_fd_t {
+ // TODO: this unwrap() is very bad
+ self.as_inner().borrow().as_ref().unwrap().as_inner().raw() as __wasi_fd_t
+ }
+}
+
+impl FromRawFd for UdpBuilder {
+ unsafe fn from_raw_fd(fd: __wasi_fd_t) -> UdpBuilder {
+ let sock = sys::Socket::from_inner(fd);
+ UdpBuilder::from_inner(Socket::from_inner(sock))
+ }
+}
+
+impl AsRawFd for UdpBuilder {
+ fn as_raw_fd(&self) -> __wasi_fd_t {
+ // TODO: this unwrap() is very bad
+ self.as_inner().borrow().as_ref().unwrap().as_inner().raw() as __wasi_fd_t
+ }
+}
diff --git a/third_party/rust/net2/src/sys/wasi/mod.rs b/third_party/rust/net2/src/sys/wasi/mod.rs
new file mode 100644
index 0000000000..bbc507ed68
--- /dev/null
+++ b/third_party/rust/net2/src/sys/wasi/mod.rs
@@ -0,0 +1,185 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(non_camel_case_types)]
+use libc::{self, c_int, __wasi_fd_t};
+use std::io;
+use std::mem;
+use std::net::{TcpListener, TcpStream, UdpSocket};
+use std::os::wasi::io::FromRawFd;
+
+mod impls;
+
+pub mod c {
+ pub use libc::*;
+
+ pub type sa_family_t = u16;
+ pub type socklen_t = u32;
+ pub type in_port_t = u16;
+
+ pub const SOCK_DGRAM: c_int = 0x00;
+ pub const SOL_SOCKET: c_int = 0x00;
+ pub const SO_RCVBUF: c_int = 0x00;
+ pub const SO_SNDBUF: c_int = 0x00;
+ pub const TCP_NODELAY: c_int = 0x00;
+ pub const IPPROTO_TCP: c_int = 0x00;
+ pub const SO_RCVTIMEO: c_int = 0x00;
+ pub const SO_SNDTIMEO: c_int = 0x00;
+ pub const IPPROTO_IP: c_int = 0x00;
+ pub const IP_TTL: c_int = 0x00;
+ pub const IPPROTO_IPV6: c_int = 0x00;
+ pub const IPV6_V6ONLY: c_int = 0x00;
+ pub const SO_ERROR: c_int = 0x00;
+ pub const SO_LINGER: c_int = 0x00;
+ pub const SO_BROADCAST: c_int = 0x00;
+ pub const IP_MULTICAST_LOOP: c_int = 0x00;
+ pub const IP_MULTICAST_TTL: c_int = 0x00;
+ pub const IPV6_MULTICAST_HOPS: c_int = 0x00;
+ pub const IPV6_MULTICAST_LOOP: c_int = 0x00;
+ pub const IP_MULTICAST_IF: c_int = 0x00;
+ pub const IPV6_MULTICAST_IF: c_int = 0x00;
+ pub const IPV6_UNICAST_HOPS: c_int = 0x00;
+ pub const IP_ADD_MEMBERSHIP: c_int = 0x00;
+ pub const IPV6_ADD_MEMBERSHIP: c_int = 0x00;
+ pub const IP_DROP_MEMBERSHIP: c_int = 0x00;
+ pub const IPV6_DROP_MEMBERSHIP: c_int = 0x00;
+ pub const SO_REUSEADDR: c_int = 0x00;
+ pub const SOCK_STREAM: c_int = 0x00;
+ pub const AF_INET: c_int = 0x00;
+ pub const AF_INET6: c_int = 0x01;
+
+ #[repr(C)]
+ pub struct sockaddr_storage {
+ pub ss_family: sa_family_t,
+ }
+ #[repr(C)]
+ pub struct sockaddr {
+ pub sa_family: sa_family_t,
+ pub sa_data: [c_char; 14],
+ }
+
+ #[repr(C)]
+ pub struct sockaddr_in6 {
+ pub sin6_family: sa_family_t,
+ pub sin6_port: in_port_t,
+ pub sin6_flowinfo: u32,
+ pub sin6_addr: in6_addr,
+ pub sin6_scope_id: u32,
+ }
+
+ #[repr(C)]
+ pub struct sockaddr_in {
+ pub sin_family: sa_family_t,
+ pub sin_port: in_port_t,
+ pub sin_addr: in_addr,
+ pub sin_zero: [u8; 8],
+ }
+
+ #[repr(align(4))]
+ #[derive(Copy, Clone)]
+ pub struct in6_addr {
+ pub s6_addr: [u8; 16],
+ }
+
+ #[derive(Copy, Clone)]
+ pub struct ipv6_mreq {
+ pub ipv6mr_multiaddr: in6_addr,
+ pub ipv6mr_interface: c_uint,
+ }
+
+ pub type in_addr_t = u32;
+ #[derive(Copy, Clone)]
+ pub struct in_addr {
+ pub s_addr: in_addr_t,
+ }
+
+ #[derive(Copy, Clone)]
+ pub struct linger {
+ pub l_onoff: c_int,
+ pub l_linger: c_int,
+ }
+
+ #[derive(Copy, Clone)]
+ pub struct ip_mreq {
+ pub imr_multiaddr: in_addr,
+ pub imr_interface: in_addr,
+ }
+
+ pub unsafe fn getsockname(_socket: __wasi_fd_t, _address: *mut sockaddr,
+ _address_len: *mut socklen_t) -> c_int {
+ unimplemented!()
+ }
+ pub unsafe fn connect(_socket: __wasi_fd_t, _address: *const sockaddr,
+ _len: socklen_t) -> c_int {
+ unimplemented!()
+ }
+ pub unsafe fn listen(_socket: __wasi_fd_t, _backlog: c_int) -> c_int {
+ unimplemented!()
+ }
+ pub unsafe fn bind(_socket: __wasi_fd_t, _address: *const sockaddr,
+ _address_len: socklen_t) -> c_int {
+ unimplemented!()
+ }
+
+ pub fn sockaddr_in_u32(sa: &sockaddr_in) -> u32 {
+ ::ntoh((*sa).sin_addr.s_addr)
+ }
+
+ pub fn in_addr_to_u32(addr: &in_addr) -> u32 {
+ ::ntoh(addr.s_addr)
+ }
+}
+
+pub struct Socket {
+ fd: __wasi_fd_t,
+}
+
+impl Socket {
+ pub fn new(_family: c_int, _ty: c_int) -> io::Result<Socket> {
+ unimplemented!()
+ }
+
+ pub fn raw(&self) -> libc::__wasi_fd_t {
+ self.fd
+ }
+
+ fn into_fd(self) -> libc::__wasi_fd_t {
+ let fd = self.fd;
+ mem::forget(self);
+ fd
+ }
+
+ pub fn into_tcp_listener(self) -> TcpListener {
+ unsafe { TcpListener::from_raw_fd(self.into_fd()) }
+ }
+
+ pub fn into_tcp_stream(self) -> TcpStream {
+ unsafe { TcpStream::from_raw_fd(self.into_fd()) }
+ }
+
+ pub fn into_udp_socket(self) -> UdpSocket {
+ unsafe { UdpSocket::from_raw_fd(self.into_fd()) }
+ }
+}
+
+impl ::FromInner for Socket {
+ type Inner = libc::__wasi_fd_t;
+ fn from_inner(fd: libc::__wasi_fd_t) -> Socket {
+ Socket { fd: fd }
+ }
+}
+
+impl Drop for Socket {
+ fn drop(&mut self) {
+ // unsafe {
+ // let _ = libc::close(self.fd);
+ // }
+ }
+} \ No newline at end of file
diff --git a/third_party/rust/net2/src/sys/windows/impls.rs b/third_party/rust/net2/src/sys/windows/impls.rs
new file mode 100644
index 0000000000..48e787ca20
--- /dev/null
+++ b/third_party/rust/net2/src/sys/windows/impls.rs
@@ -0,0 +1,44 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::os::windows::io::{FromRawSocket, RawSocket, AsRawSocket};
+use winapi::um::winsock2::SOCKET;
+
+use {TcpBuilder, UdpBuilder, FromInner, AsInner};
+use socket::Socket;
+use sys;
+
+impl FromRawSocket for TcpBuilder {
+ unsafe fn from_raw_socket(fd: RawSocket) -> TcpBuilder {
+ let sock = sys::Socket::from_inner(fd as SOCKET);
+ TcpBuilder::from_inner(Socket::from_inner(sock))
+ }
+}
+
+impl AsRawSocket for TcpBuilder {
+ fn as_raw_socket(&self) -> RawSocket {
+ // TODO: this unwrap() is very bad
+ self.as_inner().borrow().as_ref().unwrap().as_inner().raw() as RawSocket
+ }
+}
+
+impl FromRawSocket for UdpBuilder {
+ unsafe fn from_raw_socket(fd: RawSocket) -> UdpBuilder {
+ let sock = sys::Socket::from_inner(fd as SOCKET);
+ UdpBuilder::from_inner(Socket::from_inner(sock))
+ }
+}
+
+impl AsRawSocket for UdpBuilder {
+ fn as_raw_socket(&self) -> RawSocket {
+ // TODO: this unwrap() is very bad
+ self.as_inner().borrow().as_ref().unwrap().as_inner().raw() as RawSocket
+ }
+}
diff --git a/third_party/rust/net2/src/sys/windows/mod.rs b/third_party/rust/net2/src/sys/windows/mod.rs
new file mode 100644
index 0000000000..7086bec9dc
--- /dev/null
+++ b/third_party/rust/net2/src/sys/windows/mod.rs
@@ -0,0 +1,125 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(bad_style)]
+
+use std::io;
+use std::mem;
+use std::net::{TcpListener, TcpStream, UdpSocket};
+use std::os::windows::io::{RawSocket, FromRawSocket};
+use std::sync::{Once, ONCE_INIT};
+
+const HANDLE_FLAG_INHERIT: DWORD = 0x00000001;
+
+pub mod c {
+ pub use winapi::ctypes::*;
+ pub use winapi::um::handleapi::*;
+ pub use winapi::um::winbase::*;
+ pub use winapi::um::winsock2::*;
+ pub use winapi::um::ws2tcpip::*;
+
+ pub use winapi::shared::inaddr::*;
+ pub use winapi::shared::in6addr::*;
+ pub use winapi::shared::minwindef::*;
+ pub use winapi::shared::ntdef::*;
+ pub use winapi::shared::ws2def::*;
+ pub use winapi::shared::ws2def::{SOCK_STREAM, SOCK_DGRAM};
+ pub use winapi::shared::ws2def::SOCKADDR as sockaddr;
+ pub use winapi::shared::ws2def::SOCKADDR_STORAGE as sockaddr_storage;
+ pub use winapi::shared::ws2def::SOCKADDR_IN as sockaddr_in;
+ pub use winapi::shared::ws2def::ADDRESS_FAMILY as sa_family_t;
+ pub use winapi::shared::ws2ipdef::*;
+ pub use winapi::shared::ws2ipdef::SOCKADDR_IN6_LH as sockaddr_in6;
+ pub use winapi::shared::ws2ipdef::IP_MREQ as ip_mreq;
+ pub use winapi::shared::ws2ipdef::IPV6_MREQ as ipv6_mreq;
+
+ pub fn sockaddr_in_u32(sa: &sockaddr_in) -> u32 {
+ ::ntoh(unsafe { *sa.sin_addr.S_un.S_addr() })
+ }
+
+ pub fn in_addr_to_u32(addr: &in_addr) -> u32 {
+ ::ntoh(unsafe { *addr.S_un.S_addr() })
+ }
+}
+
+use self::c::*;
+
+mod impls;
+
+fn init() {
+ static INIT: Once = ONCE_INIT;
+
+ INIT.call_once(|| {
+ // Initialize winsock through the standard library by just creating a
+ // dummy socket. Whether this is successful or not we drop the result as
+ // libstd will be sure to have initialized winsock.
+ let _ = UdpSocket::bind("127.0.0.1:34254");
+ });
+}
+
+pub struct Socket {
+ socket: SOCKET,
+}
+
+impl Socket {
+ pub fn new(family: c_int, ty: c_int) -> io::Result<Socket> {
+ init();
+ let socket = try!(unsafe {
+ match WSASocketW(family, ty, 0, 0 as *mut _, 0,
+ WSA_FLAG_OVERLAPPED) {
+ INVALID_SOCKET => Err(io::Error::last_os_error()),
+ n => Ok(Socket { socket: n }),
+ }
+ });
+ try!(socket.set_no_inherit());
+ Ok(socket)
+ }
+
+ pub fn raw(&self) -> SOCKET { self.socket }
+
+ fn into_socket(self) -> SOCKET {
+ let socket = self.socket;
+ mem::forget(self);
+ socket
+ }
+
+ pub fn into_tcp_listener(self) -> TcpListener {
+ unsafe { TcpListener::from_raw_socket(self.into_socket() as RawSocket) }
+ }
+
+ pub fn into_tcp_stream(self) -> TcpStream {
+ unsafe { TcpStream::from_raw_socket(self.into_socket() as RawSocket) }
+ }
+
+ pub fn into_udp_socket(self) -> UdpSocket {
+ unsafe { UdpSocket::from_raw_socket(self.into_socket() as RawSocket) }
+ }
+
+ fn set_no_inherit(&self) -> io::Result<()> {
+ ::cvt_win(unsafe {
+ SetHandleInformation(self.socket as HANDLE, HANDLE_FLAG_INHERIT, 0)
+ }).map(|_| ())
+ }
+}
+
+impl ::FromInner for Socket {
+ type Inner = SOCKET;
+ fn from_inner(socket: SOCKET) -> Socket {
+ Socket { socket: socket }
+ }
+}
+
+impl Drop for Socket {
+ fn drop(&mut self) {
+ unsafe {
+ let _ = closesocket(self.socket);
+ }
+ }
+}
diff --git a/third_party/rust/net2/src/tcp.rs b/third_party/rust/net2/src/tcp.rs
new file mode 100644
index 0000000000..5a535dbb5c
--- /dev/null
+++ b/third_party/rust/net2/src/tcp.rs
@@ -0,0 +1,161 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::cell::RefCell;
+use std::io;
+use std::net::{SocketAddr, ToSocketAddrs, TcpListener, TcpStream};
+use std::fmt;
+
+use IntoInner;
+use socket::Socket;
+use sys::c;
+
+/// An "in progress" TCP socket which has not yet been connected or listened.
+///
+/// Allows configuration of a socket before one of these operations is executed.
+pub struct TcpBuilder {
+ socket: RefCell<Option<Socket>>,
+}
+
+impl TcpBuilder {
+ /// Constructs a new TcpBuilder with the `AF_INET` domain, the `SOCK_STREAM`
+ /// type, and with a protocol argument of 0.
+ ///
+ /// Note that passing other kinds of flags or arguments can be done through
+ /// the `FromRaw{Fd,Socket}` implementation.
+ pub fn new_v4() -> io::Result<TcpBuilder> {
+ Socket::new(c::AF_INET, c::SOCK_STREAM).map(::FromInner::from_inner)
+ }
+
+ /// Constructs a new TcpBuilder with the `AF_INET6` domain, the `SOCK_STREAM`
+ /// type, and with a protocol argument of 0.
+ ///
+ /// Note that passing other kinds of flags or arguments can be done through
+ /// the `FromRaw{Fd,Socket}` implementation.
+ pub fn new_v6() -> io::Result<TcpBuilder> {
+ Socket::new(c::AF_INET6, c::SOCK_STREAM).map(::FromInner::from_inner)
+ }
+
+ /// Binds this socket to the specified address.
+ ///
+ /// This function directly corresponds to the bind(2) function on Windows
+ /// and Unix.
+ pub fn bind<T>(&self, addr: T) -> io::Result<&TcpBuilder>
+ where T: ToSocketAddrs
+ {
+ self.with_socket(|sock| {
+ let addr = try!(::one_addr(addr));
+ sock.bind(&addr)
+ }).map(|()| self)
+ }
+
+ /// Mark a socket as ready to accept incoming connection requests using
+ /// accept()
+ ///
+ /// This function directly corresponds to the listen(2) function on Windows
+ /// and Unix.
+ ///
+ /// An error will be returned if `listen` or `connect` has already been
+ /// called on this builder.
+ pub fn listen(&self, backlog: i32) -> io::Result<TcpListener> {
+ self.with_socket(|sock| {
+ sock.listen(backlog)
+ }).and_then(|()| {
+ self.to_tcp_listener()
+ })
+ }
+
+ /// Initiate a connection on this socket to the specified address.
+ ///
+ /// This function directly corresponds to the connect(2) function on Windows
+ /// and Unix.
+ ///
+ /// An error will be returned if `listen` or `connect` has already been
+ /// called on this builder.
+ pub fn connect<T>(&self, addr: T) -> io::Result<TcpStream>
+ where T: ToSocketAddrs
+ {
+ self.with_socket(|sock| {
+ let err = io::Error::new(io::ErrorKind::Other,
+ "no socket addresses resolved");
+ try!(addr.to_socket_addrs()).fold(Err(err), |prev, addr| {
+ prev.or_else(|_| sock.connect(&addr))
+ })
+ }).and_then(|()| {
+ self.to_tcp_stream()
+ })
+ }
+
+ /// Converts this builder into a `TcpStream`
+ ///
+ /// This function will consume the internal socket and return it re-wrapped
+ /// as a `TcpStream`. An error will be returned if the internal socket has
+ /// already been consumed from a successful call to `connect`, `listen`,
+ /// etc.
+ pub fn to_tcp_stream(&self) -> io::Result<TcpStream> {
+ self.socket.borrow_mut().take().map(|s| s.into_inner().into_tcp_stream())
+ .ok_or(io::Error::new(io::ErrorKind::Other,
+ "socket has already been consumed"))
+ }
+
+ /// Converts this builder into a `TcpListener`
+ ///
+ /// This function will consume the internal socket and return it re-wrapped
+ /// as a `TcpListener`. An error will be returned if the internal socket has
+ /// already been consumed from a successful call to `connect`, `listen`,
+ /// etc.
+ pub fn to_tcp_listener(&self) -> io::Result<TcpListener> {
+ self.socket.borrow_mut().take()
+ .map(|s| s.into_inner().into_tcp_listener())
+ .ok_or(io::Error::new(io::ErrorKind::Other,
+ "socket has already been consumed"))
+ }
+
+ /// Returns the address of the local half of this TCP socket.
+ ///
+ /// An error will be returned if `listen` or `connect` has already been
+ /// called on this builder.
+ pub fn local_addr(&self) -> io::Result<SocketAddr> {
+ match *self.socket.borrow() {
+ Some(ref s) => s.getsockname(),
+ None => Err(io::Error::new(io::ErrorKind::Other,
+ "builder has already finished its socket")),
+ }
+ }
+
+ fn with_socket<F>(&self, f: F) -> io::Result<()>
+ where F: FnOnce(&Socket) -> io::Result<()>
+ {
+ match *self.socket.borrow() {
+ Some(ref s) => f(s),
+ None => Err(io::Error::new(io::ErrorKind::Other,
+ "builder has already finished its socket")),
+ }
+ }
+}
+
+impl fmt::Debug for TcpBuilder {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "TcpBuilder {{ socket: {:?} }}",
+ self.socket.borrow().as_ref().unwrap())
+ }
+}
+
+impl ::AsInner for TcpBuilder {
+ type Inner = RefCell<Option<Socket>>;
+ fn as_inner(&self) -> &RefCell<Option<Socket>> { &self.socket }
+}
+
+impl ::FromInner for TcpBuilder {
+ type Inner = Socket;
+ fn from_inner(sock: Socket) -> TcpBuilder {
+ TcpBuilder { socket: RefCell::new(Some(sock)) }
+ }
+}
diff --git a/third_party/rust/net2/src/udp.rs b/third_party/rust/net2/src/udp.rs
new file mode 100644
index 0000000000..d061ab5c6f
--- /dev/null
+++ b/third_party/rust/net2/src/udp.rs
@@ -0,0 +1,89 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::cell::RefCell;
+use std::fmt;
+use std::io;
+use std::net::{ToSocketAddrs, UdpSocket};
+
+use IntoInner;
+use socket::Socket;
+use sys::c;
+
+/// An "in progress" UDP socket which has not yet been connected.
+///
+/// Allows configuration of a socket before the socket is connected.
+pub struct UdpBuilder {
+ socket: RefCell<Option<Socket>>,
+}
+
+impl UdpBuilder {
+ /// Constructs a new UdpBuilder with the `AF_INET` domain, the `SOCK_DGRAM`
+ /// type, and with a protocol argument of 0.
+ ///
+ /// Note that passing other kinds of flags or arguments can be done through
+ /// the `FromRaw{Fd,Socket}` implementation.
+ pub fn new_v4() -> io::Result<UdpBuilder> {
+ Socket::new(c::AF_INET, c::SOCK_DGRAM).map(::FromInner::from_inner)
+ }
+
+ /// Constructs a new UdpBuilder with the `AF_INET6` domain, the `SOCK_DGRAM`
+ /// type, and with a protocol argument of 0.
+ ///
+ /// Note that passing other kinds of flags or arguments can be done through
+ /// the `FromRaw{Fd,Socket}` implementation.
+ pub fn new_v6() -> io::Result<UdpBuilder> {
+ Socket::new(c::AF_INET6, c::SOCK_DGRAM).map(::FromInner::from_inner)
+ }
+
+ /// Binds this socket to the specified address.
+ ///
+ /// This function directly corresponds to the bind(2) function on Windows
+ /// and Unix.
+ pub fn bind<T>(&self, addr: T) -> io::Result<UdpSocket>
+ where T: ToSocketAddrs
+ {
+ try!(self.with_socket(|sock| {
+ let addr = try!(::one_addr(addr));
+ sock.bind(&addr)
+ }));
+ Ok(self.socket.borrow_mut().take().unwrap().into_inner().into_udp_socket())
+ }
+
+ fn with_socket<F>(&self, f: F) -> io::Result<()>
+ where F: FnOnce(&Socket) -> io::Result<()>
+ {
+ match *self.socket.borrow() {
+ Some(ref s) => f(s),
+ None => Err(io::Error::new(io::ErrorKind::Other,
+ "builder has already finished its socket")),
+ }
+ }
+}
+
+impl fmt::Debug for UdpBuilder {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "UdpBuilder {{ socket: {:?} }}",
+ self.socket.borrow().as_ref().unwrap())
+ }
+}
+
+impl ::AsInner for UdpBuilder {
+ type Inner = RefCell<Option<Socket>>;
+ fn as_inner(&self) -> &RefCell<Option<Socket>> { &self.socket }
+}
+
+impl ::FromInner for UdpBuilder {
+ type Inner = Socket;
+ fn from_inner(sock: Socket) -> UdpBuilder {
+ UdpBuilder { socket: RefCell::new(Some(sock)) }
+ }
+}
+
diff --git a/third_party/rust/net2/src/unix.rs b/third_party/rust/net2/src/unix.rs
new file mode 100644
index 0000000000..a1e1c6f5e9
--- /dev/null
+++ b/third_party/rust/net2/src/unix.rs
@@ -0,0 +1,57 @@
+//! Unix-specific extensions to the `std::net` types.
+
+use std::io;
+use sys::c::{self, c_int};
+
+use {TcpBuilder, UdpBuilder};
+use ext::{self, AsSock};
+
+/// Unix-specific extensions for the `TcpBuilder` type in this library.
+pub trait UnixTcpBuilderExt {
+ /// Set value for the `SO_REUSEPORT` option on this socket.
+ ///
+ /// This indicates that further calls to `bind` may allow reuse of local
+ /// addresses. For IPv4 sockets this means that a socket may bind even when
+ /// there's a socket already listening on this port.
+ fn reuse_port(&self, reuse: bool) -> io::Result<&Self>;
+
+ /// Check the value of the `SO_REUSEPORT` option on this socket.
+ fn get_reuse_port(&self) -> io::Result<bool>;
+}
+
+impl UnixTcpBuilderExt for TcpBuilder {
+ fn reuse_port(&self, reuse: bool) -> io::Result<&Self> {
+ ext::set_opt(self.as_sock(), c::SOL_SOCKET, c::SO_REUSEPORT,
+ reuse as c_int).map(|()| self)
+ }
+
+ fn get_reuse_port(&self) -> io::Result<bool> {
+ ext::get_opt(self.as_sock(), c::SOL_SOCKET, c::SO_REUSEPORT)
+ .map(ext::int2bool)
+ }
+}
+
+/// Unix-specific extensions for the `UdpBuilder` type in this library.
+pub trait UnixUdpBuilderExt {
+ /// Set value for the `SO_REUSEPORT` option on this socket.
+ ///
+ /// This indicates that further calls to `bind` may allow reuse of local
+ /// addresses. For IPv4 sockets this means that a socket may bind even when
+ /// there's a socket already listening on this port.
+ fn reuse_port(&self, reuse: bool) -> io::Result<&Self>;
+
+ /// Check the value of the `SO_REUSEPORT` option on this socket.
+ fn get_reuse_port(&self) -> io::Result<bool>;
+}
+
+impl UnixUdpBuilderExt for UdpBuilder {
+ fn reuse_port(&self, reuse: bool) -> io::Result<&Self> {
+ ext::set_opt(self.as_sock(), c::SOL_SOCKET, c::SO_REUSEPORT,
+ reuse as c_int).map(|()| self)
+ }
+
+ fn get_reuse_port(&self) -> io::Result<bool> {
+ ext::get_opt(self.as_sock(), c::SOL_SOCKET, c::SO_REUSEPORT)
+ .map(ext::int2bool)
+ }
+}
diff --git a/third_party/rust/net2/src/utils.rs b/third_party/rust/net2/src/utils.rs
new file mode 100644
index 0000000000..21fe9d61fc
--- /dev/null
+++ b/third_party/rust/net2/src/utils.rs
@@ -0,0 +1,51 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+#[doc(hidden)]
+pub trait NetInt {
+ fn from_be(i: Self) -> Self;
+ fn to_be(&self) -> Self;
+}
+macro_rules! doit {
+ ($($t:ident)*) => ($(impl NetInt for $t {
+ fn from_be(i: Self) -> Self { <$t>::from_be(i) }
+ fn to_be(&self) -> Self { <$t>::to_be(*self) }
+ })*)
+}
+doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
+
+#[doc(hidden)]
+pub trait One {
+ fn one() -> Self;
+}
+
+macro_rules! one {
+ ($($t:ident)*) => ($(
+ impl One for $t { fn one() -> $t { 1 } }
+ )*)
+}
+
+one! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
+
+
+#[doc(hidden)]
+pub trait Zero {
+ fn zero() -> Self;
+}
+
+macro_rules! zero {
+ ($($t:ident)*) => ($(
+ impl Zero for $t { fn zero() -> $t { 0 } }
+ )*)
+}
+
+zero! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
+