uds_fork/
seqpacket.rs

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