uds_fork/
seqpacket.rs

1use std::
2{
3    io::{self, IoSlice, IoSliceMut}, 
4    net::Shutdown, 
5    os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}, 
6    path::Path, 
7    time::Duration
8};
9
10use libc::{MSG_EOR, MSG_PEEK, c_void, send, recv};
11
12//use crate::addr::*;
13use crate::{UnixSocketAddr, helpers::*};
14use crate::ancillary::*;
15use crate::credentials::*;
16
17/// An unix domain sequential packet connection.
18///
19/// Sequential-packet connections have an interface similar to streams,
20/// but behave more like connected datagram sockets.
21///
22/// They have guaranteed in-order and reliable delivery,
23/// which unix datagrams technically doesn't.
24///
25/// # Operating system support
26///
27/// Sequential-packet sockets are supported by Linux, FreeBSD, NetBSD
28/// and Illumos, but not by for example macOS or OpenBSD.
29///
30/// # Zero-length packets
31///
32/// ... are best avoided:  
33/// On Linux and FreeBSD zero-length packets can be sent and received,
34/// but there is no way to distinguish receiving one from reaching
35/// end of connection unless the packet has an ancillary payload.
36/// Also beware of trying to receive with a zero-length buffer,
37/// as that will on FreeBSD (and probably other BSDs with seqpacket sockets)
38/// always succeed even if there is no packet waiting.
39///
40/// Illumos and Solaris doesn't support receiving zero-length packets at all:
41/// writes succeed but recv() will block.
42///
43/// # Examples
44///
45/// What is sent separately is received separately:
46///
47#[cfg_attr(not(target_vendor="apple"), doc="```")]
48#[cfg_attr(target_vendor="apple", doc="```no_run")]
49/// let (a, b) = uds_fork::UnixSeqpacketConn::pair().expect("Cannot create seqpacket pair");
50///
51/// a.send(b"first").unwrap();
52/// a.send(b"second").unwrap();
53///
54/// let mut buffer_big_enough_for_both = [0; 20];
55/// let len = b.recv(&mut buffer_big_enough_for_both).unwrap();
56/// assert_eq!(&buffer_big_enough_for_both[..len], b"first");
57/// let len = b.recv(&mut buffer_big_enough_for_both).unwrap();
58/// assert_eq!(&buffer_big_enough_for_both[..len], b"second");
59/// ```
60///
61/// Connect to a listener on a socket file and write to it:
62///
63#[cfg_attr(not(target_vendor="apple"), doc="```")]
64#[cfg_attr(target_vendor="apple", doc="```no_run")]
65/// use uds_fork::{UnixSeqpacketListener, UnixSeqpacketConn};
66///
67/// # let _ = std::fs::remove_file("/tmp/seqpacket.socket"); // pre-emptively delete just in case
68/// let listener = UnixSeqpacketListener::bind("/tmp/seqpacket.socket")
69///     .expect("create seqpacket listener");
70/// let conn = UnixSeqpacketConn::connect("/tmp/seqpacket.socket")
71///     .expect("connect to seqpacket listener");
72///
73/// let message = "Hello, listener";
74/// let sent = conn.send(message.as_bytes()).unwrap();
75/// assert_eq!(sent, message.len());
76///
77/// std::fs::remove_file("/tmp/seqpacket.socket").unwrap(); // clean up after ourselves
78/// ```
79///
80/// Connect to a listener on an abstract address:
81///
82#[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
83#[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
84/// use uds_fork::{UnixSeqpacketListener, UnixSeqpacketConn, UnixSocketAddr};
85///
86/// let addr = UnixSocketAddr::new("@seqpacket example").unwrap();
87/// let listener = UnixSeqpacketListener::bind_unix_addr(&addr)
88///     .expect("create abstract seqpacket listener");
89/// let _client = UnixSeqpacketConn::connect_unix_addr(&addr)
90///     .expect("connect to abstract seqpacket listener");
91/// let (_server, _addr) = listener.accept_unix_addr().unwrap();
92/// ```
93#[derive(Debug)]
94#[repr(transparent)]
95pub struct UnixSeqpacketConn 
96{
97    fd: OwnedFd,
98}
99
100impl From<UnixSeqpacketConn> for OwnedFd
101{
102    fn from(value: UnixSeqpacketConn) -> Self 
103    {
104        return value.fd;
105    }
106}
107
108impl FromRawFd for UnixSeqpacketConn
109{
110    unsafe 
111    fn from_raw_fd(fd: RawFd) -> Self 
112    {
113        return 
114            UnixSeqpacketConn { fd: unsafe { OwnedFd::from_raw_fd(fd) } };
115    }
116}
117
118impl AsRawFd for UnixSeqpacketConn
119{
120    fn as_raw_fd(&self) -> RawFd 
121    {
122        self.fd.as_raw_fd()
123    }
124}
125impl IntoRawFd for UnixSeqpacketConn
126{
127    fn into_raw_fd(self) -> RawFd 
128    {
129        self.fd.into_raw_fd()
130    }
131}
132
133impl AsFd for UnixSeqpacketConn
134{
135    fn as_fd(&self) -> BorrowedFd<'_> 
136    {
137        self.fd.as_fd()
138    }
139}
140
141impl UnixSeqpacketConn 
142{
143    /// Connects to an unix seqpacket server listening at `path`.
144    ///
145    /// This is a wrapper around [`connect_unix_addr()`](#method.connect_unix_addr)
146    /// for convenience and compatibility with std.
147    pub 
148    fn connect<P: AsRef<Path>>(path: P) -> Result<Self, io::Error> 
149    {
150        let addr = UnixSocketAddr::from_path(&path)?;
151        Self::connect_unix_addr(&addr)
152    }
153
154    /// Connects to an unix seqpacket server listening at `addr`.
155    pub 
156    fn connect_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error> 
157    {
158        let socket = Socket::<SocketSeqPkt>::new(false)?;
159        socket.set_unix_addr(SetAddr::PEER,  addr)?;
160        
161        return Ok(UnixSeqpacketConn { fd: socket.into() });
162    }
163    
164    /// Binds to an address before connecting to a listening seqpacet socket.
165    pub 
166    fn connect_from_to_unix_addr(from: &UnixSocketAddr,  to: &UnixSocketAddr) -> Result<Self, io::Error> 
167    {
168        let socket = Socket::<SocketSeqPkt>::new(false)?;
169        socket.set_unix_addr(SetAddr::LOCAL, from)?;
170        socket.set_unix_addr(SetAddr::PEER, to)?;
171        
172        return Ok(UnixSeqpacketConn { fd: socket.into() });
173    }
174
175    /// Creates a pair of unix-domain seqpacket conneections connected to each other.
176    ///
177    /// # Examples
178    ///
179    #[cfg_attr(not(target_vendor="apple"), doc="```")]
180    #[cfg_attr(target_vendor="apple", doc="```no_run")]
181    /// let (a, b) = uds_fork::UnixSeqpacketConn::pair().unwrap();
182    /// assert!(a.local_unix_addr().unwrap().is_unnamed());
183    /// assert!(b.local_unix_addr().unwrap().is_unnamed());
184    ///
185    /// a.send(b"hello").unwrap();
186    /// b.recv(&mut[0; 20]).unwrap();
187    /// ```
188    pub 
189    fn pair() -> Result<(Self, Self), io::Error> 
190    {
191        let pair = Socket::<SocketSeqPkt>::pair(false)?;
192        
193        return Ok(
194            (
195                UnixSeqpacketConn { fd: pair.0.into() },
196                UnixSeqpacketConn { fd: pair.1.into() }
197            )
198        );
199    }
200
201    /// Returns the address of this side of the connection.
202    pub 
203    fn local_unix_addr(&self) -> Result<UnixSocketAddr, io::Error> 
204    {
205        get_unix_addr(&self, GetAddr::LOCAL)
206    }
207
208    /// Returns the address of the other side of the connection.
209    pub 
210    fn peer_unix_addr(&self) -> Result<UnixSocketAddr, io::Error> 
211    {
212        get_unix_addr(&self, GetAddr::PEER)
213    }
214
215    /// Returns information about the process of the peer when the connection was established.
216    ///
217    /// See documentation of the returned type for details.
218    pub 
219    fn initial_peer_credentials(&self) -> Result<ConnCredentials, io::Error> 
220    {
221        peer_credentials(&self)
222    }
223
224    /// Returns the SELinux security context of the process that created the other
225    /// end of this connection.
226    ///
227    /// Will return an error on other operating systems than Linux or Android,
228    /// and also if running inside kubernetes.
229    /// On success the number of bytes used is returned. (like `Read`)
230    ///
231    /// The default security context is `unconfined`, without any trailing NUL.  
232    /// A buffor of 50 bytes is probably always big enough.
233    pub 
234    fn initial_peer_selinux_context(&self,  buf: &mut[u8]) -> Result<usize, io::Error> 
235    {
236        selinux_context(&self, buf)
237    }
238
239
240    /// Sends a packet to the peer.
241    pub 
242    fn send(&self,  packet: &[u8]) -> Result<usize, io::Error> 
243    {
244        let ptr = packet.as_ptr() as *const c_void;
245        let flags = MSG_NOSIGNAL | MSG_EOR;
246        let sent = cvt_r!(unsafe { send(self.fd.as_raw_fd(), ptr, packet.len(), flags) })?;
247        Ok(sent as usize)
248    }
249
250    /// Sends a packet to the peer.
251    pub 
252    fn send_flags(&self,  packet: &[u8], flags: i32) -> Result<usize, io::Error> 
253    {
254        let ptr = packet.as_ptr() as *const c_void;
255        let sent = cvt_r!(unsafe { send(self.fd.as_raw_fd(), ptr, packet.len(), flags) })?;
256        Ok(sent as usize)
257    }
258
259    /// Receives a packet from the peer.
260    pub 
261    fn recv(&self,  buffer: &mut[u8]) -> Result<usize, io::Error> 
262    {
263        let ptr = buffer.as_ptr() as *mut c_void;
264        let received = cvt_r!(unsafe { recv(self.fd.as_raw_fd(), ptr, buffer.len(), MSG_NOSIGNAL) })?;
265        Ok(received as usize)
266    }
267
268    /// Sends a packet assembled from multiple byte slices.
269    pub 
270    fn send_vectored(&self,  slices: &[IoSlice]) -> Result<usize, io::Error> 
271    {
272        // Can't use writev() because we need to pass flags,
273        // and the flags accepted by pwritev2() aren't the one we need to pass.
274        send_ancillary(&self, None, MSG_EOR, slices, Vec::new(), None)
275    }
276    /// Reads a packet into multiple buffers.
277    ///
278    /// The returned `bool` indicates whether the packet was truncated due to
279    /// too short buffers.
280    pub 
281    fn recv_vectored(&self,  buffers: &mut[IoSliceMut]) -> Result<(usize, bool), io::Error> 
282    {
283        recv_ancillary(&self, None, 0, buffers, &mut[])
284            .map(|(bytes, ancillary)| (bytes, ancillary.message_truncated()) )
285    }
286
287    /// Sends a packet with associated file descriptors.
288    pub 
289    fn send_fds(&self, bytes: &[u8], fds: Vec<OwnedFd>) -> Result<usize, io::Error> 
290    {
291        send_ancillary(&self, None, MSG_EOR, &[IoSlice::new(bytes)], fds, None)
292    }
293
294    /// Receives a packet and associated file descriptors.
295    pub 
296    fn recv_fds(&self, byte_buffer: &mut[u8], fd_buffer: &mut Vec<OwnedFd>) -> Result<(usize, bool, usize), io::Error> 
297    {
298        recv_fds(&self, None, &mut[IoSliceMut::new(byte_buffer)], Some(fd_buffer))
299    }
300
301    /// Receives a packet without removing it from the incoming queue.
302    ///
303    /// # Examples
304    ///
305    #[cfg_attr(not(target_vendor="apple"), doc="```")]
306    #[cfg_attr(target_vendor="apple", doc="```no_run")]
307    /// let (a, b) = uds_fork::UnixSeqpacketConn::pair().unwrap();
308    /// a.send(b"hello").unwrap();
309    /// let mut buf = [0u8; 10];
310    /// assert_eq!(b.peek(&mut buf[..1]).unwrap(), 1);
311    /// assert_eq!(&buf[..2], &[b'h', 0]);
312    /// assert_eq!(b.peek(&mut buf).unwrap(), 5);
313    /// assert_eq!(&buf[..5], b"hello");
314    /// assert_eq!(b.recv(&mut buf).unwrap(), 5);
315    /// assert_eq!(&buf[..5], b"hello");
316    /// ```
317    pub 
318    fn peek(&self,  buffer: &mut[u8]) -> Result<usize, io::Error> 
319    {
320        let ptr = buffer.as_ptr() as *mut c_void;
321        let flags = MSG_NOSIGNAL | MSG_PEEK;
322        let received = cvt_r!(unsafe { recv(self.fd.as_raw_fd(), ptr, buffer.len(), flags) })?;
323        Ok(received as usize)
324    }
325
326    /// Receives a packet without removing it from the incoming queue.
327    ///
328    /// The returned `bool` indicates whether the packet was truncated due to
329    /// the combined buffers being too small.
330    pub 
331    fn peek_vectored(&self,  buffers: &mut[IoSliceMut]) -> Result<(usize, bool), io::Error> 
332    {
333        recv_ancillary(&self, None, MSG_PEEK, buffers, &mut[])
334            .map(|(bytes, ancillary)| (bytes, ancillary.message_truncated()) )
335    }
336
337    /// Returns the value of the `SO_ERROR` option.
338    ///
339    /// This might only provide errors generated from nonblocking `connect()`s,
340    /// which this library doesn't support. It is therefore unlikely to be 
341    /// useful, but is provided for parity with stream counterpart in std.
342    ///
343    /// # Examples
344    ///
345    #[cfg_attr(not(target_vendor="apple"), doc="```")]
346    #[cfg_attr(target_vendor="apple", doc="```no_run")]
347    /// let (a, b) = uds_fork::UnixSeqpacketConn::pair().unwrap();
348    /// drop(b);
349    ///
350    /// assert!(a.send(b"anyone there?").is_err());
351    /// assert!(a.take_error().unwrap().is_none());
352    /// ```
353    pub 
354    fn take_error(&self) -> Result<Option<io::Error>, io::Error> 
355    {
356        take_error(&self)
357    }
358
359
360    /// Creates a new file descriptor also pointing to this side of this connection.
361    ///
362    /// # Examples
363    ///
364    /// Both new and old can send and receive, and share queues:
365    ///
366    #[cfg_attr(not(target_vendor="apple"), doc="```")]
367    #[cfg_attr(target_vendor="apple", doc="```no_run")]
368    /// let (a1, b) = uds_fork::nonblocking::UnixSeqpacketConn::pair().unwrap();
369    /// let a2 = a1.try_clone().unwrap();
370    ///
371    /// a1.send(b"first").unwrap();
372    /// a2.send(b"second").unwrap();
373    ///
374    /// let mut buf = [0u8; 20];
375    /// let len = b.recv(&mut buf).unwrap();
376    /// assert_eq!(&buf[..len], b"first");
377    /// b.send(b"hello first").unwrap();
378    /// let len = b.recv(&mut buf).unwrap();
379    /// assert_eq!(&buf[..len], b"second");
380    /// b.send(b"hello second").unwrap();
381    ///
382    /// let len = a2.recv(&mut buf).unwrap();
383    /// assert_eq!(&buf[..len], b"hello first");
384    /// let len = a1.recv(&mut buf).unwrap();
385    /// assert_eq!(&buf[..len], b"hello second");
386    /// ```
387    ///
388    /// Clone can still be used after the first one has been closed:
389    ///
390    #[cfg_attr(not(target_vendor="apple"), doc="```")]
391    #[cfg_attr(target_vendor="apple", doc="```no_run")]
392    /// let (a, b1) = uds_fork::nonblocking::UnixSeqpacketConn::pair().unwrap();
393    /// a.send(b"hello").unwrap();
394    ///
395    /// let b2 = b1.try_clone().unwrap();
396    /// drop(b1);
397    /// assert_eq!(b2.recv(&mut[0; 10]).unwrap(), "hello".len());
398    /// ```
399    pub 
400    fn try_clone(&self) -> Result<Self, io::Error> 
401    {
402        let cloned = Socket::<SocketSeqPkt>::try_clone_from(self.fd.as_fd())?;
403
404        return Ok(UnixSeqpacketConn { fd: cloned.into() });
405    }
406
407    /// Sets the read timeout to the duration specified.
408    ///
409    /// If the value specified is `None`, then `recv()` and its variants will
410    /// block indefinitely.  
411    /// An error is returned if the duration is zero.
412    ///
413    /// The duration is rounded to microsecond precission.
414    /// Currently it's rounded down except if that would make it all zero.
415    ///
416    /// # Operating System Support
417    ///
418    /// On Illumos (and pressumably also Solaris) timeouts appears not to work
419    /// for unix domain sockets.
420    ///
421    /// # Examples
422    ///
423    #[cfg_attr(not(any(target_vendor="apple", target_os="illumos", target_os="solaris")), doc="```")]
424    #[cfg_attr(any(target_vendor="apple", target_os="illumos", target_os="solaris"), doc="```no_run")]
425    /// use std::io::ErrorKind;
426    /// use std::time::Duration;
427    /// use uds_fork::UnixSeqpacketConn;
428    ///
429    /// let (a, b) = UnixSeqpacketConn::pair().unwrap();
430    /// a.set_read_timeout(Some(Duration::new(0, 2_000_000))).unwrap();
431    /// let error = a.recv(&mut[0; 1024]).unwrap_err();
432    /// assert_eq!(error.kind(), ErrorKind::WouldBlock);
433    /// ```
434    pub 
435    fn set_read_timeout(&self, timeout: Option<Duration>) -> Result<(), io::Error> 
436    {
437        set_timeout(self.fd.as_fd(), TimeoutDirection::READ, timeout)
438    }
439    /// Returns the read timeout of this socket.
440    ///
441    /// `None` is returned if there is no timeout.
442    ///
443    /// Note that subsecond parts might have been be rounded by the OS
444    /// (in addition to the rounding to microsecond in `set_read_timeout()`).
445    ///
446    /// # Examples
447    ///
448    #[cfg_attr(not(any(target_vendor="apple", target_os="illumos", target_os="solaris")), doc="```")]
449    #[cfg_attr(any(target_vendor="apple", target_os="illumos", target_os="solaris"), doc="```no_run")]
450    /// use uds_fork::UnixSeqpacketConn;
451    /// use std::time::Duration;
452    ///
453    /// let timeout = Some(Duration::new(2, 0));
454    /// let conn = UnixSeqpacketConn::pair().unwrap().0;
455    /// conn.set_read_timeout(timeout).unwrap();
456    /// assert_eq!(conn.read_timeout().unwrap(), timeout);
457    /// ```
458    pub 
459    fn read_timeout(&self) -> Result<Option<Duration>, io::Error> 
460    {
461        get_timeout(self.fd.as_fd(), TimeoutDirection::READ)
462    }
463
464    /// Sets the write timeout to the duration specified.
465    ///
466    /// If the value specified is `None`, then `send()` and its variants will
467    /// block indefinitely.  
468    /// An error is returned if the duration is zero.
469    ///
470    /// # Operating System Support
471    ///
472    /// On Illumos (and pressumably also Solaris) timeouts appears not to work
473    /// for unix domain sockets.
474    ///
475    /// # Examples
476    ///
477    #[cfg_attr(not(any(target_vendor="apple", target_os="illumos", target_os="solaris")), doc="```")]
478    #[cfg_attr(any(target_vendor="apple", target_os="illumos", target_os="solaris"), doc="```no_run")]
479    /// # use std::io::ErrorKind;
480    /// # use std::time::Duration;
481    /// # use uds_fork::UnixSeqpacketConn;
482    /// #
483    /// let (conn, _other) = UnixSeqpacketConn::pair().unwrap();
484    /// conn.set_write_timeout(Some(Duration::new(0, 500 * 1000))).unwrap();
485    /// loop {
486    ///     if let Err(e) = conn.send(&[0; 1000]) {
487    ///         assert_eq!(e.kind(), ErrorKind::WouldBlock, "{}", e);
488    ///         break
489    ///     }
490    /// }
491    /// ```
492    pub 
493    fn set_write_timeout(&self,  timeout: Option<Duration>)-> Result<(), io::Error> 
494    {
495        set_timeout(self.fd.as_fd(), TimeoutDirection::WRITE, timeout)
496    }
497
498    /// Returns the write timeout of this socket.
499    ///
500    /// `None` is returned if there is no timeout.
501    ///
502    /// # Examples
503    ///
504    #[cfg_attr(not(target_vendor="apple"), doc="```")]
505    #[cfg_attr(target_vendor="apple", doc="```no_run")]
506    /// let conn = uds_fork::UnixSeqpacketConn::pair().unwrap().0;
507    /// assert!(conn.write_timeout().unwrap().is_none());
508    /// ```
509    pub 
510    fn write_timeout(&self) -> Result<Option<Duration>, io::Error> 
511    {
512        get_timeout(self.fd.as_fd(), TimeoutDirection::WRITE)
513    }
514
515    /// Enables or disables nonblocking mode.
516    ///
517    /// Consider using the nonblocking variant of this type instead.
518    /// This method mainly exists for feature parity with std's `UnixStream`.
519    ///
520    /// # Examples
521    ///
522    /// Trying to receive when there are no packets waiting:
523    ///
524    #[cfg_attr(not(target_vendor="apple"), doc="```")]
525    #[cfg_attr(target_vendor="apple", doc="```no_run")]
526    /// # use std::io::ErrorKind;
527    /// # use uds_fork::UnixSeqpacketConn;
528    /// let (a, b) = UnixSeqpacketConn::pair().expect("create seqpacket pair");
529    /// a.set_nonblocking(true).unwrap();
530    /// assert_eq!(a.recv(&mut[0; 20]).unwrap_err().kind(), ErrorKind::WouldBlock);
531    /// ```
532    ///
533    /// Trying to send when the OS buffer for the connection is full:
534    ///
535    #[cfg_attr(not(target_vendor="apple"), doc="```")]
536    #[cfg_attr(target_vendor="apple", doc="```no_run")]
537    /// # use std::io::ErrorKind;
538    /// # use uds_fork::UnixSeqpacketConn;
539    /// let (a, b) = UnixSeqpacketConn::pair().expect("create seqpacket pair");
540    /// a.set_nonblocking(true).unwrap();
541    /// loop {
542    ///     if let Err(error) = a.send(&[b'#'; 1000]) {
543    ///         assert_eq!(error.kind(), ErrorKind::WouldBlock);
544    ///         break;
545    ///     }
546    /// }
547    /// ```
548    pub 
549    fn set_nonblocking(&self,  nonblocking: bool) -> Result<(), io::Error> 
550    {
551        set_nonblocking(&self, nonblocking)
552    }
553
554    /// Shuts down the read, write, or both halves of this connection.
555    pub 
556    fn shutdown(&self, how: Shutdown) -> io::Result<()> 
557    {
558        let how = match how {
559            Shutdown::Read => libc::SHUT_RD,
560            Shutdown::Write => libc::SHUT_WR,
561            Shutdown::Both => libc::SHUT_RDWR,
562        };
563        unsafe { cvt!(libc::shutdown(self.as_raw_fd(), how)) }?;
564        Ok(())
565    }
566}
567
568
569
570/// An unix domain listener for sequential packet connections.
571///
572/// See [`UnixSeqpacketConn`](struct.UnixSeqpacketConn.html) for a description
573/// of this type of connection.
574///
575/// # Examples
576///
577#[cfg_attr(not(target_vendor="apple"), doc="```")]
578#[cfg_attr(target_vendor="apple", doc="```no_run")]
579/// # let _ = std::fs::remove_file("/tmp/seqpacket_listener.socket");
580/// let listener = uds_fork::UnixSeqpacketListener::bind("/tmp/seqpacket_listener.socket")
581///     .expect("Create seqpacket listener");
582/// let _client = uds_fork::UnixSeqpacketConn::connect("/tmp/seqpacket_listener.socket").unwrap();
583/// let (conn, _addr) = listener.accept_unix_addr().unwrap();
584/// conn.send(b"Welcome").unwrap();
585/// # std::fs::remove_file("/tmp/seqpacket_listener.socket").unwrap();
586/// ```
587#[derive(Debug)]
588#[repr(transparent)]
589pub struct UnixSeqpacketListener 
590{
591    fd: OwnedFd
592}
593
594
595impl FromRawFd for UnixSeqpacketListener
596{
597    unsafe 
598    fn from_raw_fd(fd: RawFd) -> Self 
599    {
600        return 
601            Self{ fd: unsafe { OwnedFd::from_raw_fd(fd) } };
602    }
603}
604
605impl AsRawFd for UnixSeqpacketListener
606{
607    fn as_raw_fd(&self) -> RawFd 
608    {
609        self.fd.as_raw_fd()
610    }
611}
612
613impl IntoRawFd for UnixSeqpacketListener
614{
615    fn into_raw_fd(self) -> RawFd 
616    {
617        self.fd.into_raw_fd()
618    }
619}
620
621impl AsFd for UnixSeqpacketListener
622{
623    fn as_fd(&self) -> BorrowedFd<'_> 
624    {
625        self.fd.as_fd()
626    }
627}
628
629impl UnixSeqpacketListener 
630{
631    /// Creates a socket that listens for seqpacket connections on the specified socket file.
632    pub 
633    fn bind<P: AsRef<Path>>(path: P) -> Result<Self, io::Error> 
634    {
635        let addr = UnixSocketAddr::from_path(path.as_ref())?;
636        
637        return Self::bind_unix_addr(&addr);
638    }
639
640    /// Creates a socket that listens for seqpacket connections on the specified address.
641    pub 
642    fn bind_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error> 
643    {
644        let socket = Socket::<SocketSeqPkt>::new(false)?;
645
646        socket.set_unix_addr(SetAddr::LOCAL, addr)?;
647        socket.start_listening()?;
648        
649        return Ok(UnixSeqpacketListener { fd: socket.into() });
650    }
651
652    /// Returns the address the socket is listening on.
653    pub 
654    fn local_unix_addr(&self) -> Result<UnixSocketAddr, io::Error> 
655    {
656        get_unix_addr(&self, GetAddr::LOCAL)
657    }
658
659    /// Accepts a new incoming connection to this listener.
660    pub 
661    fn accept_unix_addr(&self)-> Result<(UnixSeqpacketConn, UnixSocketAddr), io::Error> 
662    {
663        let (socket, addr) = Socket::<SocketSeqPkt>::accept_from(&self, false)?;
664        let conn = UnixSeqpacketConn { fd: socket.into() };
665        
666        return Ok((conn, addr));
667    }
668
669    /// Returns the value of the `SO_ERROR` option.
670    ///
671    /// This might never produce any errors for listeners. It is therefore
672    /// unlikely to be useful, but is provided for parity with
673    /// `std::unix::net::UnixListener`.
674    pub 
675    fn take_error(&self) -> Result<Option<io::Error>, io::Error> 
676    {
677        take_error(&self)
678    }
679
680    /// Creates a new file descriptor listening for the same connections.
681    pub 
682    fn try_clone(&self) -> Result<Self, io::Error> 
683    {
684        let cloned = Socket::<SocketSeqPkt>::try_clone_from(&self)?;
685        
686        return Ok(UnixSeqpacketListener { fd: cloned.into() });
687    }
688
689    /// Sets a maximum duration to wait in a single `accept()` on this socket.
690    ///
691    /// `None` disables a previously set timeout.
692    /// An error is returned if the duration is zero.
693    ///
694    /// # Operating System Support
695    ///
696    /// Only Linux appers to apply timeouts to `accept()`.  
697    /// On macOS, FreeBSD and NetBSD, timeouts are silently ignored.  
698    /// On Illumos setting timeouts for all unix domain sockets silently fails.
699    ///
700    /// On OSes where timeouts are known to not work, this function will
701    /// return an error even if setting the timeout didn't fail.
702    ///
703    /// # Examples
704    ///
705    #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
706    #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
707    /// # use uds_fork::{UnixSeqpacketListener, UnixSocketAddr};
708    /// # use std::io::ErrorKind;
709    /// # use std::time::Duration;
710    /// #
711    /// # let addr = UnixSocketAddr::new("@set_timeout").unwrap();
712    /// let listener = UnixSeqpacketListener::bind_unix_addr(&addr).unwrap();
713    /// listener.set_timeout(Some(Duration::new(0, 200_000_000))).unwrap();
714    /// let err = listener.accept_unix_addr().unwrap_err();
715    /// assert_eq!(err.kind(), ErrorKind::WouldBlock);
716    /// ```
717    pub 
718    fn set_timeout(&self,  timeout: Option<Duration>) -> Result<(), io::Error> 
719    {
720        match set_timeout(&self, TimeoutDirection::READ, timeout) 
721        {
722            #[cfg(any(
723                target_vendor="apple", target_os="freebsd",
724                target_os="netbsd",
725                target_os="illumos", target_os="solaris",
726            ))]
727            Ok(()) if timeout.is_some() => Err(io::Error::new(
728                ErrorKind::InvalidInput,
729                "listener timeouts are not supported on this OS"
730            )),
731            result => result
732        }
733    }
734
735    /// Returns the timeout for `accept()` on this socket.
736    ///
737    /// `None` is returned if there is no timeout.
738    ///
739    /// Even if a timeout has is set, it is ignored by `accept()` on
740    /// most operating systems except Linux.
741    ///
742    /// # Examples
743    ///
744    #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
745    #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
746    /// # use uds_fork::{UnixSeqpacketListener, UnixSocketAddr};
747    /// # use std::time::Duration;
748    /// #
749    /// # let addr = UnixSocketAddr::new("@timeout").unwrap();
750    /// let listener = UnixSeqpacketListener::bind_unix_addr(&addr).unwrap();
751    /// assert_eq!(listener.timeout().unwrap(), None);
752    /// let timeout = Some(Duration::new(2, 0));
753    /// listener.set_timeout(timeout).unwrap();
754    /// assert_eq!(listener.timeout().unwrap(), timeout);
755    /// ```
756    pub 
757    fn timeout(&self) -> Result<Option<Duration>, io::Error> 
758    {
759        get_timeout(&self, TimeoutDirection::READ)
760    }
761
762    /// Enables or disables nonblocking-ness of [`accept_unix_addr()`](#method.accept_unix addr).
763    ///
764    /// The returned connnections will still be in blocking mode regardsless.
765    ///
766    /// Consider using the nonblocking variant of this type instead;
767    /// this method mostly exists for feature parity with std's `UnixListener`.
768    ///
769    /// # Examples
770    ///
771    #[cfg_attr(not(target_vendor="apple"), doc="```")]
772    #[cfg_attr(target_vendor="apple", doc="```no_run")]
773    /// # use std::io::ErrorKind;
774    /// # use uds_fork::{UnixSocketAddr, UnixSeqpacketListener};
775    /// #
776    /// # let addr = UnixSocketAddr::from_path("/tmp/nonblocking_seqpacket_listener.socket").unwrap();
777    /// # let _ = std::fs::remove_file("/tmp/nonblocking_seqpacket_listener.socket");
778    /// let listener = UnixSeqpacketListener::bind_unix_addr(&addr).expect("create listener");
779    /// listener.set_nonblocking(true).expect("enable noblocking mode");
780    /// assert_eq!(listener.accept_unix_addr().unwrap_err().kind(), ErrorKind::WouldBlock);
781    /// # std::fs::remove_file("/tmp/nonblocking_seqpacket_listener.socket").expect("delete socket file");
782    /// ```
783    pub 
784    fn set_nonblocking(&self,  nonblocking: bool) -> Result<(), io::Error> 
785    {
786        set_nonblocking(&self, nonblocking)
787    }
788}
789
790
791
792/// A non-blocking unix domain sequential-packet connection.
793///
794/// Differs from [`uds_fork::UnixSeqpacketConn`](../struct.UnixSeqpacketConn.html)
795/// in that all operations that send or receive data will return an `Error` of
796/// kind `ErrorKind::WouldBlock` instead of blocking.
797/// This is done by creating the socket as non-blocking, and not by passing
798/// `MSG_DONTWAIT`. If creating this type from a raw file descriptor, ensure
799/// the fd is set to nonblocking before using it through this type.
800/// 
801/// # Examples
802///
803/// Sending or receiving when it would block a normal socket:
804///
805#[cfg_attr(not(target_vendor="apple"), doc="```")]
806#[cfg_attr(target_vendor="apple", doc="```no_run")]
807/// use uds_fork::nonblocking::UnixSeqpacketConn;
808/// use std::io::ErrorKind;
809///
810/// let (a, b) = UnixSeqpacketConn::pair().expect("create nonblocking seqpacket pair");
811///
812/// // trying to receive when there are no packets waiting
813/// assert_eq!(a.recv(&mut[0]).unwrap_err().kind(), ErrorKind::WouldBlock);
814///
815/// // trying to send when the OS buffer for the connection is full
816/// loop {
817///     if let Err(error) = a.send(&[0u8; 1000]) {
818///         assert_eq!(error.kind(), ErrorKind::WouldBlock);
819///         break;
820///     }
821/// }
822/// ```
823#[derive(Debug)]
824#[repr(transparent)]
825pub struct NonblockingUnixSeqpacketConn 
826{
827    fd: OwnedFd,
828}
829
830impl From<NonblockingUnixSeqpacketConn> for OwnedFd
831{
832    fn from(value: NonblockingUnixSeqpacketConn) -> Self 
833    {
834        return value.fd;
835    }
836}
837
838impl FromRawFd for NonblockingUnixSeqpacketConn
839{
840    unsafe 
841    fn from_raw_fd(fd: RawFd) -> Self 
842    {
843        return 
844            Self{ fd: unsafe { OwnedFd::from_raw_fd(fd) } };
845    }
846}
847
848impl AsRawFd for NonblockingUnixSeqpacketConn
849{
850    fn as_raw_fd(&self) -> RawFd 
851    {
852        self.fd.as_raw_fd()
853    }
854}
855impl IntoRawFd for NonblockingUnixSeqpacketConn
856{
857    fn into_raw_fd(self) -> RawFd 
858    {
859        self.fd.into_raw_fd()
860    }
861}
862
863impl AsFd for NonblockingUnixSeqpacketConn
864{
865    fn as_fd(&self) -> BorrowedFd<'_> 
866    {
867        self.fd.as_fd()
868    }
869}
870
871
872// can't Deref<Target=UnixSeqpacketConn> because that would include try_clone()
873// and later set_(read|write)_timeout()
874impl NonblockingUnixSeqpacketConn 
875{
876    /// Connects to an unix seqpacket server listening at `path`.
877    ///
878    /// This is a wrapper around [`connect_unix_addr()`](#method.connect_unix_addr)
879    /// for convenience and compatibility with std.
880    pub 
881    fn connect<P: AsRef<Path>>(path: P) -> Result<Self, io::Error> 
882    {
883        let addr = UnixSocketAddr::from_path(&path)?;
884
885        return Self::connect_unix_addr(&addr);
886    }
887
888    /// Connects to an unix seqpacket server listening at `addr`.
889    pub 
890    fn connect_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error> 
891    {
892        let socket = Socket::<SocketSeqPkt>::new(true)?;
893        socket.set_unix_addr(SetAddr::PEER, addr)?;
894        
895        return Ok(NonblockingUnixSeqpacketConn { fd: socket.into() });
896    }
897
898    /// Binds to an address before connecting to a listening seqpacket socket.
899    pub 
900    fn connect_from_to_unix_addr(from: &UnixSocketAddr,  to: &UnixSocketAddr) -> Result<Self, io::Error> 
901    {
902        let socket = Socket::<SocketSeqPkt>::new(true)?;
903        socket.set_unix_addr(SetAddr::LOCAL, from)?;
904        socket.set_unix_addr(SetAddr::PEER, to)?;
905        
906        return Ok(NonblockingUnixSeqpacketConn { fd: socket.into() });
907    }
908
909    /// Creates a pair of nonblocking unix-domain seqpacket conneections connected to each other.
910    ///
911    /// # Examples
912    ///
913    #[cfg_attr(not(target_vendor="apple"), doc="```")]
914    #[cfg_attr(target_vendor="apple", doc="```no_run")]
915    /// let (a, b) = uds_fork::nonblocking::UnixSeqpacketConn::pair().unwrap();
916    /// assert!(a.local_unix_addr().unwrap().is_unnamed());
917    /// assert!(b.local_unix_addr().unwrap().is_unnamed());
918    /// assert_eq!(b.recv(&mut[0; 20]).unwrap_err().kind(), std::io::ErrorKind::WouldBlock);
919    /// a.send(b"hello").unwrap();
920    /// assert_eq!(b.recv(&mut[0; 20]).unwrap(), 5);
921    /// ```
922    pub 
923    fn pair() -> Result<(Self, Self), io::Error> 
924    {
925        let pair = Socket::<SocketSeqPkt>::pair(true)?;
926                
927        return Ok(
928            (
929                NonblockingUnixSeqpacketConn { fd: pair.0.into() }, 
930                NonblockingUnixSeqpacketConn { fd: pair.1.into() }
931            )
932        );
933    }
934
935    /// Returns the address of this side of the connection.
936    pub 
937    fn local_unix_addr(&self) -> Result<UnixSocketAddr, io::Error> 
938    {
939        get_unix_addr(&self, GetAddr::LOCAL)
940    }
941    
942    /// Returns the address of the other side of the connection.
943    pub 
944    fn peer_unix_addr(&self) -> Result<UnixSocketAddr, io::Error> 
945    {
946        get_unix_addr(&self, GetAddr::PEER)
947    }
948
949    /// Returns information about the process of the peer when the connection was established.
950    ///
951    /// See documentation of the returned type for details.
952    pub 
953    fn initial_peer_credentials(&self) -> Result<ConnCredentials, io::Error> 
954    {
955        peer_credentials(&self)
956    }
957
958    /// Returns the SELinux security context of the process that created the other
959    /// end of this connection.
960    ///
961    /// Will return an error on other operating systems than Linux or Android,
962    /// and also if running inside kubernetes.
963    /// On success the number of bytes used is returned. (like `Read`)
964    ///
965    /// The default security context is `unconfined`, without any trailing NUL.  
966    /// A buffor of 50 bytes is probably always big enough.
967    pub 
968    fn initial_peer_selinux_context(&self,  buf: &mut[u8]) -> Result<usize, io::Error> 
969    {
970        selinux_context(&self, buf)
971    }
972
973    /// Sends a packet to the peer.
974    pub 
975    fn send(&self,  packet: &[u8]) -> Result<usize, io::Error> 
976    {
977        let ptr = packet.as_ptr() as *const c_void;
978        let flags = MSG_NOSIGNAL | MSG_EOR;
979        let sent = cvt_r!(unsafe { send(self.fd.as_raw_fd(), ptr, packet.len(), flags) })?;
980        
981        return Ok(sent as usize);
982    }
983
984    pub 
985    fn send_flags(&self,  packet: &[u8], flags: i32) -> Result<usize, io::Error> 
986    {
987        let ptr = packet.as_ptr() as *const c_void;
988        let sent = cvt_r!(unsafe { send(self.fd.as_raw_fd(), ptr, packet.len(), flags) })?;
989        
990        return Ok(sent as usize);
991    }
992
993    /// Receives a packet from the peer.
994    pub 
995    fn recv(&self,  buffer: &mut[u8]) -> Result<usize, io::Error> 
996    {
997        let ptr = buffer.as_ptr() as *mut c_void;
998        let received = cvt_r!(unsafe { recv(self.fd.as_raw_fd(), ptr, buffer.len(), MSG_NOSIGNAL) })?;
999        
1000        return Ok(received as usize);
1001    }
1002    /// Sends a packet assembled from multiple byte slices.
1003    pub fn send_vectored(&self,  slices: &[IoSlice]) -> Result<usize, io::Error> 
1004    {
1005        // Can't use writev() because we need to pass flags,
1006        // and the flags accepted by pwritev2() aren't the one we need to pass.
1007        send_ancillary(&self, None, MSG_EOR, slices, Vec::new(), None)
1008    }
1009
1010    /// Reads a packet into multiple buffers.
1011    ///
1012    /// The returned `bool` indicates whether the packet was truncated due to
1013    /// too short buffers.
1014    pub 
1015    fn recv_vectored(&self,  buffers: &mut[IoSliceMut]) -> Result<(usize, bool), io::Error> 
1016    {
1017        recv_ancillary(&self, None, 0, buffers, &mut[])
1018            .map(|(bytes, ancillary)| (bytes, ancillary.message_truncated()) )
1019    }
1020
1021    /// Sends a packet with associated file descriptors.
1022    pub 
1023    fn send_fds(&self,  bytes: &[u8],  fds: Vec<OwnedFd>) -> Result<usize, io::Error> 
1024    {
1025        send_ancillary(&self, None, MSG_EOR, &[IoSlice::new(bytes)], fds, None)
1026    }
1027
1028    /// Receives a packet and associated file descriptors.
1029    pub 
1030    fn recv_fds(&self, byte_buffer: &mut[u8], fd_buffer: &mut Vec<OwnedFd>) -> Result<(usize, bool, usize), io::Error> 
1031    {
1032        recv_fds(&self, None, &mut[IoSliceMut::new(byte_buffer)], Some(fd_buffer))
1033    }
1034
1035    /// Receives a packet without removing it from the incoming queue.
1036    ///
1037    /// # Examples
1038    ///
1039    #[cfg_attr(not(target_vendor="apple"), doc="```")]
1040    #[cfg_attr(target_vendor="apple", doc="```no_run")]
1041    /// # use std::io::ErrorKind::*;
1042    /// let (a, b) = uds_fork::nonblocking::UnixSeqpacketConn::pair().unwrap();
1043    /// let mut buf = [0u8; 10];
1044    /// assert_eq!(b.peek(&mut buf).unwrap_err().kind(), WouldBlock);
1045    /// a.send(b"hello").unwrap();
1046    /// assert_eq!(b.peek(&mut buf).unwrap(), 5);
1047    /// assert_eq!(&buf[..5], b"hello");
1048    /// assert_eq!(b.recv(&mut buf).unwrap(), 5);
1049    /// assert_eq!(&buf[..5], b"hello");
1050    /// assert_eq!(b.peek(&mut buf).unwrap_err().kind(), WouldBlock);
1051    /// ```
1052    pub 
1053    fn peek(&self,  buffer: &mut[u8]) -> Result<usize, io::Error> 
1054    {
1055        let ptr = buffer.as_ptr() as *mut c_void;
1056        let flags = MSG_NOSIGNAL | MSG_PEEK;
1057        let received = cvt_r!(unsafe { recv(self.fd.as_raw_fd(), ptr, buffer.len(), flags) })?;
1058        
1059        return Ok(received as usize);
1060    }
1061
1062    /// Receives a packet without removing it from the incoming queue.
1063    ///
1064    /// The returned `bool` indicates whether the packet was truncated due to
1065    /// the combined buffers being too small.
1066    pub 
1067    fn peek_vectored(&self,  buffers: &mut[IoSliceMut]) -> Result<(usize, bool), io::Error> 
1068    {
1069        recv_ancillary(&self, None, MSG_PEEK, buffers, &mut[])
1070            .map(|(bytes, ancillary)| (bytes, ancillary.message_truncated()) )
1071    }
1072
1073    /// Returns the value of the `SO_ERROR` option.
1074    ///
1075    /// This might only provide errors generated from nonblocking `connect()`s,
1076    /// which this library doesn't support. It is therefore unlikely to be 
1077    /// useful, but is provided for parity with `mio`s `UnixStream`.
1078    ///
1079    /// # Examples
1080    ///
1081    #[cfg_attr(not(target_vendor="apple"), doc="```")]
1082    #[cfg_attr(target_vendor="apple", doc="```no_run")]
1083    /// let (a, _b) = uds_fork::nonblocking::UnixSeqpacketConn::pair().unwrap();
1084    ///
1085    /// assert!(a.recv(&mut[0u8; 1024]).is_err());
1086    /// assert!(a.take_error().unwrap().is_none());
1087    /// ```
1088    pub 
1089    fn take_error(&self) -> Result<Option<io::Error>, io::Error> 
1090    {
1091        take_error(&self)
1092    }
1093
1094
1095    /// Creates a new file descriptor also pointing to this side of this connection.
1096    ///
1097    /// # Examples
1098    ///
1099    #[cfg_attr(not(target_vendor="apple"), doc="```")]
1100    #[cfg_attr(target_vendor="apple", doc="```no_run")]
1101    /// # use uds_fork::nonblocking::UnixSeqpacketConn;
1102    /// # use std::io::ErrorKind;
1103    /// #
1104    /// let (a1, b) = UnixSeqpacketConn::pair().unwrap();
1105    /// b.send(b"first come first serve").unwrap();
1106    /// let a2 = a1.try_clone().unwrap();
1107    /// a2.recv(&mut[0u8; 10]).unwrap();
1108    /// assert_eq!(a1.recv(&mut[0u8; 10]).unwrap_err().kind(), ErrorKind::WouldBlock);
1109    ///
1110    /// b.send(b"more").unwrap();
1111    /// a1.recv(&mut[0u8; 10]).unwrap();
1112    /// assert_eq!(a2.recv(&mut[0u8; 10]).unwrap_err().kind(), ErrorKind::WouldBlock);
1113    /// ```
1114    pub 
1115    fn try_clone(&self) -> Result<Self, io::Error> 
1116    {
1117        let cloned = Socket::<SocketSeqPkt>::try_clone_from(&self)?;
1118        // nonblockingness is shared and therefore inherited
1119        
1120        return Ok(NonblockingUnixSeqpacketConn { fd: cloned.into() });
1121    }
1122
1123    /// Shuts down the read, write, or both halves of this connection.
1124    pub 
1125    fn shutdown(&self, how: Shutdown) -> io::Result<()> 
1126    {
1127        let how = 
1128            match how 
1129            {
1130                Shutdown::Read => libc::SHUT_RD,
1131                Shutdown::Write => libc::SHUT_WR,
1132                Shutdown::Both => libc::SHUT_RDWR,
1133            };
1134
1135        unsafe { cvt!(libc::shutdown(self.as_raw_fd(), how)) }?;
1136        
1137        return Ok(());
1138    }
1139}
1140
1141
1142/// A non-blocking unix domain listener for sequential-packet connections.
1143///
1144/// Differs from [`UnixSeqpacketListener`](../struct.UnixSeqpacketListener.html)
1145/// in that [`accept()`](struct.NonblockingUnixSeqpacketListener.html#method.accept)
1146/// returns non-blocking [connection sockets](struct.NonblockingUnixSeqpacketConn.html)
1147/// and doesn't block if no client `connect()`ions are pending.
1148///
1149/// This type can be used with mio if the `mio_08` feature is enabled:
1150///
1151/// ```toml
1152/// uds = { version = "x.y", features=["mio_08"] }
1153/// ```
1154///
1155/// # Examples
1156///
1157#[cfg_attr(not(target_vendor="apple"), doc="```")]
1158#[cfg_attr(target_vendor="apple", doc="```no_run")]
1159/// use uds_fork::nonblocking::{UnixSeqpacketListener, UnixSeqpacketConn};
1160/// use std::io::ErrorKind;
1161///
1162/// # let _ = std::fs::remove_file("/tmp/nonblocking_seqpacket_listener.socket");
1163/// let listener = UnixSeqpacketListener::bind("/tmp/nonblocking_seqpacket_listener.socket")
1164///     .expect("Cannot create nonblocking seqpacket listener");
1165///
1166/// // doesn't block if no connections are waiting:
1167/// assert_eq!(listener.accept_unix_addr().unwrap_err().kind(), ErrorKind::WouldBlock);
1168///
1169/// // returned connections are nonblocking:
1170/// let _client = UnixSeqpacketConn::connect("/tmp/nonblocking_seqpacket_listener.socket").unwrap();
1171/// let (conn, _addr) = listener.accept_unix_addr().unwrap();
1172/// assert_eq!(conn.recv(&mut[0u8; 20]).unwrap_err().kind(), ErrorKind::WouldBlock);
1173/// #
1174/// # std::fs::remove_file("/tmp/nonblocking_seqpacket_listener.socket").unwrap();
1175/// ```
1176#[derive(Debug)]
1177#[repr(transparent)]
1178pub struct NonblockingUnixSeqpacketListener 
1179{
1180    fd: OwnedFd
1181}
1182
1183impl FromRawFd for NonblockingUnixSeqpacketListener
1184{
1185    unsafe 
1186    fn from_raw_fd(fd: RawFd) -> Self 
1187    {
1188        return 
1189            Self{ fd: unsafe { OwnedFd::from_raw_fd(fd) } };
1190    }
1191}
1192
1193impl AsRawFd for NonblockingUnixSeqpacketListener
1194{
1195    fn as_raw_fd(&self) -> RawFd 
1196    {
1197        self.fd.as_raw_fd()
1198    }
1199}
1200
1201impl IntoRawFd for NonblockingUnixSeqpacketListener
1202{
1203    fn into_raw_fd(self) -> RawFd 
1204    {
1205        self.fd.into_raw_fd()
1206    }
1207}
1208
1209impl AsFd for NonblockingUnixSeqpacketListener
1210{
1211    fn as_fd(&self) -> BorrowedFd<'_> 
1212    {
1213        self.fd.as_fd()
1214    }
1215}
1216
1217impl NonblockingUnixSeqpacketListener 
1218{
1219    /// Creates a socket that listens for seqpacket connections on the specified socket file.
1220    pub 
1221    fn bind<P: AsRef<Path>>(path: P) -> Result<Self, io::Error> 
1222    {
1223        let addr = UnixSocketAddr::from_path(&path)?;
1224
1225        return Self::bind_unix_addr(&addr);
1226    }
1227
1228    /// Creates a socket that listens for seqpacket connections on the specified address.
1229    pub 
1230    fn bind_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error> 
1231    {
1232        let socket = Socket::<SocketSeqPkt>::new(true)?;
1233        socket.set_unix_addr(SetAddr::LOCAL, addr)?;
1234        socket.start_listening()?;
1235
1236        return Ok(NonblockingUnixSeqpacketListener { fd: socket.into() });
1237    }
1238
1239    /// Returns the address this listener was bound to.
1240    pub 
1241    fn local_unix_addr(&self) -> Result<UnixSocketAddr, io::Error> 
1242    {
1243        get_unix_addr(&self, GetAddr::LOCAL)
1244    }
1245
1246    /// Accepts a non-blocking connection, non-blockingly.
1247    ///
1248    /// # Examples
1249    ///
1250    /// Doesn't block if no connections are waiting:
1251    ///
1252    #[cfg_attr(not(target_vendor="apple"), doc="```")]
1253    #[cfg_attr(target_vendor="apple", doc="```no_run")]
1254    /// # use uds_fork::nonblocking::UnixSeqpacketListener;
1255    /// # use std::io::ErrorKind;
1256    /// #
1257    /// let _ = std::fs::remove_file("/tmp/nonblocking_seqpacket_listener.socket");
1258    /// let listener = UnixSeqpacketListener::bind("/tmp/nonblocking_seqpacket_listener.socket")
1259    ///     .expect("Cannot create nonblocking seqpacket listener");
1260    /// assert_eq!(listener.accept_unix_addr().unwrap_err().kind(), ErrorKind::WouldBlock);
1261    /// std::fs::remove_file("/tmp/nonblocking_seqpacket_listener.socket").unwrap();
1262    /// ```
1263    pub 
1264    fn accept_unix_addr(&self) -> Result<(NonblockingUnixSeqpacketConn, UnixSocketAddr), io::Error> 
1265    {
1266        let (socket, addr) = Socket::<SocketSeqPkt>::accept_from(&self, true)?;
1267        let conn = NonblockingUnixSeqpacketConn { fd: socket.into() };
1268        
1269        return Ok((conn, addr));
1270    }
1271
1272    /// Returns the value of the `SO_ERROR` option.
1273    ///
1274    /// This might never produce any errors for listeners. It is therefore
1275    /// unlikely to be useful, but is provided for parity with `mio`s
1276    /// `UnixListener`.
1277    ///
1278    /// # Examples
1279    ///
1280    #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
1281    #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
1282    /// let listener = uds_fork::nonblocking::UnixSeqpacketListener::bind_unix_addr(
1283    ///     &uds_fork::UnixSocketAddr::new("@nonblocking_take_error").unwrap()
1284    /// ).unwrap();
1285    ///
1286    /// assert!(listener.accept_unix_addr().is_err());
1287    /// assert!(listener.take_error().unwrap().is_none());
1288    /// ```
1289    pub 
1290    fn take_error(&self) -> Result<Option<io::Error>, io::Error> 
1291    {
1292        take_error(&self)
1293    }
1294
1295    /// Creates a new file descriptor listening for the same connections.
1296    pub 
1297    fn try_clone(&self) -> Result<Self, io::Error> 
1298    {
1299        let cloned = Socket::<SocketSeqPkt>::try_clone_from(&self)?;
1300        // nonblockingness is shared and therefore inherited
1301        
1302        return Ok(NonblockingUnixSeqpacketListener { fd: cloned.into() });
1303    }
1304}