]> git.proxmox.com Git - rustc.git/blame - vendor/socket2/9f0fbf2.diff
New upstream version 1.50.0+dfsg1
[rustc.git] / vendor / socket2 / 9f0fbf2.diff
CommitLineData
fc512014
XL
1src/socket.rs
2src/sys/unix.rs
3src/sys/windows.rs
4
5
6
7
8commit 9f0fbf2ed487668e4e2b5357a8e4a167e7ec903a
9Author: Thomas de Zeeuw <thomasdezeeuw@gmail.com>
10Date: Sat Jan 18 16:43:21 2020 +0100
11
12 Part 1 of the rewrite
13
14 Currently not functional on Windows and a lot of methods are removed,
15 but its a start.
16
17diff --git a/src/socket.rs b/src/socket.rs
18index 354c5cf..424e094 100644
19--- a/src/socket.rs
20+++ b/src/socket.rs
21@@ -8,201 +8,107 @@
22 // option. This file may not be copied, modified, or distributed
23 // except according to those terms.
24
25-use std::fmt;
26-use std::io::{self, Read, Write};
27-use std::net::{self, Ipv4Addr, Ipv6Addr, Shutdown};
28-#[cfg(all(unix, feature = "unix"))]
29-use std::os::unix::net::{UnixDatagram, UnixListener, UnixStream};
30-use std::time::Duration;
31+use std::net::{Shutdown, TcpListener, TcpStream, UdpSocket};
32+#[cfg(unix)]
33+use std::os::unix::io::{FromRawFd, IntoRawFd};
34+use std::{fmt, io};
35
36-use crate::sys;
37+use crate::sys::{self, c_int};
38 use crate::{Domain, Protocol, SockAddr, Type};
39
40-/// Newtype, owned, wrapper around a system socket.
41+/// An owned system socket.
42 ///
43-/// This type simply wraps an instance of a file descriptor (`c_int`) on Unix
44-/// and an instance of `SOCKET` on Windows. This is the main type exported by
45-/// this crate and is intended to mirror the raw semantics of sockets on
46-/// platforms as closely as possible. Almost all methods correspond to
47-/// precisely one libc or OS API call which is essentially just a "Rustic
48-/// translation" of what's below.
49+/// This type simply wraps an instance of a file descriptor (`int`) on Unix and
50+/// an instance of `SOCKET` on Windows. This is the main type exported by this
51+/// crate and is intended to mirror the raw semantics of sockets on platforms as
52+/// closely as possible. All methods correspond to precisely one libc or OS API
53+/// call which is essentially just a "Rustic translation" of what's below.
54+///
55+/// # Notes
56+///
57+/// This type can be converted to and from all network types provided by the
58+/// standard library using the [`From`] and [`Into`] traits. Is up to the user
59+/// to ensure the socket is setup correctly for a given type!
60 ///
61 /// # Examples
62 ///
63-/// ```no_run
64-/// use std::net::SocketAddr;
65-/// use socket2::{Socket, Domain, Type, SockAddr};
66+/// ```
67+/// # fn main() -> std::io::Result<()> {
68+/// use std::net::{SocketAddr, TcpListener};
69+/// use socket2::{Socket, Domain, Type};
70 ///
71-/// // create a TCP listener bound to two addresses
72-/// let socket = Socket::new(Domain::ipv4(), Type::stream(), None).unwrap();
73+/// // Create a new `Socket`.
74+/// let socket = Socket::new(Domain::ipv4(), Type::stream(), None)?;
75 ///
76-/// socket.bind(&"127.0.0.1:12345".parse::<SocketAddr>().unwrap().into()).unwrap();
77-/// socket.bind(&"127.0.0.1:12346".parse::<SocketAddr>().unwrap().into()).unwrap();
78-/// socket.listen(128).unwrap();
79+/// // Bind the socket to an addresses.
80+/// let addr1: SocketAddr = "127.0.0.1:15123".parse().unwrap();
81+/// socket.bind(&addr1.into())?;
82 ///
83-/// let listener = socket.into_tcp_listener();
84-/// // ...
85+/// // Start listening on the socket.
86+/// socket.listen(128)?;
87+///
88+/// // Finally convert it to `TcpListener` from the standard library. Now it can
89+/// // be used like any other `TcpListener`.
90+/// let listener: TcpListener = socket.into();
91+/// # drop(listener);
92+/// # Ok(())
93+/// # }
94 /// ```
95 pub struct Socket {
96- // The `sys` module most have access to the socket.
97- pub(crate) inner: sys::Socket,
98+ // The `sys` module must have access to the raw socket to implement OS
99+ // specific additional methods, e.g. Unix Domain sockets (UDS).
100+ pub(crate) inner: sys::RawSocket,
101 }
102
103 impl Socket {
104 /// Creates a new socket ready to be configured.
105 ///
106- /// This function corresponds to `socket(2)` and simply creates a new
107- /// socket, no other configuration is done and further functions must be
108- /// invoked to configure this socket.
109+ /// This function corresponds to `socket(2)`.
110 pub fn new(domain: Domain, type_: Type, protocol: Option<Protocol>) -> io::Result<Socket> {
111- let protocol = protocol.map(|p| p.0).unwrap_or(0);
112- Ok(Socket {
113- inner: sys::Socket::new(domain.0, type_.0, protocol)?,
114- })
115- }
116-
117- /// Creates a pair of sockets which are connected to each other.
118- ///
119- /// This function corresponds to `socketpair(2)`.
120- ///
121- /// This function is only available on Unix when the `pair` feature is
122- /// enabled.
123- #[cfg(all(unix, feature = "pair"))]
124- pub fn pair(
125- domain: Domain,
126- type_: Type,
127- protocol: Option<Protocol>,
128- ) -> io::Result<(Socket, Socket)> {
129- let protocol = protocol.map(|p| p.0).unwrap_or(0);
130- let sockets = sys::Socket::pair(domain.0, type_.0, protocol)?;
131- Ok((Socket { inner: sockets.0 }, Socket { inner: sockets.1 }))
132- }
133-
134- /// Consumes this `Socket`, converting it to a `TcpStream`.
135- pub fn into_tcp_stream(self) -> net::TcpStream {
136- self.into()
137- }
138-
139- /// Consumes this `Socket`, converting it to a `TcpListener`.
140- pub fn into_tcp_listener(self) -> net::TcpListener {
141- self.into()
142- }
143-
144- /// Consumes this `Socket`, converting it to a `UdpSocket`.
145- pub fn into_udp_socket(self) -> net::UdpSocket {
146- self.into()
147- }
148-
149- /// Consumes this `Socket`, converting it into a `UnixStream`.
150- ///
151- /// This function is only available on Unix when the `unix` feature is
152- /// enabled.
153- #[cfg(all(unix, feature = "unix"))]
154- pub fn into_unix_stream(self) -> UnixStream {
155- self.into()
156- }
157-
158- /// Consumes this `Socket`, converting it into a `UnixListener`.
159- ///
160- /// This function is only available on Unix when the `unix` feature is
161- /// enabled.
162- #[cfg(all(unix, feature = "unix"))]
163- pub fn into_unix_listener(self) -> UnixListener {
164- self.into()
165- }
166-
167- /// Consumes this `Socket`, converting it into a `UnixDatagram`.
168- ///
169- /// This function is only available on Unix when the `unix` feature is
170- /// enabled.
171- #[cfg(all(unix, feature = "unix"))]
172- pub fn into_unix_datagram(self) -> UnixDatagram {
173- self.into()
174+ sys::socket(domain.0, type_.0, protocol.map(|p| p.0).unwrap_or(0))
175 }
176
177 /// Initiate a connection on this socket to the specified address.
178 ///
179- /// This function directly corresponds to the connect(2) function on Windows
180- /// and Unix.
181- ///
182- /// An error will be returned if `listen` or `connect` has already been
183- /// called on this builder.
184+ /// This function directly corresponds to the `connect(2)` function.
185 pub fn connect(&self, addr: &SockAddr) -> io::Result<()> {
186- self.inner.connect(addr)
187- }
188-
189- /// Initiate a connection on this socket to the specified address, only
190- /// only waiting for a certain period of time for the connection to be
191- /// established.
192- ///
193- /// Unlike many other methods on `Socket`, this does *not* correspond to a
194- /// single C function. It sets the socket to nonblocking mode, connects via
195- /// connect(2), and then waits for the connection to complete with poll(2)
196- /// on Unix and select on Windows. When the connection is complete, the
197- /// socket is set back to blocking mode. On Unix, this will loop over
198- /// `EINTR` errors.
199- ///
200- /// # Warnings
201- ///
202- /// The nonblocking state of the socket is overridden by this function -
203- /// it will be returned in blocking mode on success, and in an indeterminate
204- /// state on failure.
205- ///
206- /// If the connection request times out, it may still be processing in the
207- /// background - a second call to `connect` or `connect_timeout` may fail.
208- pub fn connect_timeout(&self, addr: &SockAddr, timeout: Duration) -> io::Result<()> {
209- self.inner.connect_timeout(addr, timeout)
210+ sys::connect(self.inner, addr.as_ptr(), addr.len())
211 }
212
213 /// Binds this socket to the specified address.
214 ///
215- /// This function directly corresponds to the bind(2) function on Windows
216- /// and Unix.
217+ /// This function directly corresponds to the `bind(2)` function.
218 pub fn bind(&self, addr: &SockAddr) -> io::Result<()> {
219- self.inner.bind(addr)
220+ sys::bind(self.inner, addr.as_ptr(), addr.len())
221 }
222
223- /// Mark a socket as ready to accept incoming connection requests using
224- /// accept()
225+ /// Returns the socket address of the local half of this connection.
226 ///
227- /// This function directly corresponds to the listen(2) function on Windows
228- /// and Unix.
229- ///
230- /// An error will be returned if `listen` or `connect` has already been
231- /// called on this builder.
232- pub fn listen(&self, backlog: i32) -> io::Result<()> {
233- self.inner.listen(backlog)
234+ /// This function directly corresponds to the `getsockname(2)` function.
235+ pub fn local_addr(&self) -> io::Result<SockAddr> {
236+ sys::getsockname(self.inner)
237 }
238
239- /// Accept a new incoming connection from this listener.
240+ /// Returns the socket address of the remote peer of this connection.
241 ///
242- /// This function will block the calling thread until a new connection is
243- /// established. When established, the corresponding `Socket` and the
244- /// remote peer's address will be returned.
245- pub fn accept(&self) -> io::Result<(Socket, SockAddr)> {
246- self.inner
247- .accept()
248- .map(|(socket, addr)| (Socket { inner: socket }, addr))
249- }
250-
251- /// Returns the socket address of the local half of this TCP connection.
252- pub fn local_addr(&self) -> io::Result<SockAddr> {
253- self.inner.local_addr()
254+ /// This function directly corresponds to the `getpeername(2)` function.
255+ pub fn peer_addr(&self) -> io::Result<SockAddr> {
256+ sys::getpeername(self.inner)
257 }
258
259- /// Returns the socket address of the remote peer of this TCP connection.
260- pub fn peer_addr(&self) -> io::Result<SockAddr> {
261- self.inner.peer_addr()
262+ /// Mark a socket as ready to accept incoming connection requests using
263+ /// `accept(2)`.
264+ ///
265+ /// This function directly corresponds to the `listen(2)` function.
266+ pub fn listen(&self, backlog: c_int) -> io::Result<()> {
267+ sys::listen(self.inner, backlog)
268 }
269
270- /// Creates a new independently owned handle to the underlying socket.
271+ /// Accept a new incoming connection from this listener.
272 ///
273- /// The returned `TcpStream` is a reference to the same stream that this
274- /// object references. Both handles will read and write the same stream of
275- /// data, and options set on one stream will be propagated to the other
276- /// stream.
277- pub fn try_clone(&self) -> io::Result<Socket> {
278- self.inner.try_clone().map(|s| Socket { inner: s })
279+ /// This function directly corresponds to the `accept(2)` function.
280+ pub fn accept(&self) -> io::Result<(Socket, SockAddr)> {
281+ sys::accept(self.inner)
282 }
283
284 /// Get the value of the `SO_ERROR` option on this socket.
285@@ -211,15 +117,14 @@ impl Socket {
286 /// the field in the process. This can be useful for checking errors between
287 /// calls.
288 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
289- self.inner.take_error()
290- }
291-
292- /// Moves this TCP stream into or out of nonblocking mode.
293- ///
294- /// On Unix this corresponds to calling fcntl, and on Windows this
295- /// corresponds to calling ioctlsocket.
296- pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
297- self.inner.set_nonblocking(nonblocking)
298+ self.getsockopt::<c_int>(libc::SOL_SOCKET, libc::SO_ERROR)
299+ .map(|errno| {
300+ if errno == 0 {
301+ None
302+ } else {
303+ Some(io::Error::from_raw_os_error(errno))
304+ }
305+ })
306 }
307
308 /// Shuts down the read, write, or both halves of this connection.
309@@ -227,689 +132,110 @@ impl Socket {
310 /// This function will cause all pending and future I/O on the specified
311 /// portions to return immediately with an appropriate value.
312 pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
313- self.inner.shutdown(how)
314- }
315-
316- /// Receives data on the socket from the remote address to which it is
317- /// connected.
318- ///
319- /// The [`connect`] method will connect this socket to a remote address. This
320- /// method will fail if the socket is not connected.
321- ///
322- /// [`connect`]: #method.connect
323- pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
324- self.inner.recv(buf)
325- }
326-
327- /// Receives data on the socket from the remote adress to which it is
328- /// connected, without removing that data from the queue. On success,
329- /// returns the number of bytes peeked.
330- ///
331- /// Successive calls return the same data. This is accomplished by passing
332- /// `MSG_PEEK` as a flag to the underlying `recv` system call.
333- pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
334- self.inner.peek(buf)
335- }
336-
337- /// Receives data from the socket. On success, returns the number of bytes
338- /// read and the address from whence the data came.
339- pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SockAddr)> {
340- self.inner.recv_from(buf)
341- }
342-
343- /// Receives data from the socket, without removing it from the queue.
344- ///
345- /// Successive calls return the same data. This is accomplished by passing
346- /// `MSG_PEEK` as a flag to the underlying `recvfrom` system call.
347- ///
348- /// On success, returns the number of bytes peeked and the address from
349- /// whence the data came.
350- pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SockAddr)> {
351- self.inner.peek_from(buf)
352- }
353-
354- /// Sends data on the socket to a connected peer.
355- ///
356- /// This is typically used on TCP sockets or datagram sockets which have
357- /// been connected.
358- ///
359- /// On success returns the number of bytes that were sent.
360- pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
361- self.inner.send(buf)
362- }
363-
364- /// Sends data on the socket to the given address. On success, returns the
365- /// number of bytes written.
366- ///
367- /// This is typically used on UDP or datagram-oriented sockets. On success
368- /// returns the number of bytes that were sent.
369- pub fn send_to(&self, buf: &[u8], addr: &SockAddr) -> io::Result<usize> {
370- self.inner.send_to(buf, addr)
371- }
372-
373- // ================================================
374-
375- /// Gets the value of the `IP_TTL` option for this socket.
376- ///
377- /// For more information about this option, see [`set_ttl`][link].
378- ///
379- /// [link]: #method.set_ttl
380- pub fn ttl(&self) -> io::Result<u32> {
381- self.inner.ttl()
382- }
383-
384- /// Sets the value for the `IP_TTL` option on this socket.
385- ///
386- /// This value sets the time-to-live field that is used in every packet sent
387- /// from this socket.
388- pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
389- self.inner.set_ttl(ttl)
390- }
391-
392- /// Gets the value of the `IPV6_UNICAST_HOPS` option for this socket.
393- ///
394- /// Specifies the hop limit for ipv6 unicast packets
395- pub fn unicast_hops_v6(&self) -> io::Result<u32> {
396- self.inner.unicast_hops_v6()
397- }
398-
399- /// Sets the value for the `IPV6_UNICAST_HOPS` option on this socket.
400- ///
401- /// Specifies the hop limit for ipv6 unicast packets
402- pub fn set_unicast_hops_v6(&self, ttl: u32) -> io::Result<()> {
403- self.inner.set_unicast_hops_v6(ttl)
404- }
405-
406- /// Gets the value of the `IPV6_V6ONLY` option for this socket.
407- ///
408- /// For more information about this option, see [`set_only_v6`][link].
409- ///
410- /// [link]: #method.set_only_v6
411- pub fn only_v6(&self) -> io::Result<bool> {
412- self.inner.only_v6()
413- }
414-
415- /// Sets the value for the `IPV6_V6ONLY` option on this socket.
416- ///
417- /// If this is set to `true` then the socket is restricted to sending and
418- /// receiving IPv6 packets only. In this case two IPv4 and IPv6 applications
419- /// can bind the same port at the same time.
420- ///
421- /// If this is set to `false` then the socket can be used to send and
422- /// receive packets from an IPv4-mapped IPv6 address.
423- pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
424- self.inner.set_only_v6(only_v6)
425- }
426-
427- /// Returns the read timeout of this socket.
428- ///
429- /// If the timeout is `None`, then `read` calls will block indefinitely.
430- pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
431- self.inner.read_timeout()
432- }
433-
434- /// Sets the read timeout to the timeout specified.
435- ///
436- /// If the value specified is `None`, then `read` calls will block
437- /// indefinitely. It is an error to pass the zero `Duration` to this
438- /// method.
439- pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
440- self.inner.set_read_timeout(dur)
441- }
442-
443- /// Returns the write timeout of this socket.
444- ///
445- /// If the timeout is `None`, then `write` calls will block indefinitely.
446- pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
447- self.inner.write_timeout()
448- }
449-
450- /// Sets the write timeout to the timeout specified.
451- ///
452- /// If the value specified is `None`, then `write` calls will block
453- /// indefinitely. It is an error to pass the zero `Duration` to this
454- /// method.
455- pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
456- self.inner.set_write_timeout(dur)
457- }
458-
459- /// Gets the value of the `TCP_NODELAY` option on this socket.
460- ///
461- /// For more information about this option, see [`set_nodelay`][link].
462- ///
463- /// [link]: #method.set_nodelay
464- pub fn nodelay(&self) -> io::Result<bool> {
465- self.inner.nodelay()
466- }
467-
468- /// Sets the value of the `TCP_NODELAY` option on this socket.
469- ///
470- /// If set, this option disables the Nagle algorithm. This means that
471- /// segments are always sent as soon as possible, even if there is only a
472- /// small amount of data. When not set, data is buffered until there is a
473- /// sufficient amount to send out, thereby avoiding the frequent sending of
474- /// small packets.
475- pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
476- self.inner.set_nodelay(nodelay)
477- }
478-
479- /// Sets the value of the `SO_BROADCAST` option for this socket.
480- ///
481- /// When enabled, this socket is allowed to send packets to a broadcast
482- /// address.
483- pub fn broadcast(&self) -> io::Result<bool> {
484- self.inner.broadcast()
485- }
486-
487- /// Gets the value of the `SO_BROADCAST` option for this socket.
488- ///
489- /// For more information about this option, see
490- /// [`set_broadcast`][link].
491- ///
492- /// [link]: #method.set_broadcast
493- pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
494- self.inner.set_broadcast(broadcast)
495- }
496-
497- /// Gets the value of the `IP_MULTICAST_LOOP` option for this socket.
498- ///
499- /// For more information about this option, see
500- /// [`set_multicast_loop_v4`][link].
501- ///
502- /// [link]: #method.set_multicast_loop_v4
503- pub fn multicast_loop_v4(&self) -> io::Result<bool> {
504- self.inner.multicast_loop_v4()
505- }
506-
507- /// Sets the value of the `IP_MULTICAST_LOOP` option for this socket.
508- ///
509- /// If enabled, multicast packets will be looped back to the local socket.
510- /// Note that this may not have any affect on IPv6 sockets.
511- pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
512- self.inner.set_multicast_loop_v4(multicast_loop_v4)
513- }
514-
515- /// Gets the value of the `IP_MULTICAST_TTL` option for this socket.
516- ///
517- /// For more information about this option, see
518- /// [`set_multicast_ttl_v4`][link].
519- ///
520- /// [link]: #method.set_multicast_ttl_v4
521- pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
522- self.inner.multicast_ttl_v4()
523- }
524-
525- /// Sets the value of the `IP_MULTICAST_TTL` option for this socket.
526- ///
527- /// Indicates the time-to-live value of outgoing multicast packets for
528- /// this socket. The default value is 1 which means that multicast packets
529- /// don't leave the local network unless explicitly requested.
530- ///
531- /// Note that this may not have any affect on IPv6 sockets.
532- pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
533- self.inner.set_multicast_ttl_v4(multicast_ttl_v4)
534- }
535-
536- /// Gets the value of the `IPV6_MULTICAST_HOPS` option for this socket
537- ///
538- /// For more information about this option, see
539- /// [`set_multicast_hops_v6`][link].
540- ///
541- /// [link]: #method.set_multicast_hops_v6
542- pub fn multicast_hops_v6(&self) -> io::Result<u32> {
543- self.inner.multicast_hops_v6()
544- }
545-
546- /// Sets the value of the `IPV6_MULTICAST_HOPS` option for this socket
547- ///
548- /// Indicates the number of "routers" multicast packets will transit for
549- /// this socket. The default value is 1 which means that multicast packets
550- /// don't leave the local network unless explicitly requested.
551- pub fn set_multicast_hops_v6(&self, hops: u32) -> io::Result<()> {
552- self.inner.set_multicast_hops_v6(hops)
553- }
554-
555- /// Gets the value of the `IP_MULTICAST_IF` option for this socket.
556- ///
557- /// For more information about this option, see
558- /// [`set_multicast_if_v4`][link].
559- ///
560- /// [link]: #method.set_multicast_if_v4
561- ///
562- /// Returns the interface to use for routing multicast packets.
563- pub fn multicast_if_v4(&self) -> io::Result<Ipv4Addr> {
564- self.inner.multicast_if_v4()
565- }
566-
567- /// Sets the value of the `IP_MULTICAST_IF` option for this socket.
568- ///
569- /// Specifies the interface to use for routing multicast packets.
570- pub fn set_multicast_if_v4(&self, interface: &Ipv4Addr) -> io::Result<()> {
571- self.inner.set_multicast_if_v4(interface)
572- }
573-
574- /// Gets the value of the `IPV6_MULTICAST_IF` option for this socket.
575- ///
576- /// For more information about this option, see
577- /// [`set_multicast_if_v6`][link].
578- ///
579- /// [link]: #method.set_multicast_if_v6
580- ///
581- /// Returns the interface to use for routing multicast packets.
582- pub fn multicast_if_v6(&self) -> io::Result<u32> {
583- self.inner.multicast_if_v6()
584- }
585-
586- /// Sets the value of the `IPV6_MULTICAST_IF` option for this socket.
587- ///
588- /// Specifies the interface to use for routing multicast packets. Unlike ipv4, this
589- /// is generally required in ipv6 contexts where network routing prefixes may
590- /// overlap.
591- pub fn set_multicast_if_v6(&self, interface: u32) -> io::Result<()> {
592- self.inner.set_multicast_if_v6(interface)
593- }
594-
595- /// Gets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
596- ///
597- /// For more information about this option, see
598- /// [`set_multicast_loop_v6`][link].
599- ///
600- /// [link]: #method.set_multicast_loop_v6
601- pub fn multicast_loop_v6(&self) -> io::Result<bool> {
602- self.inner.multicast_loop_v6()
603- }
604-
605- /// Sets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
606- ///
607- /// Controls whether this socket sees the multicast packets it sends itself.
608- /// Note that this may not have any affect on IPv4 sockets.
609- pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
610- self.inner.set_multicast_loop_v6(multicast_loop_v6)
611- }
612-
613- /// Executes an operation of the `IP_ADD_MEMBERSHIP` type.
614- ///
615- /// This function specifies a new multicast group for this socket to join.
616- /// The address must be a valid multicast address, and `interface` is the
617- /// address of the local interface with which the system should join the
618- /// multicast group. If it's equal to `INADDR_ANY` then an appropriate
619- /// interface is chosen by the system.
620- pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
621- self.inner.join_multicast_v4(multiaddr, interface)
622- }
623-
624- /// Executes an operation of the `IPV6_ADD_MEMBERSHIP` type.
625- ///
626- /// This function specifies a new multicast group for this socket to join.
627- /// The address must be a valid multicast address, and `interface` is the
628- /// index of the interface to join/leave (or 0 to indicate any interface).
629- pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
630- self.inner.join_multicast_v6(multiaddr, interface)
631- }
632-
633- /// Executes an operation of the `IP_DROP_MEMBERSHIP` type.
634- ///
635- /// For more information about this option, see
636- /// [`join_multicast_v4`][link].
637- ///
638- /// [link]: #method.join_multicast_v4
639- pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
640- self.inner.leave_multicast_v4(multiaddr, interface)
641- }
642-
643- /// Executes an operation of the `IPV6_DROP_MEMBERSHIP` type.
644- ///
645- /// For more information about this option, see
646- /// [`join_multicast_v6`][link].
647- ///
648- /// [link]: #method.join_multicast_v6
649- pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
650- self.inner.leave_multicast_v6(multiaddr, interface)
651- }
652-
653- /// Reads the linger duration for this socket by getting the SO_LINGER
654- /// option
655- pub fn linger(&self) -> io::Result<Option<Duration>> {
656- self.inner.linger()
657- }
658-
659- /// Sets the linger duration of this socket by setting the SO_LINGER option
660- pub fn set_linger(&self, dur: Option<Duration>) -> io::Result<()> {
661- self.inner.set_linger(dur)
662- }
663-
664- /// Check the `SO_REUSEADDR` option on this socket.
665- pub fn reuse_address(&self) -> io::Result<bool> {
666- self.inner.reuse_address()
667+ sys::shutdown(self.inner, how)
668 }
669+}
670
671- /// Set value for the `SO_REUSEADDR` option on this socket.
672+impl Socket {
673+ /// Set a socket option.
674 ///
675- /// This indicates that futher calls to `bind` may allow reuse of local
676- /// addresses. For IPv4 sockets this means that a socket may bind even when
677- /// there's a socket already listening on this port.
678- pub fn set_reuse_address(&self, reuse: bool) -> io::Result<()> {
679- self.inner.set_reuse_address(reuse)
680+ /// This function directly corresponds to the `setsockopt(2)` function. As
681+ /// different options use different option types the user must define the
682+ /// correct type `T`!
683+ pub fn setsockopt<T>(&self, level: c_int, optname: c_int, opt: &T) -> io::Result<()> {
684+ sys::setsockopt(self.inner, level, optname, opt)
685 }
686
687- /// Gets the value of the `SO_RCVBUF` option on this socket.
688- ///
689- /// For more information about this option, see
690- /// [`set_recv_buffer_size`][link].
691+ /// Get a socket option.
692 ///
693- /// [link]: #method.set_recv_buffer_size
694- pub fn recv_buffer_size(&self) -> io::Result<usize> {
695- self.inner.recv_buffer_size()
696- }
697-
698- /// Sets the value of the `SO_RCVBUF` option on this socket.
699+ /// This function directly corresponds to the `getsockopt(2)` function. As
700+ /// different options have different return types the user must define the
701+ /// return type `T` correctly!
702 ///
703- /// Changes the size of the operating system's receive buffer associated
704- /// with the socket.
705- pub fn set_recv_buffer_size(&self, size: usize) -> io::Result<()> {
706- self.inner.set_recv_buffer_size(size)
707- }
708-
709- /// Gets the value of the `SO_SNDBUF` option on this socket.
710+ /// For an example usage see [`Socket::take_error`].
711 ///
712- /// For more information about this option, see [`set_send_buffer`][link].
713+ /// # Notes
714 ///
715- /// [link]: #method.set_send_buffer
716- pub fn send_buffer_size(&self) -> io::Result<usize> {
717- self.inner.send_buffer_size()
718+ /// Currently this will panic (in debug mode) if `T` isn't completely
719+ /// written to, it doesn't support options which partly write to `T`.
720+ pub fn getsockopt<T>(&self, level: c_int, optname: c_int) -> io::Result<T> {
721+ sys::getsockopt(self.inner, level, optname)
722 }
723
724- /// Sets the value of the `SO_SNDBUF` option on this socket.
725+ /// Manipulate the file descriptor options of the socket.
726 ///
727- /// Changes the size of the operating system's send buffer associated with
728- /// the socket.
729- pub fn set_send_buffer_size(&self, size: usize) -> io::Result<()> {
730- self.inner.set_send_buffer_size(size)
731- }
732-
733- /// Returns whether keepalive messages are enabled on this socket, and if so
734- /// the duration of time between them.
735+ /// This function directly corresponds to the `fcntl(2)` function. As
736+ /// different command have different options the user must defined the
737+ /// correct type `T`!
738 ///
739- /// For more information about this option, see [`set_keepalive`][link].
740+ /// # Examples
741 ///
742- /// [link]: #method.set_keepalive
743- pub fn keepalive(&self) -> io::Result<Option<Duration>> {
744- self.inner.keepalive()
745- }
746-
747- /// Sets whether keepalive messages are enabled to be sent on this socket.
748+ /// The following example retrieves and sets the file descriptor flags.
749 ///
750- /// On Unix, this option will set the `SO_KEEPALIVE` as well as the
751- /// `TCP_KEEPALIVE` or `TCP_KEEPIDLE` option (depending on your platform).
752- /// On Windows, this will set the `SIO_KEEPALIVE_VALS` option.
753+ /// ```
754+ /// use std::io;
755+ /// use socket2::{Domain, Socket, Type};
756 ///
757- /// If `None` is specified then keepalive messages are disabled, otherwise
758- /// the duration specified will be the time to remain idle before sending a
759- /// TCP keepalive probe.
760+ /// # fn main() -> io::Result<()> {
761+ /// let socket = Socket::new(Domain::ipv4(), Type::stream(), None)?;
762 ///
763- /// Some platforms specify this value in seconds, so sub-second
764- /// specifications may be omitted.
765- pub fn set_keepalive(&self, keepalive: Option<Duration>) -> io::Result<()> {
766- self.inner.set_keepalive(keepalive)
767- }
768-
769- /// Check the value of the `SO_REUSEPORT` option on this socket.
770+ /// // Retrieve the flags, using nothing `()` as argument.
771+ /// let flags = socket.fcntl(libc::F_GETFD, ())?;
772+ /// assert!((flags & libc::FD_CLOEXEC) == 0);
773 ///
774- /// This function is only available on Unix.
775- #[cfg(all(unix, not(target_os = "solaris")))]
776- pub fn reuse_port(&self) -> io::Result<bool> {
777- self.inner.reuse_port()
778- }
779-
780- /// Set value for the `SO_REUSEPORT` option on this socket.
781+ /// // Now we set the `FD_CLOEXEC` flag.
782+ /// socket.fcntl(libc::F_SETFD, flags | libc::FD_CLOEXEC)?;
783 ///
784- /// This indicates that further calls to `bind` may allow reuse of local
785- /// addresses. For IPv4 sockets this means that a socket may bind even when
786- /// there's a socket already listening on this port.
787+ /// // Now the flag should be set.
788+ /// let flags = socket.fcntl(libc::F_GETFD, ())?;
789+ /// assert!((flags & libc::FD_CLOEXEC) != 0);
790 ///
791- /// This function is only available on Unix.
792- #[cfg(all(unix, not(target_os = "solaris")))]
793- pub fn set_reuse_port(&self, reuse: bool) -> io::Result<()> {
794- self.inner.set_reuse_port(reuse)
795+ /// # Ok(())
796+ /// # }
797+ /// ```
798+ pub fn fcntl<T>(&self, cmd: c_int, arg: T) -> io::Result<c_int> {
799+ sys::fcntl(self.inner, cmd, arg)
800 }
801 }
802
803-impl Read for Socket {
804- fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
805- self.inner.read(buf)
806+impl From<TcpStream> for Socket {
807+ fn from(socket: TcpStream) -> Socket {
808+ unsafe { Socket::from_raw_fd(socket.into_raw_fd()) }
809 }
810 }
811
812-impl<'a> Read for &'a Socket {
813- fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
814- (&self.inner).read(buf)
815+impl Into<TcpStream> for Socket {
816+ fn into(self) -> TcpStream {
817+ unsafe { TcpStream::from_raw_fd(self.into_raw_fd()) }
818 }
819 }
820
821-impl Write for Socket {
822- fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
823- self.inner.write(buf)
824- }
825-
826- fn flush(&mut self) -> io::Result<()> {
827- self.inner.flush()
828+impl From<TcpListener> for Socket {
829+ fn from(socket: TcpListener) -> Socket {
830+ unsafe { Socket::from_raw_fd(socket.into_raw_fd()) }
831 }
832 }
833
834-impl<'a> Write for &'a Socket {
835- fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
836- (&self.inner).write(buf)
837- }
838-
839- fn flush(&mut self) -> io::Result<()> {
840- (&self.inner).flush()
841+impl Into<TcpListener> for Socket {
842+ fn into(self) -> TcpListener {
843+ unsafe { TcpListener::from_raw_fd(self.into_raw_fd()) }
844 }
845 }
846
847-impl fmt::Debug for Socket {
848- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
849- self.inner.fmt(f)
850+impl From<UdpSocket> for Socket {
851+ fn from(socket: UdpSocket) -> Socket {
852+ unsafe { Socket::from_raw_fd(socket.into_raw_fd()) }
853 }
854 }
855
856-impl From<net::TcpStream> for Socket {
857- fn from(socket: net::TcpStream) -> Socket {
858- Socket {
859- inner: socket.into(),
860- }
861+impl Into<UdpSocket> for Socket {
862+ fn into(self) -> UdpSocket {
863+ unsafe { UdpSocket::from_raw_fd(self.into_raw_fd()) }
864 }
865 }
866
867-impl From<net::TcpListener> for Socket {
868- fn from(socket: net::TcpListener) -> Socket {
869- Socket {
870- inner: socket.into(),
871- }
872- }
873-}
874-
875-impl From<net::UdpSocket> for Socket {
876- fn from(socket: net::UdpSocket) -> Socket {
877- Socket {
878- inner: socket.into(),
879- }
880- }
881-}
882-
883-#[cfg(all(unix, feature = "unix"))]
884-impl From<UnixStream> for Socket {
885- fn from(socket: UnixStream) -> Socket {
886- Socket {
887- inner: socket.into(),
888- }
889- }
890-}
891-
892-#[cfg(all(unix, feature = "unix"))]
893-impl From<UnixListener> for Socket {
894- fn from(socket: UnixListener) -> Socket {
895- Socket {
896- inner: socket.into(),
897- }
898- }
899-}
900-
901-#[cfg(all(unix, feature = "unix"))]
902-impl From<UnixDatagram> for Socket {
903- fn from(socket: UnixDatagram) -> Socket {
904- Socket {
905- inner: socket.into(),
906- }
907- }
908-}
909-
910-impl From<Socket> for net::TcpStream {
911- fn from(socket: Socket) -> net::TcpStream {
912- socket.inner.into()
913- }
914-}
915-
916-impl From<Socket> for net::TcpListener {
917- fn from(socket: Socket) -> net::TcpListener {
918- socket.inner.into()
919- }
920-}
921-
922-impl From<Socket> for net::UdpSocket {
923- fn from(socket: Socket) -> net::UdpSocket {
924- socket.inner.into()
925- }
926-}
927-
928-#[cfg(all(unix, feature = "unix"))]
929-impl From<Socket> for UnixStream {
930- fn from(socket: Socket) -> UnixStream {
931- socket.inner.into()
932- }
933-}
934-
935-#[cfg(all(unix, feature = "unix"))]
936-impl From<Socket> for UnixListener {
937- fn from(socket: Socket) -> UnixListener {
938- socket.inner.into()
939- }
940-}
941-
942-#[cfg(all(unix, feature = "unix"))]
943-impl From<Socket> for UnixDatagram {
944- fn from(socket: Socket) -> UnixDatagram {
945- socket.inner.into()
946- }
947-}
948-
949-#[cfg(test)]
950-mod test {
951- use std::net::SocketAddr;
952-
953- use super::*;
954-
955- #[test]
956- fn connect_timeout_unrouteable() {
957- // this IP is unroutable, so connections should always time out
958- let addr = "10.255.255.1:80".parse::<SocketAddr>().unwrap().into();
959-
960- let socket = Socket::new(Domain::ipv4(), Type::stream(), None).unwrap();
961- match socket.connect_timeout(&addr, Duration::from_millis(250)) {
962- Ok(_) => panic!("unexpected success"),
963- Err(ref e) if e.kind() == io::ErrorKind::TimedOut => {}
964- Err(e) => panic!("unexpected error {}", e),
965- }
966- }
967-
968- #[test]
969- fn connect_timeout_unbound() {
970- // bind and drop a socket to track down a "probably unassigned" port
971- let socket = Socket::new(Domain::ipv4(), Type::stream(), None).unwrap();
972- let addr = "127.0.0.1:0".parse::<SocketAddr>().unwrap().into();
973- socket.bind(&addr).unwrap();
974- let addr = socket.local_addr().unwrap();
975- drop(socket);
976-
977- let socket = Socket::new(Domain::ipv4(), Type::stream(), None).unwrap();
978- match socket.connect_timeout(&addr, Duration::from_millis(250)) {
979- Ok(_) => panic!("unexpected success"),
980- Err(ref e)
981- if e.kind() == io::ErrorKind::ConnectionRefused
982- || e.kind() == io::ErrorKind::TimedOut => {}
983- Err(e) => panic!("unexpected error {}", e),
984- }
985- }
986-
987- #[test]
988- fn connect_timeout_valid() {
989- let socket = Socket::new(Domain::ipv4(), Type::stream(), None).unwrap();
990- socket
991- .bind(&"127.0.0.1:0".parse::<SocketAddr>().unwrap().into())
992- .unwrap();
993- socket.listen(128).unwrap();
994-
995- let addr = socket.local_addr().unwrap();
996-
997- let socket = Socket::new(Domain::ipv4(), Type::stream(), None).unwrap();
998- socket
999- .connect_timeout(&addr, Duration::from_millis(250))
1000- .unwrap();
1001- }
1002-
1003- #[test]
1004- #[cfg(all(unix, feature = "pair", feature = "unix"))]
1005- fn pair() {
1006- let (mut a, mut b) = Socket::pair(Domain::unix(), Type::stream(), None).unwrap();
1007- a.write_all(b"hello world").unwrap();
1008- let mut buf = [0; 11];
1009- b.read_exact(&mut buf).unwrap();
1010- assert_eq!(buf, &b"hello world"[..]);
1011- }
1012-
1013- #[test]
1014- #[cfg(all(unix, feature = "unix"))]
1015- fn unix() {
1016- use tempdir::TempDir;
1017-
1018- let dir = TempDir::new("unix").unwrap();
1019- let addr = SockAddr::unix(dir.path().join("sock")).unwrap();
1020-
1021- let listener = Socket::new(Domain::unix(), Type::stream(), None).unwrap();
1022- listener.bind(&addr).unwrap();
1023- listener.listen(10).unwrap();
1024-
1025- let mut a = Socket::new(Domain::unix(), Type::stream(), None).unwrap();
1026- a.connect(&addr).unwrap();
1027-
1028- let mut b = listener.accept().unwrap().0;
1029-
1030- a.write_all(b"hello world").unwrap();
1031- let mut buf = [0; 11];
1032- b.read_exact(&mut buf).unwrap();
1033- assert_eq!(buf, &b"hello world"[..]);
1034- }
1035-
1036- #[test]
1037- fn keepalive() {
1038- let socket = Socket::new(Domain::ipv4(), Type::stream(), None).unwrap();
1039- socket.set_keepalive(Some(Duration::from_secs(7))).unwrap();
1040- // socket.keepalive() doesn't work on Windows #24
1041- #[cfg(unix)]
1042- assert_eq!(socket.keepalive().unwrap(), Some(Duration::from_secs(7)));
1043- socket.set_keepalive(None).unwrap();
1044- #[cfg(unix)]
1045- assert_eq!(socket.keepalive().unwrap(), None);
1046- }
1047-
1048- #[test]
1049- fn nodelay() {
1050- let socket = Socket::new(Domain::ipv4(), Type::stream(), None).unwrap();
1051-
1052- assert!(socket.set_nodelay(true).is_ok());
1053-
1054- let result = socket.nodelay();
1055-
1056- assert!(result.is_ok());
1057- assert!(result.unwrap());
1058+impl fmt::Debug for Socket {
1059+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1060+ self.inner.fmt(f)
1061 }
1062 }
1063diff --git a/src/sys/unix.rs b/src/sys/unix.rs
1064index 3612f77..3cc08f6 100644
1065--- a/src/sys/unix.rs
1066+++ b/src/sys/unix.rs
1067@@ -8,23 +8,13 @@
1068 // option. This file may not be copied, modified, or distributed
1069 // except according to those terms.
1070
1071-use std::cmp;
1072-use std::fmt;
1073 use std::io;
1074-use std::io::{ErrorKind, Read, Write};
1075-use std::mem;
1076+use std::mem::{self, size_of, MaybeUninit};
1077 use std::net::Shutdown;
1078-use std::net::{self, Ipv4Addr, Ipv6Addr};
1079-use std::ops::Neg;
1080-#[cfg(feature = "unix")]
1081+use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
1082 use std::os::unix::net::{UnixDatagram, UnixListener, UnixStream};
1083-use std::os::unix::prelude::*;
1084-use std::sync::atomic::{AtomicBool, Ordering};
1085-use std::time::{Duration, Instant};
1086
1087-use libc::{self, c_void, socklen_t, ssize_t};
1088-
1089-use crate::{Domain, Type};
1090+use crate::{Domain, Protocol, SockAddr, Socket, Type};
1091
1092 // Used in conversions for `Domain`, `Type` and `Protocol`.
1093 #[allow(non_camel_case_types)]
1094@@ -36,43 +26,8 @@ pub(crate) use libc::{AF_INET, AF_INET6};
1095 pub(crate) use libc::{SOCK_DGRAM, SOCK_RAW, SOCK_SEQPACKET, SOCK_STREAM};
1096 // Used in `Protocol`.
1097 pub(crate) use libc::{IPPROTO_ICMP, IPPROTO_ICMPV6, IPPROTO_TCP, IPPROTO_UDP};
1098-
1099-cfg_if::cfg_if! {
1100- if #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
1101- target_os = "ios", target_os = "macos",
1102- target_os = "openbsd", target_os = "netbsd",
1103- target_os = "solaris", target_os = "haiku"))] {
1104- use libc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
1105- use libc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
1106- } else {
1107- use libc::IPV6_ADD_MEMBERSHIP;
1108- use libc::IPV6_DROP_MEMBERSHIP;
1109- }
1110-}
1111-
1112-cfg_if::cfg_if! {
1113- if #[cfg(any(target_os = "linux", target_os = "android",
1114- target_os = "dragonfly", target_os = "freebsd",
1115- target_os = "openbsd", target_os = "netbsd",
1116- target_os = "haiku", target_os = "bitrig"))] {
1117- use libc::MSG_NOSIGNAL;
1118- } else {
1119- const MSG_NOSIGNAL: c_int = 0x0;
1120- }
1121-}
1122-
1123-cfg_if::cfg_if! {
1124- if #[cfg(any(target_os = "macos", target_os = "ios"))] {
1125- use libc::TCP_KEEPALIVE as KEEPALIVE_OPTION;
1126- } else if #[cfg(any(target_os = "openbsd", target_os = "netbsd", target_os = "haiku"))] {
1127- use libc::SO_KEEPALIVE as KEEPALIVE_OPTION;
1128- } else {
1129- use libc::TCP_KEEPIDLE as KEEPALIVE_OPTION;
1130- }
1131-}
1132-
1133-use crate::utils::One;
1134-use crate::SockAddr;
1135+// Used in `Socket`.
1136+pub(crate) use std::os::unix::io::RawFd as RawSocket;
1137
1138 /// Unix only API.
1139 impl Domain {
1140@@ -131,1036 +86,241 @@ impl Type {
1141 }
1142 }
1143
1144-pub struct Socket {
1145- fd: c_int,
1146+/// Helper macro to execute a system call that returns an `io::Result`.
1147+macro_rules! syscall {
1148+ ($fn: ident ( $($arg: expr),* $(,)* ) ) => {{
1149+ let res = unsafe { libc::$fn($($arg, )*) };
1150+ if res == -1 {
1151+ Err(std::io::Error::last_os_error())
1152+ } else {
1153+ Ok(res)
1154+ }
1155+ }};
1156+}
1157+
1158+pub(crate) fn socket(domain: c_int, type_: c_int, protocol: c_int) -> io::Result<Socket> {
1159+ syscall!(socket(domain, type_, protocol)).map(|fd| Socket { inner: fd })
1160+}
1161+
1162+pub(crate) fn connect(
1163+ sockfd: RawSocket,
1164+ addr: *const libc::sockaddr_storage,
1165+ addrlen: libc::socklen_t,
1166+) -> io::Result<()> {
1167+ // Most OSes don't actually use `sockaddr_storage` in the `connect(2)` call,
1168+ // but `sockaddr_storage` can be converted safely into the correct type.
1169+ syscall!(connect(sockfd, addr as *const _, addrlen)).map(|_| ())
1170+}
1171+
1172+pub(crate) fn bind(
1173+ sockfd: RawSocket,
1174+ addr: *const libc::sockaddr_storage,
1175+ addrlen: libc::socklen_t,
1176+) -> io::Result<()> {
1177+ // Most OSes don't actually use `sockaddr_storage` in the `bind(2)` call,
1178+ // but `sockaddr_storage` can be converted safely into the correct type.
1179+ syscall!(bind(sockfd, addr as *const _, addrlen)).map(|_| ())
1180+}
1181+
1182+pub(crate) fn listen(sockfd: RawSocket, backlog: c_int) -> io::Result<()> {
1183+ syscall!(listen(sockfd, backlog)).map(|_| ())
1184+}
1185+
1186+pub(crate) fn accept(sockfd: RawSocket) -> io::Result<(Socket, SockAddr)> {
1187+ let mut addr: MaybeUninit<libc::sockaddr_storage> = MaybeUninit::uninit();
1188+ let mut addrlen = size_of::<libc::sockaddr_storage>() as libc::socklen_t;
1189+ syscall!(accept(sockfd, addr.as_mut_ptr() as *mut _, &mut addrlen)).map(|stream_fd| {
1190+ // This is safe because `accept(2)` filled in the address for us.
1191+ let addr = unsafe { SockAddr::from_raw_parts(addr.assume_init(), addrlen) };
1192+ (Socket { inner: stream_fd }, addr)
1193+ })
1194+}
1195+
1196+pub(crate) fn getsockname(sockfd: RawSocket) -> io::Result<SockAddr> {
1197+ let mut addr: MaybeUninit<libc::sockaddr_storage> = MaybeUninit::uninit();
1198+ let mut addrlen = size_of::<libc::sockaddr_storage>() as libc::socklen_t;
1199+ syscall!(getsockname(
1200+ sockfd,
1201+ addr.as_mut_ptr() as *mut _,
1202+ &mut addrlen
1203+ ))
1204+ .map(|_| {
1205+ // This is safe because `getsockname(2)` filled in the address for us.
1206+ unsafe { SockAddr::from_raw_parts(addr.assume_init(), addrlen) }
1207+ })
1208+}
1209+
1210+pub(crate) fn getpeername(sockfd: RawSocket) -> io::Result<SockAddr> {
1211+ let mut addr: MaybeUninit<libc::sockaddr_storage> = MaybeUninit::uninit();
1212+ let mut addrlen = size_of::<libc::sockaddr_storage>() as libc::socklen_t;
1213+ syscall!(getpeername(
1214+ sockfd,
1215+ addr.as_mut_ptr() as *mut _,
1216+ &mut addrlen
1217+ ))
1218+ .map(|_| {
1219+ // This is safe because `getpeername(2)` filled in the address for us.
1220+ unsafe { SockAddr::from_raw_parts(addr.assume_init(), addrlen) }
1221+ })
1222+}
1223+
1224+pub(crate) fn shutdown(sockfd: RawSocket, how: Shutdown) -> io::Result<()> {
1225+ let how = match how {
1226+ Shutdown::Write => libc::SHUT_WR,
1227+ Shutdown::Read => libc::SHUT_RD,
1228+ Shutdown::Both => libc::SHUT_RDWR,
1229+ };
1230+ syscall!(shutdown(sockfd, how)).map(|_| ())
1231+}
1232+
1233+pub(crate) fn setsockopt<T>(
1234+ sockfd: RawSocket,
1235+ level: c_int,
1236+ optname: c_int,
1237+ opt: &T,
1238+) -> io::Result<()> {
1239+ syscall!(setsockopt(
1240+ sockfd,
1241+ level,
1242+ optname,
1243+ opt as *const _ as *const _,
1244+ size_of::<T>() as libc::socklen_t,
1245+ ))
1246+ .map(|_| ())
1247+}
1248+
1249+pub(crate) fn getsockopt<T>(sockfd: RawSocket, level: c_int, optname: c_int) -> io::Result<T> {
1250+ let mut optval: MaybeUninit<T> = MaybeUninit::uninit();
1251+ let mut optlen = size_of::<T>() as libc::socklen_t;
1252+ syscall!(getsockopt(
1253+ sockfd,
1254+ level,
1255+ optname,
1256+ optval.as_mut_ptr() as *mut _,
1257+ &mut optlen
1258+ ))
1259+ .map(|_| unsafe {
1260+ // Safe because `getsockopt(2)` initialised the value for us.
1261+ debug_assert_eq!(optlen as usize, size_of::<T>());
1262+ optval.assume_init()
1263+ })
1264+}
1265+
1266+pub(crate) fn fcntl<T>(sockfd: RawSocket, cmd: c_int, arg: T) -> io::Result<c_int> {
1267+ syscall!(fcntl(sockfd, cmd, arg))
1268 }
1269
1270+/// Unix only API.
1271 impl Socket {
1272- pub fn new(family: c_int, ty: c_int, protocol: c_int) -> io::Result<Socket> {
1273- unsafe {
1274- // On linux we first attempt to pass the SOCK_CLOEXEC flag to
1275- // atomically create the socket and set it as CLOEXEC. Support for
1276- // this option, however, was added in 2.6.27, and we still support
1277- // 2.6.18 as a kernel, so if the returned error is EINVAL we
1278- // fallthrough to the fallback.
1279- #[cfg(target_os = "linux")]
1280- {
1281- match cvt(libc::socket(family, ty | libc::SOCK_CLOEXEC, protocol)) {
1282- Ok(fd) => return Ok(Socket::from_raw_fd(fd)),
1283- Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => {}
1284- Err(e) => return Err(e),
1285- }
1286- }
1287-
1288- let fd = cvt(libc::socket(family, ty, protocol))?;
1289- let fd = Socket::from_raw_fd(fd);
1290- set_cloexec(fd.as_raw_fd())?;
1291- #[cfg(target_os = "macos")]
1292- {
1293- fd.setsockopt(libc::SOL_SOCKET, libc::SO_NOSIGPIPE, 1i32)?;
1294- }
1295- Ok(fd)
1296- }
1297- }
1298-
1299- pub fn pair(family: c_int, ty: c_int, protocol: c_int) -> io::Result<(Socket, Socket)> {
1300- unsafe {
1301- let mut fds = [0, 0];
1302- cvt(libc::socketpair(family, ty, protocol, fds.as_mut_ptr()))?;
1303- let fds = (Socket::from_raw_fd(fds[0]), Socket::from_raw_fd(fds[1]));
1304- set_cloexec(fds.0.as_raw_fd())?;
1305- set_cloexec(fds.1.as_raw_fd())?;
1306- #[cfg(target_os = "macos")]
1307- {
1308- fds.0
1309- .setsockopt(libc::SOL_SOCKET, libc::SO_NOSIGPIPE, 1i32)?;
1310- fds.1
1311- .setsockopt(libc::SOL_SOCKET, libc::SO_NOSIGPIPE, 1i32)?;
1312- }
1313- Ok(fds)
1314- }
1315- }
1316-
1317- pub fn bind(&self, addr: &SockAddr) -> io::Result<()> {
1318- unsafe { cvt(libc::bind(self.fd, addr.as_ptr(), addr.len() as _)).map(|_| ()) }
1319- }
1320-
1321- pub fn listen(&self, backlog: i32) -> io::Result<()> {
1322- unsafe { cvt(libc::listen(self.fd, backlog)).map(|_| ()) }
1323- }
1324-
1325- pub fn connect(&self, addr: &SockAddr) -> io::Result<()> {
1326- unsafe { cvt(libc::connect(self.fd, addr.as_ptr(), addr.len())).map(|_| ()) }
1327- }
1328-
1329- pub fn connect_timeout(&self, addr: &SockAddr, timeout: Duration) -> io::Result<()> {
1330- self.set_nonblocking(true)?;
1331- let r = self.connect(addr);
1332- self.set_nonblocking(false)?;
1333-
1334- match r {
1335- Ok(()) => return Ok(()),
1336- // there's no io::ErrorKind conversion registered for EINPROGRESS :(
1337- Err(ref e) if e.raw_os_error() == Some(libc::EINPROGRESS) => {}
1338- Err(e) => return Err(e),
1339- }
1340-
1341- let mut pollfd = libc::pollfd {
1342- fd: self.fd,
1343- events: libc::POLLOUT,
1344- revents: 0,
1345- };
1346-
1347- if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 {
1348- return Err(io::Error::new(
1349- io::ErrorKind::InvalidInput,
1350- "cannot set a 0 duration timeout",
1351- ));
1352- }
1353-
1354- let start = Instant::now();
1355-
1356- loop {
1357- let elapsed = start.elapsed();
1358- if elapsed >= timeout {
1359- return Err(io::Error::new(
1360- io::ErrorKind::TimedOut,
1361- "connection timed out",
1362- ));
1363- }
1364-
1365- let timeout = timeout - elapsed;
1366- let mut timeout = timeout
1367- .as_secs()
1368- .saturating_mul(1_000)
1369- .saturating_add(timeout.subsec_nanos() as u64 / 1_000_000);
1370- if timeout == 0 {
1371- timeout = 1;
1372- }
1373-
1374- let timeout = cmp::min(timeout, c_int::max_value() as u64) as c_int;
1375-
1376- match unsafe { libc::poll(&mut pollfd, 1, timeout) } {
1377- -1 => {
1378- let err = io::Error::last_os_error();
1379- if err.kind() != io::ErrorKind::Interrupted {
1380- return Err(err);
1381- }
1382- }
1383- 0 => {
1384- return Err(io::Error::new(
1385- io::ErrorKind::TimedOut,
1386- "connection timed out",
1387- ))
1388- }
1389- _ => {
1390- // linux returns POLLOUT|POLLERR|POLLHUP for refused connections (!), so look
1391- // for POLLHUP rather than read readiness
1392- if pollfd.revents & libc::POLLHUP != 0 {
1393- let e = self.take_error()?.unwrap_or_else(|| {
1394- io::Error::new(io::ErrorKind::Other, "no error set after POLLHUP")
1395- });
1396- return Err(e);
1397- }
1398- return Ok(());
1399- }
1400- }
1401- }
1402- }
1403-
1404- pub fn local_addr(&self) -> io::Result<SockAddr> {
1405- unsafe {
1406- let mut storage: libc::sockaddr_storage = mem::zeroed();
1407- let mut len = mem::size_of_val(&storage) as libc::socklen_t;
1408- cvt(libc::getsockname(
1409- self.fd,
1410- &mut storage as *mut _ as *mut _,
1411- &mut len,
1412- ))?;
1413- Ok(SockAddr::from_raw_parts(
1414- &storage as *const _ as *const _,
1415- len,
1416- ))
1417- }
1418- }
1419-
1420- pub fn peer_addr(&self) -> io::Result<SockAddr> {
1421- unsafe {
1422- let mut storage: libc::sockaddr_storage = mem::zeroed();
1423- let mut len = mem::size_of_val(&storage) as libc::socklen_t;
1424- cvt(libc::getpeername(
1425- self.fd,
1426- &mut storage as *mut _ as *mut _,
1427- &mut len,
1428- ))?;
1429- Ok(SockAddr::from_raw_parts(
1430- &storage as *const _ as *const _,
1431- len,
1432- ))
1433- }
1434- }
1435-
1436- pub fn try_clone(&self) -> io::Result<Socket> {
1437- // implementation lifted from libstd
1438- #[cfg(any(target_os = "android", target_os = "haiku"))]
1439- use libc::F_DUPFD as F_DUPFD_CLOEXEC;
1440- #[cfg(not(any(target_os = "android", target_os = "haiku")))]
1441- use libc::F_DUPFD_CLOEXEC;
1442-
1443- static CLOEXEC_FAILED: AtomicBool = AtomicBool::new(false);
1444- unsafe {
1445- if !CLOEXEC_FAILED.load(Ordering::Relaxed) {
1446- match cvt(libc::fcntl(self.fd, F_DUPFD_CLOEXEC, 0)) {
1447- Ok(fd) => {
1448- let fd = Socket::from_raw_fd(fd);
1449- if cfg!(target_os = "linux") {
1450- set_cloexec(fd.as_raw_fd())?;
1451- }
1452- return Ok(fd);
1453- }
1454- Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => {
1455- CLOEXEC_FAILED.store(true, Ordering::Relaxed);
1456- }
1457- Err(e) => return Err(e),
1458- }
1459- }
1460- let fd = cvt(libc::fcntl(self.fd, libc::F_DUPFD, 0))?;
1461- let fd = Socket::from_raw_fd(fd);
1462- set_cloexec(fd.as_raw_fd())?;
1463- Ok(fd)
1464- }
1465- }
1466-
1467- #[allow(unused_mut)]
1468- pub fn accept(&self) -> io::Result<(Socket, SockAddr)> {
1469- let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
1470- let mut len = mem::size_of_val(&storage) as socklen_t;
1471-
1472- let mut socket = None;
1473- #[cfg(target_os = "linux")]
1474- {
1475- let res = cvt_r(|| unsafe {
1476- libc::syscall(
1477- libc::SYS_accept4,
1478- self.fd as libc::c_long,
1479- &mut storage as *mut _ as libc::c_long,
1480- &mut len,
1481- libc::SOCK_CLOEXEC as libc::c_long,
1482- ) as libc::c_int
1483- });
1484- match res {
1485- Ok(fd) => socket = Some(Socket { fd: fd }),
1486- Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {}
1487- Err(e) => return Err(e),
1488- }
1489- }
1490-
1491- let socket = match socket {
1492- Some(socket) => socket,
1493- None => unsafe {
1494- let fd =
1495- cvt_r(|| libc::accept(self.fd, &mut storage as *mut _ as *mut _, &mut len))?;
1496- let fd = Socket::from_raw_fd(fd);
1497- set_cloexec(fd.as_raw_fd())?;
1498- fd
1499- },
1500- };
1501- let addr = unsafe { SockAddr::from_raw_parts(&storage as *const _ as *const _, len) };
1502- Ok((socket, addr))
1503- }
1504-
1505- pub fn take_error(&self) -> io::Result<Option<io::Error>> {
1506- unsafe {
1507- let raw: c_int = self.getsockopt(libc::SOL_SOCKET, libc::SO_ERROR)?;
1508- if raw == 0 {
1509- Ok(None)
1510- } else {
1511- Ok(Some(io::Error::from_raw_os_error(raw as i32)))
1512- }
1513- }
1514- }
1515-
1516- pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
1517- unsafe {
1518- let previous = cvt(libc::fcntl(self.fd, libc::F_GETFL))?;
1519- let new = if nonblocking {
1520- previous | libc::O_NONBLOCK
1521- } else {
1522- previous & !libc::O_NONBLOCK
1523- };
1524- if new != previous {
1525- cvt(libc::fcntl(self.fd, libc::F_SETFL, new))?;
1526- }
1527- Ok(())
1528- }
1529- }
1530-
1531- pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
1532- let how = match how {
1533- Shutdown::Write => libc::SHUT_WR,
1534- Shutdown::Read => libc::SHUT_RD,
1535- Shutdown::Both => libc::SHUT_RDWR,
1536- };
1537- cvt(unsafe { libc::shutdown(self.fd, how) })?;
1538- Ok(())
1539- }
1540-
1541- pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
1542- unsafe {
1543- let n = cvt({
1544- libc::recv(
1545- self.fd,
1546- buf.as_mut_ptr() as *mut c_void,
1547- cmp::min(buf.len(), max_len()),
1548- 0,
1549- )
1550- })?;
1551- Ok(n as usize)
1552- }
1553- }
1554-
1555- pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
1556- unsafe {
1557- let n = cvt({
1558- libc::recv(
1559- self.fd,
1560- buf.as_mut_ptr() as *mut c_void,
1561- cmp::min(buf.len(), max_len()),
1562- libc::MSG_PEEK,
1563- )
1564- })?;
1565- Ok(n as usize)
1566- }
1567- }
1568-
1569- pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SockAddr)> {
1570- self.recvfrom(buf, 0)
1571- }
1572-
1573- pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SockAddr)> {
1574- self.recvfrom(buf, libc::MSG_PEEK)
1575- }
1576-
1577- fn recvfrom(&self, buf: &mut [u8], flags: c_int) -> io::Result<(usize, SockAddr)> {
1578- unsafe {
1579- let mut storage: libc::sockaddr_storage = mem::zeroed();
1580- let mut addrlen = mem::size_of_val(&storage) as socklen_t;
1581-
1582- let n = cvt({
1583- libc::recvfrom(
1584- self.fd,
1585- buf.as_mut_ptr() as *mut c_void,
1586- cmp::min(buf.len(), max_len()),
1587- flags,
1588- &mut storage as *mut _ as *mut _,
1589- &mut addrlen,
1590- )
1591- })?;
1592- let addr = SockAddr::from_raw_parts(&storage as *const _ as *const _, addrlen);
1593- Ok((n as usize, addr))
1594- }
1595- }
1596-
1597- pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
1598- unsafe {
1599- let n = cvt({
1600- libc::send(
1601- self.fd,
1602- buf.as_ptr() as *const c_void,
1603- cmp::min(buf.len(), max_len()),
1604- MSG_NOSIGNAL,
1605- )
1606- })?;
1607- Ok(n as usize)
1608- }
1609- }
1610-
1611- pub fn send_to(&self, buf: &[u8], addr: &SockAddr) -> io::Result<usize> {
1612- unsafe {
1613- let n = cvt({
1614- libc::sendto(
1615- self.fd,
1616- buf.as_ptr() as *const c_void,
1617- cmp::min(buf.len(), max_len()),
1618- MSG_NOSIGNAL,
1619- addr.as_ptr(),
1620- addr.len(),
1621- )
1622- })?;
1623- Ok(n as usize)
1624- }
1625- }
1626-
1627- // ================================================
1628-
1629- pub fn ttl(&self) -> io::Result<u32> {
1630- unsafe {
1631- let raw: c_int = self.getsockopt(libc::IPPROTO_IP, libc::IP_TTL)?;
1632- Ok(raw as u32)
1633- }
1634- }
1635-
1636- pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
1637- unsafe { self.setsockopt(libc::IPPROTO_IP, libc::IP_TTL, ttl as c_int) }
1638- }
1639-
1640- pub fn unicast_hops_v6(&self) -> io::Result<u32> {
1641- unsafe {
1642- let raw: c_int = self.getsockopt(libc::IPPROTO_IPV6, libc::IPV6_UNICAST_HOPS)?;
1643- Ok(raw as u32)
1644- }
1645- }
1646-
1647- pub fn set_unicast_hops_v6(&self, hops: u32) -> io::Result<()> {
1648- unsafe {
1649- self.setsockopt(
1650- libc::IPPROTO_IPV6 as c_int,
1651- libc::IPV6_UNICAST_HOPS,
1652- hops as c_int,
1653- )
1654- }
1655- }
1656-
1657- pub fn only_v6(&self) -> io::Result<bool> {
1658- unsafe {
1659- let raw: c_int = self.getsockopt(libc::IPPROTO_IPV6, libc::IPV6_V6ONLY)?;
1660- Ok(raw != 0)
1661- }
1662- }
1663-
1664- pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
1665- unsafe { self.setsockopt(libc::IPPROTO_IPV6, libc::IPV6_V6ONLY, only_v6 as c_int) }
1666- }
1667-
1668- pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
1669- unsafe {
1670- Ok(timeval2dur(
1671- self.getsockopt(libc::SOL_SOCKET, libc::SO_RCVTIMEO)?,
1672- ))
1673- }
1674- }
1675-
1676- pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
1677- unsafe { self.setsockopt(libc::SOL_SOCKET, libc::SO_RCVTIMEO, dur2timeval(dur)?) }
1678- }
1679-
1680- pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
1681- unsafe {
1682- Ok(timeval2dur(
1683- self.getsockopt(libc::SOL_SOCKET, libc::SO_SNDTIMEO)?,
1684- ))
1685- }
1686- }
1687-
1688- pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
1689- unsafe { self.setsockopt(libc::SOL_SOCKET, libc::SO_SNDTIMEO, dur2timeval(dur)?) }
1690- }
1691-
1692- pub fn nodelay(&self) -> io::Result<bool> {
1693- unsafe {
1694- let raw: c_int = self.getsockopt(libc::IPPROTO_TCP, libc::TCP_NODELAY)?;
1695- Ok(raw != 0)
1696- }
1697- }
1698-
1699- pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
1700- unsafe { self.setsockopt(libc::IPPROTO_TCP, libc::TCP_NODELAY, nodelay as c_int) }
1701- }
1702-
1703- pub fn broadcast(&self) -> io::Result<bool> {
1704- unsafe {
1705- let raw: c_int = self.getsockopt(libc::SOL_SOCKET, libc::SO_BROADCAST)?;
1706- Ok(raw != 0)
1707- }
1708- }
1709-
1710- pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
1711- unsafe { self.setsockopt(libc::SOL_SOCKET, libc::SO_BROADCAST, broadcast as c_int) }
1712- }
1713-
1714- pub fn multicast_loop_v4(&self) -> io::Result<bool> {
1715- unsafe {
1716- let raw: c_int = self.getsockopt(libc::IPPROTO_IP, libc::IP_MULTICAST_LOOP)?;
1717- Ok(raw != 0)
1718- }
1719- }
1720-
1721- pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
1722- unsafe {
1723- self.setsockopt(
1724- libc::IPPROTO_IP,
1725- libc::IP_MULTICAST_LOOP,
1726- multicast_loop_v4 as c_int,
1727- )
1728- }
1729- }
1730-
1731- pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
1732- unsafe {
1733- let raw: c_int = self.getsockopt(libc::IPPROTO_IP, libc::IP_MULTICAST_TTL)?;
1734- Ok(raw as u32)
1735- }
1736- }
1737-
1738- pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
1739- unsafe {
1740- self.setsockopt(
1741- libc::IPPROTO_IP,
1742- libc::IP_MULTICAST_TTL,
1743- multicast_ttl_v4 as c_int,
1744- )
1745- }
1746- }
1747-
1748- pub fn multicast_hops_v6(&self) -> io::Result<u32> {
1749- unsafe {
1750- let raw: c_int = self.getsockopt(libc::IPPROTO_IPV6, libc::IPV6_MULTICAST_HOPS)?;
1751- Ok(raw as u32)
1752- }
1753- }
1754-
1755- pub fn set_multicast_hops_v6(&self, hops: u32) -> io::Result<()> {
1756- unsafe { self.setsockopt(libc::IPPROTO_IPV6, libc::IPV6_MULTICAST_HOPS, hops as c_int) }
1757- }
1758-
1759- pub fn multicast_if_v4(&self) -> io::Result<Ipv4Addr> {
1760- unsafe {
1761- let imr_interface: libc::in_addr =
1762- self.getsockopt(libc::IPPROTO_IP, libc::IP_MULTICAST_IF)?;
1763- Ok(from_s_addr(imr_interface.s_addr))
1764- }
1765- }
1766-
1767- pub fn set_multicast_if_v4(&self, interface: &Ipv4Addr) -> io::Result<()> {
1768- let interface = to_s_addr(interface);
1769- let imr_interface = libc::in_addr { s_addr: interface };
1770-
1771- unsafe { self.setsockopt(libc::IPPROTO_IP, libc::IP_MULTICAST_IF, imr_interface) }
1772- }
1773-
1774- pub fn multicast_if_v6(&self) -> io::Result<u32> {
1775- unsafe {
1776- let raw: c_int = self.getsockopt(libc::IPPROTO_IPV6, libc::IPV6_MULTICAST_IF)?;
1777- Ok(raw as u32)
1778- }
1779- }
1780-
1781- pub fn set_multicast_if_v6(&self, interface: u32) -> io::Result<()> {
1782- unsafe {
1783- self.setsockopt(
1784- libc::IPPROTO_IPV6,
1785- libc::IPV6_MULTICAST_IF,
1786- interface as c_int,
1787- )
1788- }
1789- }
1790-
1791- pub fn multicast_loop_v6(&self) -> io::Result<bool> {
1792- unsafe {
1793- let raw: c_int = self.getsockopt(libc::IPPROTO_IPV6, libc::IPV6_MULTICAST_LOOP)?;
1794- Ok(raw != 0)
1795- }
1796- }
1797-
1798- pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
1799- unsafe {
1800- self.setsockopt(
1801- libc::IPPROTO_IPV6,
1802- libc::IPV6_MULTICAST_LOOP,
1803- multicast_loop_v6 as c_int,
1804- )
1805- }
1806- }
1807-
1808- pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
1809- let multiaddr = to_s_addr(multiaddr);
1810- let interface = to_s_addr(interface);
1811- let mreq = libc::ip_mreq {
1812- imr_multiaddr: libc::in_addr { s_addr: multiaddr },
1813- imr_interface: libc::in_addr { s_addr: interface },
1814- };
1815- unsafe { self.setsockopt(libc::IPPROTO_IP, libc::IP_ADD_MEMBERSHIP, mreq) }
1816- }
1817-
1818- pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
1819- let multiaddr = to_in6_addr(multiaddr);
1820- let mreq = libc::ipv6_mreq {
1821- ipv6mr_multiaddr: multiaddr,
1822- ipv6mr_interface: to_ipv6mr_interface(interface),
1823- };
1824- unsafe { self.setsockopt(libc::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq) }
1825- }
1826-
1827- pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
1828- let multiaddr = to_s_addr(multiaddr);
1829- let interface = to_s_addr(interface);
1830- let mreq = libc::ip_mreq {
1831- imr_multiaddr: libc::in_addr { s_addr: multiaddr },
1832- imr_interface: libc::in_addr { s_addr: interface },
1833- };
1834- unsafe { self.setsockopt(libc::IPPROTO_IP, libc::IP_DROP_MEMBERSHIP, mreq) }
1835- }
1836-
1837- pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
1838- let multiaddr = to_in6_addr(multiaddr);
1839- let mreq = libc::ipv6_mreq {
1840- ipv6mr_multiaddr: multiaddr,
1841- ipv6mr_interface: to_ipv6mr_interface(interface),
1842- };
1843- unsafe { self.setsockopt(libc::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq) }
1844- }
1845-
1846- pub fn linger(&self) -> io::Result<Option<Duration>> {
1847- unsafe {
1848- Ok(linger2dur(
1849- self.getsockopt(libc::SOL_SOCKET, libc::SO_LINGER)?,
1850- ))
1851- }
1852- }
1853-
1854- pub fn set_linger(&self, dur: Option<Duration>) -> io::Result<()> {
1855- unsafe { self.setsockopt(libc::SOL_SOCKET, libc::SO_LINGER, dur2linger(dur)) }
1856- }
1857-
1858- pub fn set_reuse_address(&self, reuse: bool) -> io::Result<()> {
1859- unsafe { self.setsockopt(libc::SOL_SOCKET, libc::SO_REUSEADDR, reuse as c_int) }
1860- }
1861-
1862- pub fn reuse_address(&self) -> io::Result<bool> {
1863- unsafe {
1864- let raw: c_int = self.getsockopt(libc::SOL_SOCKET, libc::SO_REUSEADDR)?;
1865- Ok(raw != 0)
1866- }
1867- }
1868-
1869- pub fn recv_buffer_size(&self) -> io::Result<usize> {
1870- unsafe {
1871- let raw: c_int = self.getsockopt(libc::SOL_SOCKET, libc::SO_RCVBUF)?;
1872- Ok(raw as usize)
1873- }
1874- }
1875-
1876- pub fn set_recv_buffer_size(&self, size: usize) -> io::Result<()> {
1877- unsafe {
1878- // TODO: casting usize to a c_int should be a checked cast
1879- self.setsockopt(libc::SOL_SOCKET, libc::SO_RCVBUF, size as c_int)
1880- }
1881- }
1882-
1883- pub fn send_buffer_size(&self) -> io::Result<usize> {
1884- unsafe {
1885- let raw: c_int = self.getsockopt(libc::SOL_SOCKET, libc::SO_SNDBUF)?;
1886- Ok(raw as usize)
1887- }
1888- }
1889-
1890- pub fn set_send_buffer_size(&self, size: usize) -> io::Result<()> {
1891- unsafe {
1892- // TODO: casting usize to a c_int should be a checked cast
1893- self.setsockopt(libc::SOL_SOCKET, libc::SO_SNDBUF, size as c_int)
1894- }
1895- }
1896-
1897- pub fn keepalive(&self) -> io::Result<Option<Duration>> {
1898- unsafe {
1899- let raw: c_int = self.getsockopt(libc::SOL_SOCKET, libc::SO_KEEPALIVE)?;
1900- if raw == 0 {
1901- return Ok(None);
1902- }
1903- let secs: c_int = self.getsockopt(libc::IPPROTO_TCP, KEEPALIVE_OPTION)?;
1904- Ok(Some(Duration::new(secs as u64, 0)))
1905- }
1906- }
1907-
1908- pub fn set_keepalive(&self, keepalive: Option<Duration>) -> io::Result<()> {
1909- unsafe {
1910- self.setsockopt(
1911- libc::SOL_SOCKET,
1912- libc::SO_KEEPALIVE,
1913- keepalive.is_some() as c_int,
1914- )?;
1915- if let Some(dur) = keepalive {
1916- // TODO: checked cast here
1917- self.setsockopt(libc::IPPROTO_TCP, KEEPALIVE_OPTION, dur.as_secs() as c_int)?;
1918- }
1919- Ok(())
1920- }
1921- }
1922-
1923- #[cfg(all(unix, not(target_os = "solaris")))]
1924- pub fn reuse_port(&self) -> io::Result<bool> {
1925- unsafe {
1926- let raw: c_int = self.getsockopt(libc::SOL_SOCKET, libc::SO_REUSEPORT)?;
1927- Ok(raw != 0)
1928- }
1929- }
1930-
1931- #[cfg(all(unix, not(target_os = "solaris")))]
1932- pub fn set_reuse_port(&self, reuse: bool) -> io::Result<()> {
1933- unsafe { self.setsockopt(libc::SOL_SOCKET, libc::SO_REUSEPORT, reuse as c_int) }
1934- }
1935-
1936- unsafe fn setsockopt<T>(&self, opt: c_int, val: c_int, payload: T) -> io::Result<()>
1937- where
1938- T: Copy,
1939- {
1940- let payload = &payload as *const T as *const c_void;
1941- cvt(libc::setsockopt(
1942- self.fd,
1943- opt,
1944- val,
1945- payload,
1946- mem::size_of::<T>() as libc::socklen_t,
1947- ))?;
1948- Ok(())
1949- }
1950-
1951- unsafe fn getsockopt<T: Copy>(&self, opt: c_int, val: c_int) -> io::Result<T> {
1952- let mut slot: T = mem::zeroed();
1953- let mut len = mem::size_of::<T>() as libc::socklen_t;
1954- cvt(libc::getsockopt(
1955- self.fd,
1956- opt,
1957- val,
1958- &mut slot as *mut _ as *mut _,
1959- &mut len,
1960- ))?;
1961- assert_eq!(len as usize, mem::size_of::<T>());
1962- Ok(slot)
1963- }
1964-}
1965-
1966-impl Read for Socket {
1967- fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
1968- <&Socket>::read(&mut &*self, buf)
1969- }
1970-}
1971-
1972-impl<'a> Read for &'a Socket {
1973- fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
1974- unsafe {
1975- let n = cvt({
1976- libc::read(
1977- self.fd,
1978- buf.as_mut_ptr() as *mut c_void,
1979- cmp::min(buf.len(), max_len()),
1980- )
1981- })?;
1982- Ok(n as usize)
1983- }
1984- }
1985-}
1986-
1987-impl Write for Socket {
1988- fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
1989- <&Socket>::write(&mut &*self, buf)
1990- }
1991-
1992- fn flush(&mut self) -> io::Result<()> {
1993- <&Socket>::flush(&mut &*self)
1994- }
1995-}
1996-
1997-impl<'a> Write for &'a Socket {
1998- fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
1999- self.send(buf)
2000- }
2001-
2002- fn flush(&mut self) -> io::Result<()> {
2003- Ok(())
2004- }
2005-}
2006-
2007-impl fmt::Debug for Socket {
2008- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2009- let mut f = f.debug_struct("Socket");
2010- f.field("fd", &self.fd);
2011- if let Ok(addr) = self.local_addr() {
2012- f.field("local_addr", &addr);
2013- }
2014- if let Ok(addr) = self.peer_addr() {
2015- f.field("peer_addr", &addr);
2016- }
2017- f.finish()
2018- }
2019-}
2020-
2021-impl AsRawFd for Socket {
2022- fn as_raw_fd(&self) -> c_int {
2023- self.fd
2024- }
2025-}
2026-
2027-impl IntoRawFd for Socket {
2028- fn into_raw_fd(self) -> c_int {
2029- let fd = self.fd;
2030- mem::forget(self);
2031- return fd;
2032- }
2033-}
2034-
2035-impl FromRawFd for Socket {
2036- unsafe fn from_raw_fd(fd: c_int) -> Socket {
2037- Socket { fd: fd }
2038- }
2039-}
2040-
2041-impl AsRawFd for crate::Socket {
2042- fn as_raw_fd(&self) -> c_int {
2043- self.inner.as_raw_fd()
2044- }
2045-}
2046-
2047-impl IntoRawFd for crate::Socket {
2048- fn into_raw_fd(self) -> c_int {
2049- self.inner.into_raw_fd()
2050- }
2051-}
2052-
2053-impl FromRawFd for crate::Socket {
2054- unsafe fn from_raw_fd(fd: c_int) -> crate::Socket {
2055- crate::Socket {
2056- inner: Socket::from_raw_fd(fd),
2057- }
2058- }
2059-}
2060-
2061-impl Drop for Socket {
2062- fn drop(&mut self) {
2063- unsafe {
2064- let _ = libc::close(self.fd);
2065- }
2066- }
2067-}
2068-
2069-impl From<Socket> for net::TcpStream {
2070- fn from(socket: Socket) -> net::TcpStream {
2071- unsafe { net::TcpStream::from_raw_fd(socket.into_raw_fd()) }
2072- }
2073-}
2074-
2075-impl From<Socket> for net::TcpListener {
2076- fn from(socket: Socket) -> net::TcpListener {
2077- unsafe { net::TcpListener::from_raw_fd(socket.into_raw_fd()) }
2078- }
2079-}
2080-
2081-impl From<Socket> for net::UdpSocket {
2082- fn from(socket: Socket) -> net::UdpSocket {
2083- unsafe { net::UdpSocket::from_raw_fd(socket.into_raw_fd()) }
2084- }
2085-}
2086-
2087-#[cfg(all(unix, feature = "unix"))]
2088-impl From<Socket> for UnixStream {
2089- fn from(socket: Socket) -> UnixStream {
2090- unsafe { UnixStream::from_raw_fd(socket.into_raw_fd()) }
2091- }
2092-}
2093-
2094-#[cfg(all(unix, feature = "unix"))]
2095-impl From<Socket> for UnixListener {
2096- fn from(socket: Socket) -> UnixListener {
2097- unsafe { UnixListener::from_raw_fd(socket.into_raw_fd()) }
2098- }
2099-}
2100-
2101-#[cfg(all(unix, feature = "unix"))]
2102-impl From<Socket> for UnixDatagram {
2103- fn from(socket: Socket) -> UnixDatagram {
2104- unsafe { UnixDatagram::from_raw_fd(socket.into_raw_fd()) }
2105- }
2106-}
2107-
2108-impl From<net::TcpStream> for Socket {
2109- fn from(socket: net::TcpStream) -> Socket {
2110- unsafe { Socket::from_raw_fd(socket.into_raw_fd()) }
2111+ /// Creates a pair of sockets which are connected to each other.
2112+ ///
2113+ /// This function corresponds to `socketpair(2)`.
2114+ pub fn pair(
2115+ domain: Domain,
2116+ type_: Type,
2117+ protocol: Option<Protocol>,
2118+ ) -> io::Result<(Socket, Socket)> {
2119+ let mut fds = [0, 0];
2120+ let protocol = protocol.map(|p| p.0).unwrap_or(0);
2121+ syscall!(socketpair(domain.0, type_.0, protocol, fds.as_mut_ptr()))
2122+ .map(|_| (Socket { inner: fds[0] }, Socket { inner: fds[1] }))
2123+ }
2124+
2125+ /// Accept a new incoming connection from this listener.
2126+ ///
2127+ /// This function directly corresponds to the `accept4(2)` function.
2128+ ///
2129+ /// # Notes
2130+ ///
2131+ /// This only available on Android, DragonFlyBSD, FreeBSD, Linux and
2132+ /// OpenBSD. Once https://github.com/rust-lang/libc/issues/1636 is fixed
2133+ /// NetBSD will also support it.
2134+ #[cfg(any(
2135+ target_os = "android",
2136+ target_os = "dragonfly",
2137+ target_os = "freebsd",
2138+ target_os = "linux",
2139+ // NetBSD 8.0 actually has `accept4(2)`, but libc doesn't expose it
2140+ // (yet). See https://github.com/rust-lang/libc/issues/1636.
2141+ //target_os = "netbsd",
2142+ target_os = "openbsd"
2143+ ))]
2144+ pub fn accept4(&self, flags: c_int) -> io::Result<(Socket, SockAddr)> {
2145+ let mut addr: MaybeUninit<libc::sockaddr_storage> = MaybeUninit::uninit();
2146+ let mut addrlen = size_of::<libc::sockaddr_storage>() as libc::socklen_t;
2147+ syscall!(accept4(
2148+ self.inner,
2149+ addr.as_mut_ptr() as *mut _,
2150+ &mut addrlen,
2151+ flags
2152+ ))
2153+ .map(|stream_fd| {
2154+ // This is safe because `accept(2)` filled in the address for us.
2155+ let addr = unsafe { SockAddr::from_raw_parts(addr.assume_init(), addrlen) };
2156+ (Socket { inner: stream_fd }, addr)
2157+ })
2158 }
2159 }
2160
2161-impl From<net::TcpListener> for Socket {
2162- fn from(socket: net::TcpListener) -> Socket {
2163+impl From<UnixStream> for Socket {
2164+ fn from(socket: UnixStream) -> Socket {
2165 unsafe { Socket::from_raw_fd(socket.into_raw_fd()) }
2166 }
2167 }
2168
2169-impl From<net::UdpSocket> for Socket {
2170- fn from(socket: net::UdpSocket) -> Socket {
2171- unsafe { Socket::from_raw_fd(socket.into_raw_fd()) }
2172+impl Into<UnixStream> for Socket {
2173+ fn into(self) -> UnixStream {
2174+ unsafe { UnixStream::from_raw_fd(self.into_raw_fd()) }
2175 }
2176 }
2177
2178-#[cfg(all(unix, feature = "unix"))]
2179-impl From<UnixStream> for Socket {
2180- fn from(socket: UnixStream) -> Socket {
2181+impl From<UnixListener> for Socket {
2182+ fn from(socket: UnixListener) -> Socket {
2183 unsafe { Socket::from_raw_fd(socket.into_raw_fd()) }
2184 }
2185 }
2186
2187-#[cfg(all(unix, feature = "unix"))]
2188-impl From<UnixListener> for Socket {
2189- fn from(socket: UnixListener) -> Socket {
2190- unsafe { Socket::from_raw_fd(socket.into_raw_fd()) }
2191+impl Into<UnixListener> for Socket {
2192+ fn into(self) -> UnixListener {
2193+ unsafe { UnixListener::from_raw_fd(self.into_raw_fd()) }
2194 }
2195 }
2196
2197-#[cfg(all(unix, feature = "unix"))]
2198 impl From<UnixDatagram> for Socket {
2199 fn from(socket: UnixDatagram) -> Socket {
2200 unsafe { Socket::from_raw_fd(socket.into_raw_fd()) }
2201 }
2202 }
2203
2204-fn max_len() -> usize {
2205- // The maximum read limit on most posix-like systems is `SSIZE_MAX`,
2206- // with the man page quoting that if the count of bytes to read is
2207- // greater than `SSIZE_MAX` the result is "unspecified".
2208- //
2209- // On macOS, however, apparently the 64-bit libc is either buggy or
2210- // intentionally showing odd behavior by rejecting any read with a size
2211- // larger than or equal to INT_MAX. To handle both of these the read
2212- // size is capped on both platforms.
2213- if cfg!(target_os = "macos") {
2214- <c_int>::max_value() as usize - 1
2215- } else {
2216- <ssize_t>::max_value() as usize
2217- }
2218-}
2219-
2220-fn cvt<T: One + PartialEq + Neg<Output = T>>(t: T) -> io::Result<T> {
2221- let one: T = T::one();
2222- if t == -one {
2223- Err(io::Error::last_os_error())
2224- } else {
2225- Ok(t)
2226+impl Into<UnixDatagram> for Socket {
2227+ fn into(self) -> UnixDatagram {
2228+ unsafe { UnixDatagram::from_raw_fd(self.into_raw_fd()) }
2229 }
2230 }
2231
2232-fn cvt_r<F, T>(mut f: F) -> io::Result<T>
2233-where
2234- F: FnMut() -> T,
2235- T: One + PartialEq + Neg<Output = T>,
2236-{
2237- loop {
2238- match cvt(f()) {
2239- Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
2240- other => return other,
2241- }
2242- }
2243-}
2244-
2245-fn set_cloexec(fd: c_int) -> io::Result<()> {
2246- unsafe {
2247- let previous = cvt(libc::fcntl(fd, libc::F_GETFD))?;
2248- let new = previous | libc::FD_CLOEXEC;
2249- if new != previous {
2250- cvt(libc::fcntl(fd, libc::F_SETFD, new))?;
2251- }
2252- Ok(())
2253- }
2254-}
2255-
2256-fn dur2timeval(dur: Option<Duration>) -> io::Result<libc::timeval> {
2257- match dur {
2258- Some(dur) => {
2259- if dur.as_secs() == 0 && dur.subsec_nanos() == 0 {
2260- return Err(io::Error::new(
2261- io::ErrorKind::InvalidInput,
2262- "cannot set a 0 duration timeout",
2263- ));
2264- }
2265-
2266- let secs = if dur.as_secs() > libc::time_t::max_value() as u64 {
2267- libc::time_t::max_value()
2268- } else {
2269- dur.as_secs() as libc::time_t
2270- };
2271- let mut timeout = libc::timeval {
2272- tv_sec: secs,
2273- tv_usec: (dur.subsec_nanos() / 1000) as libc::suseconds_t,
2274- };
2275- if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
2276- timeout.tv_usec = 1;
2277- }
2278- Ok(timeout)
2279- }
2280- None => Ok(libc::timeval {
2281- tv_sec: 0,
2282- tv_usec: 0,
2283- }),
2284+impl FromRawFd for Socket {
2285+ unsafe fn from_raw_fd(fd: RawFd) -> Socket {
2286+ Socket { inner: fd }
2287 }
2288 }
2289
2290-fn timeval2dur(raw: libc::timeval) -> Option<Duration> {
2291- if raw.tv_sec == 0 && raw.tv_usec == 0 {
2292- None
2293- } else {
2294- let sec = raw.tv_sec as u64;
2295- let nsec = (raw.tv_usec as u32) * 1000;
2296- Some(Duration::new(sec, nsec))
2297+impl AsRawFd for Socket {
2298+ fn as_raw_fd(&self) -> RawFd {
2299+ self.inner
2300 }
2301 }
2302
2303-fn to_s_addr(addr: &Ipv4Addr) -> libc::in_addr_t {
2304- let octets = addr.octets();
2305- crate::hton(
2306- ((octets[0] as libc::in_addr_t) << 24)
2307- | ((octets[1] as libc::in_addr_t) << 16)
2308- | ((octets[2] as libc::in_addr_t) << 8)
2309- | ((octets[3] as libc::in_addr_t) << 0),
2310- )
2311-}
2312-
2313-fn from_s_addr(in_addr: libc::in_addr_t) -> Ipv4Addr {
2314- let h_addr = crate::ntoh(in_addr);
2315-
2316- let a: u8 = (h_addr >> 24) as u8;
2317- let b: u8 = (h_addr >> 16) as u8;
2318- let c: u8 = (h_addr >> 8) as u8;
2319- let d: u8 = (h_addr >> 0) as u8;
2320-
2321- Ipv4Addr::new(a, b, c, d)
2322-}
2323-
2324-fn to_in6_addr(addr: &Ipv6Addr) -> libc::in6_addr {
2325- let mut ret: libc::in6_addr = unsafe { mem::zeroed() };
2326- ret.s6_addr = addr.octets();
2327- return ret;
2328-}
2329-
2330-#[cfg(target_os = "android")]
2331-fn to_ipv6mr_interface(value: u32) -> c_int {
2332- value as c_int
2333-}
2334-
2335-#[cfg(not(target_os = "android"))]
2336-fn to_ipv6mr_interface(value: u32) -> libc::c_uint {
2337- value as libc::c_uint
2338-}
2339-
2340-fn linger2dur(linger_opt: libc::linger) -> Option<Duration> {
2341- if linger_opt.l_onoff == 0 {
2342- None
2343- } else {
2344- Some(Duration::from_secs(linger_opt.l_linger as u64))
2345+impl IntoRawFd for Socket {
2346+ fn into_raw_fd(self) -> RawFd {
2347+ let fd = self.inner;
2348+ mem::forget(self);
2349+ fd
2350 }
2351 }
2352
2353-fn dur2linger(dur: Option<Duration>) -> libc::linger {
2354- match dur {
2355- Some(d) => libc::linger {
2356- l_onoff: 1,
2357- l_linger: d.as_secs() as c_int,
2358- },
2359- None => libc::linger {
2360- l_onoff: 0,
2361- l_linger: 0,
2362- },
2363+impl Drop for Socket {
2364+ fn drop(&mut self) {
2365+ // Can't handle the error here, nor can we do much with it.
2366+ let _ = unsafe { libc::close(self.inner) };
2367 }
2368 }
2369-
2370-#[test]
2371-fn test_ip() {
2372- let ip = Ipv4Addr::new(127, 0, 0, 1);
2373- assert_eq!(ip, from_s_addr(to_s_addr(&ip)));
2374-}
2375diff --git a/tests/socket.rs b/tests/socket.rs
2376new file mode 100644
2377index 0000000..66058e1
2378--- /dev/null
2379+++ b/tests/socket.rs
2380@@ -0,0 +1,122 @@
2381+use std::net::{TcpListener, TcpStream, UdpSocket};
2382+
2383+use socket2::{Domain, Socket, Type};
2384+
2385+mod util;
2386+use util::any_local_ipv4_addr;
2387+
2388+#[test]
2389+fn from_std_tcp_stream() {
2390+ let listener = TcpListener::bind(any_local_ipv4_addr()).unwrap();
2391+ let tcp_socket = TcpStream::connect(listener.local_addr().unwrap()).unwrap();
2392+ let socket: Socket = tcp_socket.into();
2393+ drop(socket);
2394+}
2395+
2396+#[test]
2397+fn from_std_tcp_listener() {
2398+ let tcp_socket = TcpListener::bind(any_local_ipv4_addr()).unwrap();
2399+ let socket: Socket = tcp_socket.into();
2400+ drop(socket);
2401+}
2402+
2403+#[test]
2404+fn from_std_udp_socket() {
2405+ let udp_socket = UdpSocket::bind(any_local_ipv4_addr()).unwrap();
2406+ let socket: Socket = udp_socket.into();
2407+ drop(socket);
2408+}
2409+
2410+#[test]
2411+fn into_std_tcp_stream() {
2412+ let socket: Socket = Socket::new(Domain::ipv4(), Type::stream(), None).unwrap();
2413+ let tcp_socket: TcpStream = socket.into();
2414+ drop(tcp_socket);
2415+}
2416+
2417+#[test]
2418+fn into_std_tcp_listener() {
2419+ let socket: Socket = Socket::new(Domain::ipv4(), Type::stream(), None).unwrap();
2420+ let tcp_socket: TcpListener = socket.into();
2421+ drop(tcp_socket);
2422+}
2423+
2424+#[test]
2425+fn into_std_udp_socket() {
2426+ let socket: Socket = Socket::new(Domain::ipv4(), Type::dgram(), None).unwrap();
2427+ let udp_socket: UdpSocket = socket.into();
2428+ drop(udp_socket);
2429+}
2430+
2431+#[test]
2432+fn socket_connect_tcp() {
2433+ let listener = TcpListener::bind(any_local_ipv4_addr()).unwrap();
2434+ let addr = listener.local_addr().unwrap();
2435+
2436+ let socket: TcpStream = Socket::new(Domain::ipv4(), Type::stream(), None)
2437+ .and_then(|socket| socket.connect(&addr.into()).map(|()| socket.into()))
2438+ .unwrap();
2439+ assert_eq!(socket.peer_addr().unwrap(), addr);
2440+
2441+ let (stream, peer_addr) = listener.accept().unwrap();
2442+ let socket_local_addr = socket.local_addr().unwrap();
2443+ assert_eq!(peer_addr, socket_local_addr);
2444+ assert_eq!(stream.peer_addr().unwrap(), socket_local_addr);
2445+}
2446+
2447+#[test]
2448+fn socket_bind_tcp() {
2449+ let socket: TcpListener = Socket::new(Domain::ipv4(), Type::stream(), None)
2450+ .and_then(|socket| {
2451+ socket
2452+ .bind(&any_local_ipv4_addr().into())
2453+ .map(|()| socket.into())
2454+ })
2455+ .unwrap();
2456+
2457+ assert!(socket.local_addr().unwrap().ip().is_loopback())
2458+}
2459+
2460+#[test]
2461+fn socket_listen_tcp() {
2462+ let socket: TcpListener = Socket::new(Domain::ipv4(), Type::stream(), None)
2463+ .and_then(|socket| {
2464+ socket.bind(&any_local_ipv4_addr().into())?;
2465+ socket.listen(1024)?;
2466+ Ok(socket.into())
2467+ })
2468+ .unwrap();
2469+ let addr = socket.local_addr().unwrap();
2470+
2471+ let stream = TcpStream::connect(addr).unwrap();
2472+ let stream_addr = stream.local_addr().unwrap();
2473+
2474+ let (accepted_stream, peer_addr) = socket.accept().unwrap();
2475+ assert_eq!(peer_addr, stream_addr);
2476+ assert_eq!(accepted_stream.peer_addr().unwrap(), stream_addr);
2477+}
2478+
2479+// Also tests `local_addr` and `peer_addr`.
2480+#[test]
2481+fn socket_accept_tcp() {
2482+ let socket: Socket = Socket::new(Domain::ipv4(), Type::stream(), None)
2483+ .and_then(|socket| {
2484+ socket.bind(&any_local_ipv4_addr().into())?;
2485+ socket.listen(1024)?;
2486+ Ok(socket.into())
2487+ })
2488+ .unwrap();
2489+ let addr = socket.local_addr().unwrap();
2490+ let addr = addr.as_std().unwrap();
2491+
2492+ let stream = TcpStream::connect(addr).unwrap();
2493+ let stream_addr = stream.local_addr().unwrap();
2494+
2495+ let (accepted_socket, peer_addr) = socket.accept().unwrap();
2496+ let peer_addr = peer_addr.as_std().unwrap();
2497+ assert_eq!(peer_addr, stream_addr);
2498+ assert_eq!(
2499+ accepted_socket.peer_addr().unwrap().as_std().unwrap(),
2500+ stream_addr
2501+ );
2502+}
2503diff --git a/tests/unix.rs b/tests/unix.rs
2504new file mode 100644
2505index 0000000..3af40f6
2506--- /dev/null
2507+++ b/tests/unix.rs
2508@@ -0,0 +1,60 @@
2509+//! Tests for Unix only API.
2510+
2511+#![cfg(unix)]
2512+
2513+use std::os::unix::net::{UnixDatagram, UnixListener, UnixStream};
2514+
2515+use socket2::{Domain, Socket, Type};
2516+
2517+mod util;
2518+use util::temp_file;
2519+
2520+#[test]
2521+fn from_std_unix_stream() {
2522+ let path = temp_file("from_std_unix_stream");
2523+ let listener = UnixListener::bind(&path).unwrap();
2524+ let stream = UnixStream::connect(&path).unwrap();
2525+ let socket: Socket = stream.into();
2526+ drop(socket);
2527+ drop(listener);
2528+}
2529+
2530+#[test]
2531+fn from_std_unix_listener() {
2532+ let path = temp_file("from_std_unix_listener");
2533+ let listener = UnixListener::bind(&path).unwrap();
2534+ let socket: Socket = listener.into();
2535+ drop(socket);
2536+}
2537+
2538+#[test]
2539+fn from_std_unix_socket() {
2540+ let path = temp_file("from_std_unix_socket");
2541+ let datagram = UnixDatagram::bind(&path).unwrap();
2542+ let socket: Socket = datagram.into();
2543+ drop(socket);
2544+}
2545+
2546+#[test]
2547+fn into_std_unix_stream() {
2548+ let socket: Socket = Socket::new(Domain::unix(), Type::stream(), None).unwrap();
2549+ let unix_socket: UnixStream = socket.into();
2550+ drop(unix_socket);
2551+}
2552+
2553+#[test]
2554+fn into_std_tcp_listener() {
2555+ let socket: Socket = Socket::new(Domain::unix(), Type::stream(), None).unwrap();
2556+ let unix_socket: UnixListener = socket.into();
2557+ drop(unix_socket);
2558+}
2559+
2560+#[test]
2561+fn into_std_udp_socket() {
2562+ let socket: Socket = Socket::new(Domain::unix(), Type::dgram(), None).unwrap();
2563+ let unix_socket: UnixDatagram = socket.into();
2564+ drop(unix_socket);
2565+}
2566+
2567+// TODO: test accept4.
2568+// TODO: test pair.
2569diff --git a/tests/util/mod.rs b/tests/util/mod.rs
2570new file mode 100644
2571index 0000000..1744e40
2572--- /dev/null
2573+++ b/tests/util/mod.rs
2574@@ -0,0 +1,49 @@
2575+// Not all tests use all functions.
2576+#![allow(dead_code)]
2577+
2578+use std::net::SocketAddr;
2579+use std::path::PathBuf;
2580+use std::sync::Once;
2581+use std::{env, fs};
2582+
2583+/// Bind to any port on localhost.
2584+pub fn any_local_ipv4_addr() -> SocketAddr {
2585+ "127.0.0.1:0".parse().unwrap()
2586+}
2587+
2588+/* TODO: needed?
2589+/// Bind to any port on localhost, using a IPv6 address.
2590+pub fn any_local_ipv6_addr() -> SocketAddr {
2591+ "[::1]:0".parse().unwrap()
2592+}
2593+*/
2594+
2595+/// Returns a path to a temporary file using `name` as filename.
2596+pub fn temp_file(name: &'static str) -> PathBuf {
2597+ init();
2598+ let mut path = temp_dir();
2599+ path.push(name);
2600+ path
2601+}
2602+
2603+pub fn init() {
2604+ static INIT: Once = Once::new();
2605+
2606+ INIT.call_once(|| {
2607+ // Remove all temporary files from previous test runs.
2608+ let dir = temp_dir();
2609+ let _ = fs::remove_dir_all(&dir);
2610+ fs::create_dir_all(&dir).expect("unable to create temporary directory");
2611+ })
2612+}
2613+
2614+/// Returns the temporary directory for test files.
2615+///
2616+/// # Notes
2617+///
2618+/// `init` must be called before this.
2619+fn temp_dir() -> PathBuf {
2620+ let mut path = env::temp_dir();
2621+ path.push("socket_tests");
2622+ path
2623+}