Skip to main content

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}, net::Shutdown, ops::{Deref, DerefMut}, os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}, path::Path, time::Duration
10};
11
12use libc::{MSG_EOR, MSG_PEEK, c_void, send, recv};
13
14//use crate::addr::*;
15use crate::{UnixSocketAddr, helpers::*};
16use crate::ancillary::*;
17use crate::credentials::*;
18
19/// An unix domain sequential packet connection.
20///
21/// Sequential-packet connections have an interface similar to streams,
22/// but behave more like connected datagram sockets.
23///
24/// They have guaranteed in-order and reliable delivery,
25/// which unix datagrams technically doesn't.
26///
27/// # Operating system support
28///
29/// Sequential-packet sockets are supported by Linux, FreeBSD, NetBSD
30/// and Illumos, but not by for example macOS or OpenBSD.
31///
32/// # Zero-length packets
33///
34/// ... are best avoided:  
35/// On Linux and FreeBSD zero-length packets can be sent and received,
36/// but there is no way to distinguish receiving one from reaching
37/// end of connection unless the packet has an ancillary payload.
38/// Also beware of trying to receive with a zero-length buffer,
39/// as that will on FreeBSD (and probably other BSDs with seqpacket sockets)
40/// always succeed even if there is no packet waiting.
41///
42/// Illumos and Solaris doesn't support receiving zero-length packets at all:
43/// writes succeed but recv() will block.
44/// 
45/// # Registering with Xio (xio-rs) a feature = "xio-rs"
46/// 
47/// A `XioEventPipe` is implemented on this function. During initial registration
48/// an attempt set `nonblocking` mode is performed during initial registration.
49/// 
50/// See examples below.
51/// 
52/// # Registering with Mio (mio) a feature = "mio"
53/// 
54/// A `Source` is implemented on the instance.During initial registration
55/// an attempt set `nonblocking` mode is performed during initial registration.
56///
57/// # Examples
58///
59/// What is sent separately is received separately:
60///
61#[cfg_attr(not(target_vendor="apple"), doc="```")]
62#[cfg_attr(target_vendor="apple", doc="```no_run")]
63/// let (a, b) = uds_fork::UnixSeqpacketConn::pair().expect("Cannot create seqpacket pair");
64///
65/// a.send(b"first").unwrap();
66/// a.send(b"second").unwrap();
67///
68/// let mut buffer_big_enough_for_both = [0; 20];
69/// let len = b.recv(&mut buffer_big_enough_for_both).unwrap();
70/// assert_eq!(&buffer_big_enough_for_both[..len], b"first");
71/// let len = b.recv(&mut buffer_big_enough_for_both).unwrap();
72/// assert_eq!(&buffer_big_enough_for_both[..len], b"second");
73/// ```
74///
75/// Connect to a listener on a socket file and write to it:
76///
77#[cfg_attr(not(target_vendor="apple"), doc="```")]
78#[cfg_attr(target_vendor="apple", doc="```no_run")]
79/// use uds_fork::{UnixSeqpacketListener, UnixSeqpacketConn};
80///
81/// let file_path = "/tmp/seqpacket.socket";
82/// let _ = std::fs::remove_file(file_path); // pre-emptively delete just in case
83/// let listener = UnixSeqpacketListener::bind(file_path)
84///     .expect("create seqpacket listener");
85/// let conn = UnixSeqpacketConn::connect(file_path)
86///     .expect("connect to seqpacket listener");
87///
88/// let message = "Hello, listener";
89/// let sent = conn.send(message.as_bytes()).unwrap();
90/// assert_eq!(sent, message.len());
91///
92/// std::fs::remove_file(file_path).unwrap(); // clean up after ourselves
93/// ```
94///
95/// Connect to a listener on an abstract address:
96///
97#[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
98#[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
99/// use uds_fork::{UnixSeqpacketListener, UnixSeqpacketConn, UnixSocketAddr};
100///
101/// let addr = UnixSocketAddr::new("@seqpacket example").unwrap();
102/// let listener = UnixSeqpacketListener::bind_unix_addr(&addr)
103///     .expect("create abstract seqpacket listener");
104/// let _client = UnixSeqpacketConn::connect_unix_addr(&addr)
105///     .expect("connect to abstract seqpacket listener");
106/// let (_server, _addr) = listener.accept_unix_addr().unwrap();
107/// ```
108/// 
109/// ### Xio
110/// 
111/// ```ignore
112/// let (mut a, b) = UnixSeqpacketConn::pair().unwrap();
113/// 
114/// let mut reg = XioPollRegistry::<ESS>::new().unwrap();
115/// let mut event_buf = XioPollRegistry::<ESS>::allocate_events(128.try_into().unwrap());
116/// 
117/// // either
118/// let a_wrapped =
119///     reg.get_registry()
120///         .en_register_wrap(a, XioEventUid::manual(1), XioChannel::INPUT)
121///         .unwrap();
122///  
123/// // or 
124///     reg.get_registry()
125///         .en_register&mut a, XioEventUid::manual(1), XioChannel::INPUT)
126///         .unwrap();
127/// 
128/// // so depending on the method, use either:
129/// a_wrapped.inner();
130/// 
131/// // or continue using a directly
132/// ```
133/// 
134/// ### Mio:
135/// 
136/// ```ignore
137/// let (mut a, b) = UnixSeqpacketConn::pair().unwrap();
138/// 
139/// let mut poll = Poll::new().expect("create mio poll");
140/// let mut events = Events::with_capacity(10);
141/// 
142/// poll.registry()
143///     .register(&mut a, Token(1), Interest::READABLE)
144///     .unwrap();
145/// // ...
146/// ```
147#[derive(Debug)]
148#[repr(transparent)]
149pub struct UnixSeqpacketConn 
150{
151    fd: OwnedFd,
152}
153
154impl From<OwnedFd> for UnixSeqpacketConn
155{
156    fn from(ofd: OwnedFd) -> Self 
157    {
158        let sa_fam = get_socket_family(&ofd).unwrap();
159        let sa_type = get_socket_type(&ofd).unwrap() & 0x00000FFF;
160
161        if sa_fam as i32 != libc::AF_UNIX || sa_type != libc::SOCK_SEQPACKET
162        {
163            panic!("assertion trap: provided FD is not AF_UNIX & SOCK_SEQPACKET, {} {}", 
164                sa_fam, sa_type);
165        }
166
167        return UnixSeqpacketConn{ fd: ofd };
168    }
169}
170
171impl From<UnixSeqpacketConn> for OwnedFd
172{
173    fn from(value: UnixSeqpacketConn) -> Self 
174    {
175        return value.fd;
176    }
177}
178
179impl FromRawFd for UnixSeqpacketConn
180{
181    unsafe 
182    fn from_raw_fd(fd: RawFd) -> Self 
183    {
184        UnixSeqpacketConn::from( unsafe { OwnedFd::from_raw_fd(fd) } )
185    }
186}
187
188impl AsRawFd for UnixSeqpacketConn
189{
190    fn as_raw_fd(&self) -> RawFd 
191    {
192        self.fd.as_raw_fd()
193    }
194}
195impl IntoRawFd for UnixSeqpacketConn
196{
197    fn into_raw_fd(self) -> RawFd 
198    {
199        self.fd.into_raw_fd()
200    }
201}
202
203impl AsFd for UnixSeqpacketConn
204{
205    fn as_fd(&self) -> BorrowedFd<'_> 
206    {
207        self.fd.as_fd()
208    }
209}
210
211#[cfg(feature = "mio")]
212pub mod mio_conn_enabled
213{
214    use mio::{event::Source, unix::SourceFd};
215    use super::*;
216
217    impl Source for UnixSeqpacketConn
218    {
219        fn register(
220            &mut self,
221            registry: &mio::Registry,
222            token: mio::Token,
223            interests: mio::Interest,
224        ) -> io::Result<()> 
225        {
226            self.set_nonblocking(true)?;
227
228            SourceFd(&self.fd.as_raw_fd()).register(registry, token, interests)
229        }
230    
231        fn reregister(
232            &mut self,
233            registry: &mio::Registry,
234            token: mio::Token,
235            interests: mio::Interest,
236        ) -> io::Result<()> 
237        {
238            SourceFd(&self.fd.as_raw_fd()).reregister(registry, token, interests)
239        }
240    
241        fn deregister(&mut self, registry: &mio::Registry) -> io::Result<()> 
242        {
243            SourceFd(&self.fd.as_raw_fd()).deregister(registry)
244        }
245    }
246}
247
248#[cfg(feature = "xio-rs")]
249pub mod xio_conn_enabled
250{
251    use xio_rs::{EsInterfaceRegistry, XioChannel, XioEventPipe, XioEventUid, XioResult, event_registry::XioRegistry};
252
253    use crate::UnixSeqpacketConn;
254
255    impl<ESSR: EsInterfaceRegistry> XioEventPipe<ESSR, Self> for UnixSeqpacketConn
256    {
257        fn connect_event_pipe(&mut self, ess: &XioRegistry<ESSR>, ev_uid: XioEventUid, channel: XioChannel) -> XioResult<()> 
258        {
259            self.set_nonblocking(true)?;
260
261            ess.get_ev_sys().en_register(&self.fd, ev_uid, channel)
262        }
263    
264        fn modify_event_pipe(&mut self, ess: &XioRegistry<ESSR>, ev_uid: XioEventUid, channel: XioChannel) -> XioResult<()> 
265        {
266            ess.get_ev_sys().re_register(&self.fd, ev_uid, channel)
267        }
268    
269        fn disconnect_event_pipe(&mut self, ess: &XioRegistry<ESSR>) -> XioResult<()> 
270        {
271            ess.get_ev_sys().de_register(&self.fd)
272        }
273    }
274}
275
276impl UnixSeqpacketConn 
277{
278    /// Connects to an unix seqpacket server listening at `path`.
279    ///
280    /// This is a wrapper around [`connect_unix_addr()`](#method.connect_unix_addr)
281    /// for convenience and compatibility with std.
282    pub 
283    fn connect<P: AsRef<Path>>(path: P) -> Result<Self, io::Error> 
284    {
285        let addr = UnixSocketAddr::from_path(&path)?;
286
287        return Self::connect_unix_addr(&addr);
288    }
289
290    /// Connects to an unix seqpacket server listening at `addr`.
291    pub 
292    fn connect_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error> 
293    {
294        let socket = Socket::<SocketSeqPkt>::new(false)?;
295        socket.set_unix_peer_addr(addr)?;
296        
297        return Ok(UnixSeqpacketConn { fd: socket.into() });
298    }
299    
300    /// Binds to an address before connecting to a listening seqpacet socket.
301    pub 
302    fn connect_from_to_unix_addr(from: &UnixSocketAddr,  to: &UnixSocketAddr) -> Result<Self, io::Error> 
303    {
304        let socket = Socket::<SocketSeqPkt>::new(false)?;
305        socket.set_unix_local_addr(from)?;
306        socket.set_unix_peer_addr(to)?;
307        
308        return Ok(UnixSeqpacketConn{ fd: socket.into() });
309    }
310
311    /// Creates a pair of unix-domain seqpacket conneections connected to each other.
312    ///
313    /// # Examples
314    ///
315    #[cfg_attr(not(target_vendor="apple"), doc="```")]
316    #[cfg_attr(target_vendor="apple", doc="```no_run")]
317    /// let (a, b) = uds_fork::UnixSeqpacketConn::pair().unwrap();
318    /// assert!(a.local_unix_addr().unwrap().is_unnamed());
319    /// assert!(b.local_unix_addr().unwrap().is_unnamed());
320    ///
321    /// a.send(b"hello").unwrap();
322    /// b.recv(&mut[0; 20]).unwrap();
323    /// ```
324    pub 
325    fn pair() -> Result<(Self, Self), io::Error> 
326    {
327        let pair = Socket::<SocketSeqPkt>::pair(false)?;
328        
329        return Ok(
330            (
331                UnixSeqpacketConn { fd: pair.0.into() },
332                UnixSeqpacketConn { fd: pair.1.into() }
333            )
334        );
335    }
336
337    /// Returns the address of this side of the connection.
338    pub 
339    fn local_unix_addr(&self) -> Result<UnixSocketAddr, io::Error> 
340    {
341        get_unix_local_addr(&self)
342    }
343
344    /// Returns the address of the other side of the connection.
345    pub 
346    fn peer_unix_addr(&self) -> Result<UnixSocketAddr, io::Error> 
347    {
348        get_unix_peer_addr(&self)
349    }
350
351    /// Returns information about the process of the peer when the connection was established.
352    ///
353    /// See documentation of the returned type for details.
354    pub 
355    fn initial_peer_credentials(&self) -> Result<ConnCredentials, io::Error> 
356    {
357        peer_credentials(&self)
358    }
359
360    /// Returns the SELinux security context of the process that created the other
361    /// end of this connection.
362    ///
363    /// Will return an error on other operating systems than Linux or Android,
364    /// and also if running inside kubernetes.
365    /// On success the number of bytes used is returned. (like `Read`)
366    ///
367    /// The default security context is `unconfined`, without any trailing NUL.  
368    /// A buffor of 50 bytes is probably always big enough.
369    pub 
370    fn initial_peer_selinux_context(&self,  buf: &mut[u8]) -> Result<usize, io::Error> 
371    {
372        selinux_context(&self, buf)
373    }
374
375
376    /// Sends a packet to the peer.
377    pub 
378    fn send(&self, packet: &[u8]) -> Result<usize, io::Error> 
379    {
380        let ptr = packet.as_ptr() as *const c_void;
381        let flags = MSG_NOSIGNAL | MSG_EOR;
382        let sent = cvt_r!(unsafe { send(self.fd.as_raw_fd(), ptr, packet.len(), flags) })?;
383        
384        
385        return Ok(sent as usize);
386    }
387
388    /// Sends a packet to the peer.
389    pub 
390    fn send_flags(&self,  packet: &[u8], flags: i32) -> Result<usize, io::Error> 
391    {
392        let ptr = packet.as_ptr() as *const c_void;
393        let sent = cvt_r!(unsafe { send(self.fd.as_raw_fd(), ptr, packet.len(), flags) })?;
394        
395        return Ok(sent as usize);
396    }
397
398    /// Receives a packet from the peer.
399    pub 
400    fn recv(&self, buffer: &mut[u8]) -> Result<usize, io::Error> 
401    {
402        let ptr = buffer.as_ptr() as *mut c_void;
403        let received = cvt_r!(unsafe { recv(self.fd.as_raw_fd(), ptr, buffer.len(), MSG_NOSIGNAL) })?;
404        
405        return Ok(received as usize);
406    }
407
408    /// Sends a packet assembled from multiple byte slices.
409    pub 
410    fn send_vectored(&self,  slices: &[IoSlice]) -> Result<usize, io::Error> 
411    {
412        // Can't use writev() because we need to pass flags,
413        // and the flags accepted by pwritev2() aren't the one we need to pass.
414        send_ancillary(&self, None, MSG_EOR, slices, Vec::new(), None)
415    }
416    /// Reads a packet into multiple buffers.
417    ///
418    /// The returned `bool` indicates whether the packet was truncated due to
419    /// too short buffers.
420    pub 
421    fn recv_vectored(&self,  buffers: &mut[IoSliceMut]) -> Result<(usize, bool), io::Error> 
422    {
423        recv_ancillary(&self, None, 0, buffers, &mut[])
424            .map(|(bytes, ancillary)| (bytes, ancillary.message_truncated()) )
425    }
426
427    /// Sends a packet with associated file descriptors.
428    pub 
429    fn send_fds(&self, bytes: &[u8], fds: Vec<OwnedFd>) -> Result<usize, io::Error> 
430    {
431        send_ancillary(&self, None, MSG_EOR, &[IoSlice::new(bytes)], fds, None)
432    }
433
434    /// Receives a packet and associated file descriptors.
435    pub 
436    fn recv_fds(&self, byte_buffer: &mut[u8], fd_buffer: &mut Vec<OwnedFd>) -> Result<(usize, bool, usize), io::Error> 
437    {
438        recv_fds(&self, None, &mut[IoSliceMut::new(byte_buffer)], Some(fd_buffer))
439    }
440
441    /// Receives a packet without removing it from the incoming queue.
442    ///
443    /// # Examples
444    ///
445    #[cfg_attr(not(target_vendor="apple"), doc="```")]
446    #[cfg_attr(target_vendor="apple", doc="```no_run")]
447    /// let (a, b) = uds_fork::UnixSeqpacketConn::pair().unwrap();
448    /// a.send(b"hello").unwrap();
449    /// let mut buf = [0u8; 10];
450    /// assert_eq!(b.peek(&mut buf[..1]).unwrap(), 1);
451    /// assert_eq!(&buf[..2], &[b'h', 0]);
452    /// assert_eq!(b.peek(&mut buf).unwrap(), 5);
453    /// assert_eq!(&buf[..5], b"hello");
454    /// assert_eq!(b.recv(&mut buf).unwrap(), 5);
455    /// assert_eq!(&buf[..5], b"hello");
456    /// ```
457    pub 
458    fn peek(&self,  buffer: &mut[u8]) -> Result<usize, io::Error> 
459    {
460        let ptr = buffer.as_ptr() as *mut c_void;
461        let flags = MSG_NOSIGNAL | MSG_PEEK;
462        let received = cvt_r!(unsafe { recv(self.fd.as_raw_fd(), ptr, buffer.len(), flags) })?;
463        
464        return Ok(received as usize);
465    }
466
467    /// Receives a packet without removing it from the incoming queue.
468    ///
469    /// The returned `bool` indicates whether the packet was truncated due to
470    /// the combined buffers being too small.
471    pub 
472    fn peek_vectored(&self,  buffers: &mut[IoSliceMut]) -> Result<(usize, bool), io::Error> 
473    {
474        recv_ancillary(&self, None, MSG_PEEK, buffers, &mut[])
475            .map(|(bytes, ancillary)| (bytes, ancillary.message_truncated()) )
476    }
477
478    /// Returns the value of the `SO_ERROR` option.
479    ///
480    /// This might only provide errors generated from nonblocking `connect()`s,
481    /// which this library doesn't support. It is therefore unlikely to be 
482    /// useful, but is provided for parity with stream counterpart in std.
483    ///
484    /// # Examples
485    ///
486    #[cfg_attr(not(target_vendor="apple"), doc="```")]
487    #[cfg_attr(target_vendor="apple", doc="```no_run")]
488    /// let (a, b) = uds_fork::UnixSeqpacketConn::pair().unwrap();
489    /// drop(b);
490    ///
491    /// assert!(a.send(b"anyone there?").is_err());
492    /// assert!(a.take_error().unwrap().is_none());
493    /// ```
494    pub 
495    fn take_error(&self) -> Result<Option<io::Error>, io::Error> 
496    {
497        take_error(&self)
498    }
499
500
501    /// Creates a new file descriptor also pointing to this side of this connection.
502    ///
503    /// # Examples
504    ///
505    /// Both new and old can send and receive, and share queues:
506    ///
507    #[cfg_attr(not(target_vendor="apple"), doc="```")]
508    #[cfg_attr(target_vendor="apple", doc="```no_run")]
509    /// let (a1, b) = uds_fork::nonblocking::UnixSeqpacketConn::pair().unwrap();
510    /// let a2 = a1.try_clone().unwrap();
511    ///
512    /// a1.send(b"first").unwrap();
513    /// a2.send(b"second").unwrap();
514    ///
515    /// let mut buf = [0u8; 20];
516    /// let len = b.recv(&mut buf).unwrap();
517    /// assert_eq!(&buf[..len], b"first");
518    /// b.send(b"hello first").unwrap();
519    /// let len = b.recv(&mut buf).unwrap();
520    /// assert_eq!(&buf[..len], b"second");
521    /// b.send(b"hello second").unwrap();
522    ///
523    /// let len = a2.recv(&mut buf).unwrap();
524    /// assert_eq!(&buf[..len], b"hello first");
525    /// let len = a1.recv(&mut buf).unwrap();
526    /// assert_eq!(&buf[..len], b"hello second");
527    /// ```
528    ///
529    /// Clone can still be used after the first one has been closed:
530    ///
531    #[cfg_attr(not(target_vendor="apple"), doc="```")]
532    #[cfg_attr(target_vendor="apple", doc="```no_run")]
533    /// let (a, b1) = uds_fork::nonblocking::UnixSeqpacketConn::pair().unwrap();
534    /// a.send(b"hello").unwrap();
535    ///
536    /// let b2 = b1.try_clone().unwrap();
537    /// drop(b1);
538    /// assert_eq!(b2.recv(&mut[0; 10]).unwrap(), "hello".len());
539    /// ```
540    pub 
541    fn try_clone(&self) -> Result<Self, io::Error> 
542    {
543        let cloned = Socket::<SocketSeqPkt>::try_clone_from(self)?;
544
545        return Ok(UnixSeqpacketConn { fd: cloned.into() });
546    }
547
548    /// Sets the read timeout to the duration specified.
549    ///
550    /// If the value specified is `None`, then `recv()` and its variants will
551    /// block indefinitely.  
552    /// An error is returned if the duration is zero.
553    ///
554    /// The duration is rounded to microsecond precission.
555    /// Currently it's rounded down except if that would make it all zero.
556    ///
557    /// # Operating System Support
558    ///
559    /// On Illumos (and pressumably also Solaris) timeouts appears not to work
560    /// for unix domain sockets.
561    ///
562    /// # Examples
563    ///
564    #[cfg_attr(not(any(target_vendor="apple", target_os="illumos", target_os="solaris")), doc="```")]
565    #[cfg_attr(any(target_vendor="apple", target_os="illumos", target_os="solaris"), doc="```no_run")]
566    /// use std::io::ErrorKind;
567    /// use std::time::Duration;
568    /// use uds_fork::UnixSeqpacketConn;
569    ///
570    /// let (a, b) = UnixSeqpacketConn::pair().unwrap();
571    /// a.set_read_timeout(Some(Duration::new(0, 2_000_000))).unwrap();
572    /// let error = a.recv(&mut[0; 1024]).unwrap_err();
573    /// assert_eq!(error.kind(), ErrorKind::WouldBlock);
574    /// ```
575    pub 
576    fn set_read_timeout(&self, timeout: Option<Duration>) -> Result<(), io::Error> 
577    {
578        set_timeout(self.fd.as_fd(), TimeoutDirection::Read, timeout)
579    }
580
581    /// Returns the read timeout of this socket.
582    ///
583    /// `None` is returned if there is no timeout.
584    ///
585    /// Note that subsecond parts might have been be rounded by the OS
586    /// (in addition to the rounding to microsecond in `set_read_timeout()`).
587    ///
588    /// # Examples
589    ///
590    #[cfg_attr(not(any(target_vendor="apple", target_os="illumos", target_os="solaris")), doc="```")]
591    #[cfg_attr(any(target_vendor="apple", target_os="illumos", target_os="solaris"), doc="```no_run")]
592    /// use uds_fork::UnixSeqpacketConn;
593    /// use std::time::Duration;
594    ///
595    /// let timeout = Some(Duration::new(2, 0));
596    /// let conn = UnixSeqpacketConn::pair().unwrap().0;
597    /// conn.set_read_timeout(timeout).unwrap();
598    /// assert_eq!(conn.read_timeout().unwrap(), timeout);
599    /// ```
600    pub 
601    fn read_timeout(&self) -> Result<Option<Duration>, io::Error> 
602    {
603        get_timeout(self.fd.as_fd(), TimeoutDirection::Read)
604    }
605
606    /// Sets the write timeout to the duration specified.
607    ///
608    /// If the value specified is `None`, then `send()` and its variants will
609    /// block indefinitely.  
610    /// An error is returned if the duration is zero.
611    ///
612    /// # Operating System Support
613    ///
614    /// On Illumos (and pressumably also Solaris) timeouts appears not to work
615    /// for unix domain sockets.
616    ///
617    /// # Examples
618    ///
619    #[cfg_attr(not(any(target_vendor="apple", target_os="illumos", target_os="solaris")), doc="```")]
620    #[cfg_attr(any(target_vendor="apple", target_os="illumos", target_os="solaris"), doc="```no_run")]
621    /// # use std::io::ErrorKind;
622    /// # use std::time::Duration;
623    /// # use uds_fork::UnixSeqpacketConn;
624    /// #
625    /// let (conn, _other) = UnixSeqpacketConn::pair().unwrap();
626    /// conn.set_write_timeout(Some(Duration::new(0, 500 * 1000))).unwrap();
627    /// loop {
628    ///     if let Err(e) = conn.send(&[0; 1000]) {
629    ///         assert_eq!(e.kind(), ErrorKind::WouldBlock, "{}", e);
630    ///         break
631    ///     }
632    /// }
633    /// ```
634    pub 
635    fn set_write_timeout(&self,  timeout: Option<Duration>)-> Result<(), io::Error> 
636    {
637        set_timeout(self.fd.as_fd(), TimeoutDirection::Write, timeout)
638    }
639
640    /// Returns the write timeout of this socket.
641    ///
642    /// `None` is returned if there is no timeout.
643    ///
644    /// # Examples
645    ///
646    #[cfg_attr(not(target_vendor="apple"), doc="```")]
647    #[cfg_attr(target_vendor="apple", doc="```no_run")]
648    /// let conn = uds_fork::UnixSeqpacketConn::pair().unwrap().0;
649    /// assert!(conn.write_timeout().unwrap().is_none());
650    /// ```
651    pub 
652    fn write_timeout(&self) -> Result<Option<Duration>, io::Error> 
653    {
654        get_timeout(self.fd.as_fd(), TimeoutDirection::Write)
655    }
656
657    /// Enables or disables nonblocking mode.
658    ///
659    /// Consider using the nonblocking variant of this type instead.
660    /// This method mainly exists for feature parity with std's `UnixStream`.
661    ///
662    /// # Examples
663    ///
664    /// Trying to receive when there are no packets waiting:
665    ///
666    #[cfg_attr(not(target_vendor="apple"), doc="```")]
667    #[cfg_attr(target_vendor="apple", doc="```no_run")]
668    /// # use std::io::ErrorKind;
669    /// # use uds_fork::UnixSeqpacketConn;
670    /// let (a, b) = UnixSeqpacketConn::pair().expect("create seqpacket pair");
671    /// a.set_nonblocking(true).unwrap();
672    /// assert_eq!(a.recv(&mut[0; 20]).unwrap_err().kind(), ErrorKind::WouldBlock);
673    /// ```
674    ///
675    /// Trying to send when the OS buffer for the connection is full:
676    ///
677    #[cfg_attr(not(target_vendor="apple"), doc="```")]
678    #[cfg_attr(target_vendor="apple", doc="```no_run")]
679    /// # use std::io::ErrorKind;
680    /// # use uds_fork::UnixSeqpacketConn;
681    /// let (a, b) = UnixSeqpacketConn::pair().expect("create seqpacket pair");
682    /// a.set_nonblocking(true).unwrap();
683    /// loop {
684    ///     if let Err(error) = a.send(&[b'#'; 1000]) {
685    ///         assert_eq!(error.kind(), ErrorKind::WouldBlock);
686    ///         break;
687    ///     }
688    /// }
689    /// ```
690    pub 
691    fn set_nonblocking(&self,  nonblocking: bool) -> Result<(), io::Error> 
692    {
693        set_nonblocking(&self, nonblocking)
694    }
695
696    /// Shuts down the read, write, or both halves of this connection.
697    pub 
698    fn shutdown(&self, how: Shutdown) -> io::Result<()> 
699    {
700        let how = 
701            match how 
702            {
703                Shutdown::Read => libc::SHUT_RD,
704                Shutdown::Write => libc::SHUT_WR,
705                Shutdown::Both => libc::SHUT_RDWR,
706            };
707
708        unsafe { cvt!(libc::shutdown(self.as_raw_fd(), how)) }?;
709        
710        return Ok(());
711    }
712}
713
714
715/// An unix domain listener for sequential packet connections.
716///
717/// See [`UnixSeqpacketConn`](struct.UnixSeqpacketConn.html) for a description
718/// of this type of connection.
719/// 
720/// # Registering with Xio (xio-rs) a feature = "xio-rs"
721/// 
722/// A `XioEventPipe` is implemented on this function. During initial registration
723/// an attempt set `nonblocking` mode is performed during initial registration.
724/// 
725/// See examples below.
726/// 
727/// # Registering with Mio (mio) a feature = "mio"
728/// 
729/// A `Source` is implemented on the instance.During initial registration
730/// an attempt set `nonblocking` mode is performed during initial registration.
731///
732/// # Examples
733///
734#[cfg_attr(not(target_vendor="apple"), doc="```")]
735#[cfg_attr(target_vendor="apple", doc="```no_run")]
736/// let file_path = "/tmp/seqpacket_listener.socket";
737/// let _ = std::fs::remove_file(file_path);
738/// let listener = uds_fork::UnixSeqpacketListener::bind(file_path)
739///     .expect("Create seqpacket listener");
740/// let _client = uds_fork::UnixSeqpacketConn::connect(file_path).unwrap();
741/// let (conn, _addr) = listener.accept_unix_addr().unwrap();
742/// conn.send(b"Welcome").unwrap();
743/// # std::fs::remove_file(file_path).unwrap();
744/// ```
745/// 
746/// ### Xio
747/// 
748/// ```ignore
749/// let listener = uds_fork::UnixSeqpacketListener::bind(file_path).unwrap();
750/// 
751/// let mut reg = XioPollRegistry::<ESS>::new().unwrap();
752/// let mut event_buf = XioPollRegistry::<ESS>::allocate_events(128.try_into().unwrap());
753/// 
754/// // either
755/// let a_wrapped =
756///     reg.get_registry()
757///         .en_register_wrap(listener, XioEventUid::manual(1), XioChannel::INPUT)
758///         .unwrap();
759///  
760/// // or 
761///     reg.get_registry()
762///         .en_register&mut listener, XioEventUid::manual(1), XioChannel::INPUT)
763///         .unwrap();
764/// 
765/// // so depending on the method, use either:
766/// a_wrapped.inner();
767/// 
768/// // or continue using a directly
769/// ```
770/// 
771/// ### Mio:
772/// 
773/// ```ignore
774/// let listener = uds_fork::UnixSeqpacketListener::bind(file_path).unwrap();
775/// 
776/// let mut poll = Poll::new().expect("create mio poll");
777/// let mut events = Events::with_capacity(10);
778/// 
779/// poll.registry()
780///     .register(&mut listener, Token(1), Interest::READABLE)
781///     .unwrap();
782/// // ...
783/// ``` 
784#[derive(Debug)]
785#[repr(transparent)]
786pub struct UnixSeqpacketListener 
787{
788    fd: OwnedFd
789}
790
791
792impl From<OwnedFd> for UnixSeqpacketListener
793{
794    fn from(ofd: OwnedFd) -> Self 
795    {
796        let sa_fam = get_socket_family(&ofd).unwrap();
797        let sa_type = get_socket_type(&ofd).unwrap() & 0x00000FFF;
798
799        if sa_fam as i32 != libc::AF_UNIX || sa_type != libc::SOCK_SEQPACKET
800        {
801            panic!("assertion trap: provided FD is not AF_UNIX & SOCK_SEQPACKET, {} {}", 
802                sa_fam, sa_type);
803        }
804
805        return UnixSeqpacketListener{ fd: ofd };
806    }
807}
808
809impl From<UnixSeqpacketListener> for OwnedFd
810{
811    fn from(value: UnixSeqpacketListener) -> Self 
812    {
813        return value.fd;
814    }
815}
816
817impl FromRawFd for UnixSeqpacketListener
818{
819    unsafe 
820    fn from_raw_fd(fd: RawFd) -> Self 
821    {
822        UnixSeqpacketListener::from( unsafe { OwnedFd::from_raw_fd(fd) } )
823    }
824}
825
826impl AsRawFd for UnixSeqpacketListener
827{
828    fn as_raw_fd(&self) -> RawFd 
829    {
830        self.fd.as_raw_fd()
831    }
832}
833
834impl IntoRawFd for UnixSeqpacketListener
835{
836    fn into_raw_fd(self) -> RawFd 
837    {
838        self.fd.into_raw_fd()
839    }
840}
841
842impl AsFd for UnixSeqpacketListener
843{
844    fn as_fd(&self) -> BorrowedFd<'_> 
845    {
846        self.fd.as_fd()
847    }
848}
849
850#[cfg(feature = "mio")]
851pub mod mio_listener_enabled
852{
853    use std::{io, os::fd::AsRawFd};
854
855    use mio::{event::Source, unix::SourceFd};
856    use crate::UnixSeqpacketListener;
857
858    impl Source for UnixSeqpacketListener
859    {
860        fn register(
861            &mut self,
862            registry: &mio::Registry,
863            token: mio::Token,
864            interests: mio::Interest,
865        ) -> io::Result<()> 
866        {
867            self.set_nonblocking(true)?;
868            
869            SourceFd(&self.fd.as_raw_fd()).register(registry, token, interests)
870        }
871    
872        fn reregister(
873            &mut self,
874            registry: &mio::Registry,
875            token: mio::Token,
876            interests: mio::Interest,
877        ) -> io::Result<()> 
878        {
879            SourceFd(&self.fd.as_raw_fd()).reregister(registry, token, interests)
880        }
881    
882        fn deregister(&mut self, registry: &mio::Registry) -> io::Result<()> 
883        {
884            SourceFd(&self.fd.as_raw_fd()).deregister(registry)
885        }
886    }
887}
888
889#[cfg(feature = "xio-rs")]
890pub mod xio_listener_enabled
891{
892    use xio_rs::{EsInterfaceRegistry, XioChannel, XioEventPipe, XioEventUid, XioResult, event_registry::XioRegistry};
893
894    use crate::UnixSeqpacketListener;
895
896    impl<ESSR: EsInterfaceRegistry> XioEventPipe<ESSR, Self> for UnixSeqpacketListener
897    {
898        fn connect_event_pipe(&mut self, ess: &XioRegistry<ESSR>, ev_uid: XioEventUid, channel: XioChannel) -> XioResult<()> 
899        {
900            self.set_nonblocking(true)?;
901            
902            ess.get_ev_sys().en_register(&self.fd, ev_uid, channel)
903        }
904    
905        fn modify_event_pipe(&mut self, ess: &XioRegistry<ESSR>, ev_uid: XioEventUid, channel: XioChannel) -> XioResult<()> 
906        {
907            ess.get_ev_sys().re_register(&self.fd, ev_uid, channel)
908        }
909    
910        fn disconnect_event_pipe(&mut self, ess: &XioRegistry<ESSR>) -> XioResult<()> 
911        {
912            ess.get_ev_sys().de_register(&self.fd)
913        }
914    }
915}
916
917impl UnixSeqpacketListener 
918{
919    /// Creates a socket that listens for seqpacket connections on the specified socket file.
920    pub 
921    fn bind<P: AsRef<Path>>(path: P) -> Result<Self, io::Error> 
922    {
923        let addr = UnixSocketAddr::from_path(path.as_ref())?;
924        
925        return Self::bind_unix_addr(&addr);
926    }
927
928    /// Creates a socket that listens for seqpacket connections on the specified address.
929    pub 
930    fn bind_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error> 
931    {
932        let socket = Socket::<SocketSeqPkt>::new(false)?;
933
934        socket.set_unix_local_addr(addr)?;
935        socket.start_listening()?;
936        
937        return Ok(UnixSeqpacketListener { fd: socket.into() });
938    }
939
940    /// Returns the address the socket is listening on.
941    pub 
942    fn local_unix_addr(&self) -> Result<UnixSocketAddr, io::Error> 
943    {
944        get_unix_local_addr(&self)
945    }
946
947    /// Accepts a new incoming connection to this listener.
948    /// 
949    /// Rustdocs: 
950    /// > This function will block the calling thread until a new Unix connection
951    /// > is established. When established, the corresponding [`UnixSeqpacketConn`] and
952    /// > the remote peer's address will be returned.
953    /// 
954    /// [`UnixSeqpacketConn`]: uds_fork::UnixSeqpacketConn
955    ///
956    /// # Examples
957    ///
958    /// ```no_run
959    /// use uds_fork::UnixSeqpacketListener;
960    ///
961    /// fn main() -> std::io::Result<()> 
962    /// {
963    ///     let listener = UnixSeqpacketListener::bind("/path/to/the/socket")?;
964    ///
965    ///     match listener.accept()
966    ///     {
967    ///         Ok((socket, addr)) => 
968    ///             println!("Got a client: {addr:?}"),
969    ///         Err(e) => 
970    ///             println!("accept function failed: {e:?}"),
971    ///     }
972    /// 
973    ///     return Ok(());
974    /// }
975    /// ```
976    #[inline]
977    pub 
978    fn accept(&self)-> Result<(UnixSeqpacketConn, UnixSocketAddr), io::Error> 
979    {
980        self.accept_unix_addr()
981    }
982
983    /// Accepts a new incoming connection to this listener.
984    /// 
985    /// See [Self::accept].
986    pub 
987    fn accept_unix_addr(&self)-> Result<(UnixSeqpacketConn, UnixSocketAddr), io::Error> 
988    {
989        let (socket, addr) = Socket::<SocketSeqPkt>::accept_from(&self, false)?;
990        let conn = UnixSeqpacketConn { fd: socket.into() };
991        
992        return Ok((conn, addr));
993    }
994
995    /// Returns the value of the `SO_ERROR` option.
996    ///
997    /// This might never produce any errors for listeners. It is therefore
998    /// unlikely to be useful, but is provided for parity with
999    /// `std::unix::net::UnixListener`.
1000    pub 
1001    fn take_error(&self) -> Result<Option<io::Error>, io::Error> 
1002    {
1003        take_error(&self)
1004    }
1005
1006    /// Creates a new file descriptor listening for the same connections.
1007    pub 
1008    fn try_clone(&self) -> Result<Self, io::Error> 
1009    {
1010        let cloned = Socket::<SocketSeqPkt>::try_clone_from(&self)?;
1011        
1012        return Ok(UnixSeqpacketListener { fd: cloned.into() });
1013    }
1014
1015    /// Sets a maximum duration to wait in a single `accept()` on this socket.
1016    ///
1017    /// `None` disables a previously set timeout.
1018    /// An error is returned if the duration is zero.
1019    ///
1020    /// # Operating System Support
1021    ///
1022    /// Only Linux appers to apply timeouts to `accept()`.  
1023    /// On macOS, FreeBSD and NetBSD, timeouts are silently ignored.  
1024    /// On Illumos setting timeouts for all unix domain sockets silently fails.
1025    ///
1026    /// On OSes where timeouts are known to not work, this function will
1027    /// return an error even if setting the timeout didn't fail.
1028    ///
1029    /// # Examples
1030    ///
1031    #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
1032    #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
1033    /// # use uds_fork::{UnixSeqpacketListener, UnixSocketAddr};
1034    /// # use std::io::ErrorKind;
1035    /// # use std::time::Duration;
1036    /// #
1037    /// # let addr = UnixSocketAddr::new("@set_timeout").unwrap();
1038    /// let listener = UnixSeqpacketListener::bind_unix_addr(&addr).unwrap();
1039    /// listener.set_timeout(Some(Duration::new(0, 200_000_000))).unwrap();
1040    /// let err = listener.accept_unix_addr().unwrap_err();
1041    /// assert_eq!(err.kind(), ErrorKind::WouldBlock);
1042    /// ```
1043    pub 
1044    fn set_timeout(&self,  timeout: Option<Duration>) -> Result<(), io::Error> 
1045    {
1046        let res = set_timeout(&self, TimeoutDirection::Read, timeout);
1047
1048        #[cfg(any(
1049                target_vendor="apple", target_os="freebsd",
1050                target_os="netbsd",
1051                target_os="illumos", target_os="solaris",
1052            ))]
1053        {
1054            if res.is_ok() == true && timeout.is_some() == true
1055            {
1056                return Err(
1057                    io::Error::new(
1058                        ErrorKind::InvalidInput,
1059                        "listener timeouts are not supported on this OS"
1060                    )
1061                );
1062            }
1063        }
1064
1065        return res;
1066    }
1067
1068    /// Returns the timeout for `accept()` on this socket.
1069    ///
1070    /// `None` is returned if there is no timeout.
1071    ///
1072    /// Even if a timeout has is set, it is ignored by `accept()` on
1073    /// most operating systems except Linux.
1074    ///
1075    /// # Examples
1076    ///
1077    #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
1078    #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
1079    /// # use uds_fork::{UnixSeqpacketListener, UnixSocketAddr};
1080    /// # use std::time::Duration;
1081    /// #
1082    /// # let addr = UnixSocketAddr::new("@timeout").unwrap();
1083    /// let listener = UnixSeqpacketListener::bind_unix_addr(&addr).unwrap();
1084    /// assert_eq!(listener.timeout().unwrap(), None);
1085    /// let timeout = Some(Duration::new(2, 0));
1086    /// listener.set_timeout(timeout).unwrap();
1087    /// assert_eq!(listener.timeout().unwrap(), timeout);
1088    /// ```
1089    pub 
1090    fn timeout(&self) -> Result<Option<Duration>, io::Error> 
1091    {
1092        get_timeout(&self, TimeoutDirection::Read)
1093    }
1094
1095    /// Enables or disables nonblocking-ness of [`accept_unix_addr()`](#method.accept_unix addr).
1096    ///
1097    /// The returned connnections will still be in blocking mode regardsless.
1098    ///
1099    /// Consider using the nonblocking variant of this type instead;
1100    /// this method mostly exists for feature parity with std's `UnixListener`.
1101    ///
1102    /// # Examples
1103    ///
1104    #[cfg_attr(not(target_vendor="apple"), doc="```")]
1105    #[cfg_attr(target_vendor="apple", doc="```no_run")]
1106    /// # use std::io::ErrorKind;
1107    /// # use uds_fork::{UnixSocketAddr, UnixSeqpacketListener};
1108    /// 
1109    /// let file_path = "/tmp/nonblocking_seqpacket_listener1.socket";
1110    /// let addr = UnixSocketAddr::from_path(file_path).unwrap();
1111    /// let _ = std::fs::remove_file(file_path);
1112    /// let listener = UnixSeqpacketListener::bind_unix_addr(&addr).expect("create listener");
1113    /// listener.set_nonblocking(true).expect("enable noblocking mode");
1114    /// assert_eq!(listener.accept_unix_addr().unwrap_err().kind(), ErrorKind::WouldBlock);
1115    /// # std::fs::remove_file(file_path).expect("delete socket file");
1116    /// ```
1117    pub 
1118    fn set_nonblocking(&self,  nonblocking: bool) -> Result<(), io::Error> 
1119    {
1120        set_nonblocking(&self, nonblocking)
1121    }
1122
1123    /// Returns an iterator over incoming connections.
1124    /// 
1125    /// Rustdoc:
1126    /// > The iterator will never return [`None`] and will also not yield the
1127    /// > peer's [`UnixSocketAddr`] structure.
1128    /// 
1129    /// ```no_run
1130    /// use std::thread;
1131    /// use uds_fork::{UnixSeqpacketConn, UnixSeqpacketListener};
1132    ///
1133    /// fn handle_client(stream: UnixSeqpacketConn) 
1134    /// {
1135    ///     // ...
1136    /// }
1137    ///
1138    /// fn main() -> std::io::Result<()> 
1139    /// {
1140    ///     let listener = UnixSeqpacketListener::bind("/path/to/the/socket")?;
1141    ///
1142    ///     for stream in listener.incoming() 
1143    ///     {
1144    ///         match stream 
1145    ///         {
1146    ///             Ok(stream) => 
1147    ///             {
1148    ///                 thread::spawn(|| handle_client(stream));
1149    ///             },
1150    ///             Err(err) => 
1151    ///             {
1152    ///                 break;
1153    ///             }
1154    ///         }
1155    ///     }
1156    /// 
1157    ///     return Ok(());
1158    /// }
1159    /// ```
1160    pub 
1161    fn incoming(&self) -> Incoming<'_> 
1162    {
1163        Incoming { listener: self }
1164    }
1165}
1166
1167/// A rust std API.
1168/// 
1169/// From Rustdocs:
1170/// > An iterator over incoming connections to a [`UnixListener`].
1171/// >
1172/// > It will never return [`None`].
1173/// 
1174/// # Examples
1175///
1176/// ```no_run
1177/// use std::thread;
1178/// use uds_fork::{UnixSeqpacketConn, UnixSeqpacketListener};
1179///
1180/// fn handle_client(stream: UnixSeqpacketConn) {
1181///     // ...
1182/// }
1183///
1184/// fn main() -> std::io::Result<()> 
1185/// {
1186///     let listener = UnixSeqpacketListener::bind("/path/to/the/socket")?;
1187///
1188///     for stream in listener.incoming() 
1189///     {
1190///         match stream 
1191///         {
1192///             Ok(stream) => 
1193///             {
1194///                 thread::spawn(|| handle_client(stream));
1195///             }
1196///             Err(err) => 
1197///             {
1198///                 break;
1199///             }
1200///         }
1201///     }
1202///     return Ok(());
1203/// }
1204/// ```
1205#[derive(Debug)]
1206pub struct Incoming<'a> 
1207{
1208    listener: &'a UnixSeqpacketListener,
1209}
1210
1211impl<'a> Iterator for Incoming<'a> 
1212{
1213    type Item = io::Result<UnixSeqpacketConn>;
1214
1215    fn next(&mut self) -> Option<io::Result<UnixSeqpacketConn>> 
1216    {
1217        Some(self.listener.accept().map(|s| s.0))
1218    }
1219
1220    fn size_hint(&self) -> (usize, Option<usize>) 
1221    {
1222        (usize::MAX, None)
1223    }
1224}
1225
1226impl<'a> IntoIterator for &'a UnixSeqpacketListener 
1227{
1228    type Item = io::Result<UnixSeqpacketConn>;
1229    type IntoIter = Incoming<'a>;
1230
1231    fn into_iter(self) -> Incoming<'a> 
1232    {
1233        self.incoming()
1234    }
1235}
1236
1237
1238
1239/// A non-blocking unix domain sequential-packet connection.
1240///
1241/// Differs from [`uds_fork::UnixSeqpacketConn`](../struct.UnixSeqpacketConn.html)
1242/// in that all operations that send or receive data will return an `Error` of
1243/// kind `ErrorKind::WouldBlock` instead of blocking.
1244/// This is done by creating the socket as non-blocking, and not by passing
1245/// `MSG_DONTWAIT`. If creating this type from a raw file descriptor, ensure
1246/// the fd is set to nonblocking before using it through this type.
1247/// 
1248/// # Registering with Xio (xio-rs) a feature = "xio-rs"
1249/// 
1250/// A `XioEventPipe` is implemented on this function. See [UnixSeqpacketConn]
1251/// for an examples.
1252/// 
1253/// See examples below.
1254/// 
1255/// # Registering with Mio (mio) a feature = "mio"
1256/// 
1257/// A `Source` is implemented on the instance. See [UnixSeqpacketConn]
1258/// for an examples.
1259/// 
1260/// # Examples
1261///
1262/// Sending or receiving when it would block a normal socket:
1263///
1264#[cfg_attr(not(target_vendor="apple"), doc="```")]
1265#[cfg_attr(target_vendor="apple", doc="```no_run")]
1266/// use uds_fork::nonblocking::UnixSeqpacketConn;
1267/// use std::io::ErrorKind;
1268///
1269/// let (a, b) = UnixSeqpacketConn::pair().expect("create nonblocking seqpacket pair");
1270///
1271/// // trying to receive when there are no packets waiting
1272/// assert_eq!(a.recv(&mut[0]).unwrap_err().kind(), ErrorKind::WouldBlock);
1273///
1274/// // trying to send when the OS buffer for the connection is full
1275/// loop {
1276///     if let Err(error) = a.send(&[0u8; 1000]) {
1277///         assert_eq!(error.kind(), ErrorKind::WouldBlock);
1278///         break;
1279///     }
1280/// }
1281/// ```
1282//#[deprecated = "Use UnixSeqpacketListener set_nonblocking(true)!"]
1283#[derive(Debug)]
1284#[repr(transparent)]
1285pub struct NonblockingUnixSeqpacketConn 
1286{
1287    usc: UnixSeqpacketConn,
1288}
1289
1290impl From<OwnedFd> for NonblockingUnixSeqpacketConn
1291{
1292    fn from(value: OwnedFd) -> Self 
1293    {
1294        let usc = UnixSeqpacketConn::from(value);
1295        usc.set_nonblocking(true).unwrap();
1296
1297        return Self{ usc: usc };
1298    }
1299}
1300
1301impl From<NonblockingUnixSeqpacketConn> for OwnedFd
1302{
1303    fn from(value: NonblockingUnixSeqpacketConn) -> Self 
1304    {
1305        return value.usc.fd;
1306    }
1307}
1308
1309impl FromRawFd for NonblockingUnixSeqpacketConn
1310{
1311    unsafe 
1312    fn from_raw_fd(fd: RawFd) -> Self 
1313    {
1314        let usc = unsafe{ UnixSeqpacketConn::from_raw_fd(fd) };
1315        usc.set_nonblocking(true).unwrap();
1316
1317        return Self{ usc: usc };
1318    }
1319}
1320
1321impl AsRawFd for NonblockingUnixSeqpacketConn
1322{
1323    fn as_raw_fd(&self) -> RawFd 
1324    {
1325        self.usc.as_raw_fd()
1326    }
1327}
1328impl IntoRawFd for NonblockingUnixSeqpacketConn
1329{
1330    fn into_raw_fd(self) -> RawFd 
1331    {
1332        self.usc.into_raw_fd()
1333    }
1334}
1335
1336impl AsFd for NonblockingUnixSeqpacketConn
1337{
1338    fn as_fd(&self) -> BorrowedFd<'_> 
1339    {
1340        self.usc.as_fd()
1341    }
1342}
1343
1344impl Deref for NonblockingUnixSeqpacketConn
1345{
1346    type Target = UnixSeqpacketConn;
1347
1348    fn deref(&self) -> &Self::Target 
1349    {
1350        &self.usc
1351    }
1352}
1353
1354impl DerefMut for NonblockingUnixSeqpacketConn
1355{
1356    fn deref_mut(&mut self) -> &mut Self::Target 
1357    {
1358        &mut self.usc
1359    }
1360}
1361
1362
1363#[cfg(feature = "mio")]
1364pub mod mio_non_blk_conn_enabled
1365{
1366    use std::io;
1367
1368    use mio::event::Source;
1369    use super::NonblockingUnixSeqpacketConn;
1370
1371    impl Source for NonblockingUnixSeqpacketConn
1372    {
1373        fn register(
1374            &mut self,
1375            registry: &mio::Registry,
1376            token: mio::Token,
1377            interests: mio::Interest,
1378        ) -> io::Result<()> 
1379        {
1380            self.usc.register(registry, token, interests)
1381        }
1382    
1383        fn reregister(
1384            &mut self,
1385            registry: &mio::Registry,
1386            token: mio::Token,
1387            interests: mio::Interest,
1388        ) -> io::Result<()> 
1389        {
1390            self.usc.reregister(registry, token, interests)
1391        }
1392    
1393        fn deregister(&mut self, registry: &mio::Registry) -> io::Result<()> 
1394        {
1395            self.usc.deregister(registry)
1396        }
1397    }
1398}
1399
1400#[cfg(feature = "xio-rs")]
1401pub mod xio_non_blk_conn_enabled
1402{
1403    use xio_rs::{EsInterfaceRegistry, XioChannel, XioEventPipe, XioEventUid, XioResult, event_registry::XioRegistry};
1404
1405    use super::NonblockingUnixSeqpacketConn;
1406
1407    impl<ESSR: EsInterfaceRegistry> XioEventPipe<ESSR, Self> for NonblockingUnixSeqpacketConn
1408    {
1409        fn connect_event_pipe(&mut self, ess: &XioRegistry<ESSR>, ev_uid: XioEventUid, channel: XioChannel) -> XioResult<()> 
1410        {
1411            self.usc.connect_event_pipe(ess, ev_uid, channel)
1412        }
1413    
1414        fn modify_event_pipe(&mut self, ess: &XioRegistry<ESSR>, ev_uid: XioEventUid, channel: XioChannel) -> XioResult<()> 
1415        {
1416            self.usc.modify_event_pipe(ess, ev_uid, channel)
1417        }
1418    
1419        fn disconnect_event_pipe(&mut self, ess: &XioRegistry<ESSR>) -> XioResult<()> 
1420        {
1421            self.usc.disconnect_event_pipe(ess)
1422        }
1423    }
1424}
1425
1426// can't Deref<Target=UnixSeqpacketConn> because that would include try_clone()
1427// and later set_(read|write)_timeout()
1428impl NonblockingUnixSeqpacketConn 
1429{
1430    /// Connects to an unix seqpacket server listening at `path`.
1431    ///
1432    /// This is a wrapper around [`connect_unix_addr()`](#method.connect_unix_addr)
1433    /// for convenience and compatibility with std.
1434    pub 
1435    fn connect<P: AsRef<Path>>(path: P) -> Result<Self, io::Error> 
1436    {
1437        let addr = UnixSocketAddr::from_path(&path)?;
1438
1439        return Self::connect_unix_addr(&addr);
1440    }
1441
1442    /// Connects to an unix seqpacket server listening at `addr`.
1443    pub 
1444    fn connect_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error> 
1445    {
1446        let socket = Socket::<SocketSeqPkt>::new(true)?;
1447        socket.set_unix_peer_addr(addr)?;
1448        
1449        return Ok(
1450            NonblockingUnixSeqpacketConn 
1451            {
1452                usc: UnixSeqpacketConn { fd: socket.into() }
1453            }
1454        );
1455    }
1456    
1457    /// Binds to an address before connecting to a listening seqpacet socket.
1458    pub 
1459    fn connect_from_to_unix_addr(from: &UnixSocketAddr,  to: &UnixSocketAddr) -> Result<Self, io::Error> 
1460    {
1461        let socket = Socket::<SocketSeqPkt>::new(true)?;
1462        socket.set_unix_local_addr(from)?;
1463        socket.set_unix_peer_addr(to)?;
1464        
1465        return Ok(
1466            NonblockingUnixSeqpacketConn 
1467            {
1468                usc: UnixSeqpacketConn { fd: socket.into() }
1469            }
1470        );
1471    }
1472
1473    /// Creates a pair of unix-domain seqpacket conneections connected to each other.
1474    ///
1475    /// # Examples
1476    ///
1477    #[cfg_attr(not(target_vendor="apple"), doc="```")]
1478    #[cfg_attr(target_vendor="apple", doc="```no_run")]
1479    /// let (a, b) = uds_fork::UnixSeqpacketConn::pair().unwrap();
1480    /// assert!(a.local_unix_addr().unwrap().is_unnamed());
1481    /// assert!(b.local_unix_addr().unwrap().is_unnamed());
1482    ///
1483    /// a.send(b"hello").unwrap();
1484    /// b.recv(&mut[0; 20]).unwrap();
1485    /// ```
1486    pub 
1487    fn pair() -> Result<(Self, Self), io::Error> 
1488    {
1489        let pair = Socket::<SocketSeqPkt>::pair(true)?;
1490        
1491        return Ok(
1492            (
1493                Self{ usc: UnixSeqpacketConn { fd: pair.0.into() } },
1494                Self{ usc: UnixSeqpacketConn { fd: pair.1.into() } },
1495            )
1496        );
1497    }
1498
1499    pub 
1500    fn try_clone(&self) -> Result<Self, io::Error> 
1501    {
1502        let cloned = Socket::<SocketSeqPkt>::try_clone_from(self)?;
1503
1504        return Ok(
1505            NonblockingUnixSeqpacketConn 
1506            {
1507                usc: UnixSeqpacketConn { fd: cloned.into() }
1508            }
1509        );
1510    }
1511}
1512
1513
1514/// A non-blocking unix domain listener for sequential-packet connections.
1515///
1516/// Differs from [`UnixSeqpacketListener`](../struct.UnixSeqpacketListener.html)
1517/// in that [`accept()`](struct.NonblockingUnixSeqpacketListener.html#method.accept)
1518/// returns non-blocking [connection sockets](struct.NonblockingUnixSeqpacketConn.html)
1519/// and doesn't block if no client `connect()`ions are pending.
1520///
1521/// # Registering with Xio (xio-rs) a feature = "xio-rs"
1522/// 
1523/// A `XioEventPipe` is implemented on this function. See [UnixSeqpacketListener]
1524/// for an examples.
1525/// 
1526/// See examples below.
1527/// 
1528/// # Registering with Mio (mio) a feature = "mio"
1529/// 
1530/// A `Source` is implemented on the instance. See [UnixSeqpacketListener]
1531/// for an examples.
1532///
1533/// # Examples
1534///
1535#[cfg_attr(not(target_vendor="apple"), doc="```")]
1536#[cfg_attr(target_vendor="apple", doc="```no_run")]
1537/// use uds_fork::nonblocking::{UnixSeqpacketListener, UnixSeqpacketConn};
1538/// use std::io::ErrorKind;
1539///
1540/// let file_path = "/tmp/nonblocking_seqpacket_listener2.socket";
1541/// 
1542/// let _ = std::fs::remove_file(file_path);
1543/// let listener = UnixSeqpacketListener::bind(file_path)
1544///     .expect("Cannot create nonblocking seqpacket listener");
1545///
1546/// // doesn't block if no connections are waiting:
1547/// assert_eq!(listener.accept_unix_addr().unwrap_err().kind(), ErrorKind::WouldBlock);
1548///
1549/// // returned connections are nonblocking:
1550/// let _client = UnixSeqpacketConn::connect(file_path).unwrap();
1551/// let (conn, _addr) = listener.accept_unix_addr().unwrap();
1552/// assert_eq!(conn.recv(&mut[0u8; 20]).unwrap_err().kind(), ErrorKind::WouldBlock);
1553/// #
1554/// # std::fs::remove_file(file_path).unwrap();
1555/// ```
1556#[derive(Debug)]
1557#[repr(transparent)]
1558pub struct NonblockingUnixSeqpacketListener 
1559{
1560    usl: UnixSeqpacketListener,
1561}
1562
1563impl From<OwnedFd> for NonblockingUnixSeqpacketListener
1564{
1565    fn from(ofd: OwnedFd) -> Self 
1566    {
1567        let usl = UnixSeqpacketListener::from(ofd);
1568        usl.set_nonblocking(true).unwrap();
1569
1570        return Self{ usl };
1571    }
1572}
1573
1574impl FromRawFd for NonblockingUnixSeqpacketListener
1575{
1576    unsafe 
1577    fn from_raw_fd(fd: RawFd) -> Self 
1578    {
1579        let usl = unsafe{ UnixSeqpacketListener::from_raw_fd(fd) };
1580        usl.set_nonblocking(true).unwrap();
1581
1582        return Self{ usl };
1583    }
1584}
1585
1586
1587impl From<NonblockingUnixSeqpacketListener> for OwnedFd
1588{
1589    fn from(value: NonblockingUnixSeqpacketListener) -> Self 
1590    {
1591        return value.usl.fd;
1592    }
1593}
1594
1595
1596impl AsRawFd for NonblockingUnixSeqpacketListener
1597{
1598    fn as_raw_fd(&self) -> RawFd 
1599    {
1600        self.usl.as_raw_fd()
1601    }
1602}
1603
1604impl IntoRawFd for NonblockingUnixSeqpacketListener
1605{
1606    fn into_raw_fd(self) -> RawFd 
1607    {
1608        self.usl.into_raw_fd()
1609    }
1610}
1611
1612impl AsFd for NonblockingUnixSeqpacketListener
1613{
1614    fn as_fd(&self) -> BorrowedFd<'_> 
1615    {
1616        self.usl.as_fd()
1617    }
1618}
1619
1620
1621impl Deref for NonblockingUnixSeqpacketListener
1622{
1623    type Target = UnixSeqpacketListener;
1624
1625    fn deref(&self) -> &Self::Target 
1626    {
1627        &self.usl
1628    }
1629}
1630
1631impl DerefMut for NonblockingUnixSeqpacketListener
1632{
1633    fn deref_mut(&mut self) -> &mut Self::Target 
1634    {
1635        &mut self.usl
1636    }
1637}
1638
1639impl NonblockingUnixSeqpacketListener 
1640{
1641    /// Creates a socket that listens for seqpacket connections on the specified socket file.
1642    pub 
1643    fn bind<P: AsRef<Path>>(path: P) -> Result<Self, io::Error> 
1644    {
1645        let addr = UnixSocketAddr::from_path(&path)?;
1646
1647        return Self::bind_unix_addr(&addr);
1648    }
1649
1650    /// Creates a socket that listens for seqpacket connections on the specified address.
1651    pub 
1652    fn bind_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error> 
1653    {
1654        let socket = Socket::<SocketSeqPkt>::new(true)?;
1655        socket.set_unix_local_addr(addr)?;
1656        socket.start_listening()?;
1657
1658        return Ok( Self{ usl: UnixSeqpacketListener{ fd: socket.into() }} );
1659    }
1660
1661    /// Accepts a non-blocking connection, non-blockingly.
1662    ///
1663    /// # Examples
1664    ///
1665    /// Doesn't block if no connections are waiting:
1666    ///
1667    #[cfg_attr(not(target_vendor="apple"), doc="```")]
1668    #[cfg_attr(target_vendor="apple", doc="```no_run")]
1669    /// # use uds_fork::nonblocking::UnixSeqpacketListener;
1670    /// # use std::io::ErrorKind;
1671    /// #
1672    /// let file_path = "/tmp/nonblocking_seqpacket_listener3.socket";
1673    /// let _ = std::fs::remove_file(file_path);
1674    /// let listener = UnixSeqpacketListener::bind(file_path)
1675    ///     .expect("Cannot create nonblocking seqpacket listener");
1676    /// assert_eq!(listener.accept_unix_addr().unwrap_err().kind(), ErrorKind::WouldBlock);
1677    /// std::fs::remove_file(file_path).unwrap();
1678    /// ```
1679    pub 
1680    fn accept_unix_addr(&self) -> Result<(NonblockingUnixSeqpacketConn, UnixSocketAddr), io::Error> 
1681    {
1682        let (socket, addr) = Socket::<SocketSeqPkt>::accept_from(&self, true)?;
1683        let conn = NonblockingUnixSeqpacketConn { usc: UnixSeqpacketConn{ fd: socket.into() }};
1684        
1685        return Ok((conn, addr));
1686    }
1687}
1688
1689#[cfg(feature = "mio")]
1690pub mod mio_non_blk_listener_enabled
1691{
1692    use std::{io, os::fd::AsRawFd};
1693
1694    use mio::{event::Source, unix::SourceFd};
1695    use super::NonblockingUnixSeqpacketListener;
1696
1697    impl Source for NonblockingUnixSeqpacketListener
1698    {
1699        fn register(
1700            &mut self,
1701            registry: &mio::Registry,
1702            token: mio::Token,
1703            interests: mio::Interest,
1704        ) -> io::Result<()> 
1705        {
1706            self.usl.register(registry, token, interests)
1707        }
1708    
1709        fn reregister(
1710            &mut self,
1711            registry: &mio::Registry,
1712            token: mio::Token,
1713            interests: mio::Interest,
1714        ) -> io::Result<()> 
1715        {
1716            self.usl.reregister(registry, token, interests)
1717        }
1718    
1719        fn deregister(&mut self, registry: &mio::Registry) -> io::Result<()> 
1720        {
1721            self.usl.deregister(registry)
1722        }
1723    }
1724}
1725
1726#[cfg(feature = "xio-rs")]
1727pub mod xio_non_blk_listener_enabled
1728{
1729    use xio_rs::{EsInterfaceRegistry, XioChannel, XioEventPipe, XioEventUid, XioResult, event_registry::XioRegistry};
1730
1731    use super::NonblockingUnixSeqpacketListener;
1732
1733    impl<ESSR: EsInterfaceRegistry> XioEventPipe<ESSR, Self> for NonblockingUnixSeqpacketListener
1734    {
1735        fn connect_event_pipe(&mut self, ess: &XioRegistry<ESSR>, ev_uid: XioEventUid, channel: XioChannel) -> XioResult<()> 
1736        {
1737 
1738            self.usl.connect_event_pipe(ess, ev_uid, channel)
1739        }
1740    
1741        fn modify_event_pipe(&mut self, ess: &XioRegistry<ESSR>, ev_uid: XioEventUid, channel: XioChannel) -> XioResult<()> 
1742        {
1743            self.usl.modify_event_pipe(ess, ev_uid, channel)
1744        }
1745    
1746        fn disconnect_event_pipe(&mut self, ess: &XioRegistry<ESSR>) -> XioResult<()> 
1747        {
1748            self.usl.disconnect_event_pipe(ess)
1749        }
1750    }
1751}