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/// use tempfile::TempDir;
81/// 
82/// let dir = tempfile::tempdir().unwrap();
83/// let mut file_path = dir.path().join("seqpacket.socket");
84/// 
85/// let listener = UnixSeqpacketListener::bind(&file_path)
86///     .expect("create seqpacket listener");
87/// let conn = UnixSeqpacketConn::connect(&file_path)
88///     .expect("connect to seqpacket listener");
89///
90/// let message = "Hello, listener";
91/// let sent = conn.send(message.as_bytes()).unwrap();
92/// assert_eq!(sent, message.len());
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/// use tempfile::TempDir;
737/// 
738/// let dir = tempfile::tempdir().unwrap();
739/// let mut file_path = dir.path().join("seqpacket_listener.socket");
740/// 
741/// let listener = uds_fork::UnixSeqpacketListener::bind(&file_path)
742///     .expect("Create seqpacket listener");
743/// let _client = uds_fork::UnixSeqpacketConn::connect(&file_path).unwrap();
744/// let (conn, _addr) = listener.accept_unix_addr().unwrap();
745/// conn.send(b"Welcome").unwrap();
746/// ```
747/// 
748/// ### Xio
749/// 
750/// ```ignore
751/// let listener = uds_fork::UnixSeqpacketListener::bind(file_path).unwrap();
752/// 
753/// let mut reg = XioPollRegistry::<ESS>::new().unwrap();
754/// let mut event_buf = XioPollRegistry::<ESS>::allocate_events(128.try_into().unwrap());
755/// 
756/// // either
757/// let a_wrapped =
758///     reg.get_registry()
759///         .en_register_wrap(listener, XioEventUid::manual(1), XioChannel::INPUT)
760///         .unwrap();
761///  
762/// // or 
763///     reg.get_registry()
764///         .en_register&mut listener, XioEventUid::manual(1), XioChannel::INPUT)
765///         .unwrap();
766/// 
767/// // so depending on the method, use either:
768/// a_wrapped.inner();
769/// 
770/// // or continue using a directly
771/// ```
772/// 
773/// ### Mio:
774/// 
775/// ```ignore
776/// let listener = uds_fork::UnixSeqpacketListener::bind(file_path).unwrap();
777/// 
778/// let mut poll = Poll::new().expect("create mio poll");
779/// let mut events = Events::with_capacity(10);
780/// 
781/// poll.registry()
782///     .register(&mut listener, Token(1), Interest::READABLE)
783///     .unwrap();
784/// // ...
785/// ``` 
786#[derive(Debug)]
787#[repr(transparent)]
788pub struct UnixSeqpacketListener 
789{
790    fd: OwnedFd
791}
792
793
794impl From<OwnedFd> for UnixSeqpacketListener
795{
796    fn from(ofd: OwnedFd) -> Self 
797    {
798        let sa_fam = get_socket_family(&ofd).unwrap();
799        let sa_type = get_socket_type(&ofd).unwrap() & 0x00000FFF;
800
801        if sa_fam as i32 != libc::AF_UNIX || sa_type != libc::SOCK_SEQPACKET
802        {
803            panic!("assertion trap: provided FD is not AF_UNIX & SOCK_SEQPACKET, {} {}", 
804                sa_fam, sa_type);
805        }
806
807        return UnixSeqpacketListener{ fd: ofd };
808    }
809}
810
811impl From<UnixSeqpacketListener> for OwnedFd
812{
813    fn from(value: UnixSeqpacketListener) -> Self 
814    {
815        return value.fd;
816    }
817}
818
819impl FromRawFd for UnixSeqpacketListener
820{
821    unsafe 
822    fn from_raw_fd(fd: RawFd) -> Self 
823    {
824        UnixSeqpacketListener::from( unsafe { OwnedFd::from_raw_fd(fd) } )
825    }
826}
827
828impl AsRawFd for UnixSeqpacketListener
829{
830    fn as_raw_fd(&self) -> RawFd 
831    {
832        self.fd.as_raw_fd()
833    }
834}
835
836impl IntoRawFd for UnixSeqpacketListener
837{
838    fn into_raw_fd(self) -> RawFd 
839    {
840        self.fd.into_raw_fd()
841    }
842}
843
844impl AsFd for UnixSeqpacketListener
845{
846    fn as_fd(&self) -> BorrowedFd<'_> 
847    {
848        self.fd.as_fd()
849    }
850}
851
852#[cfg(feature = "mio")]
853pub mod mio_listener_enabled
854{
855    use std::{io, os::fd::AsRawFd};
856
857    use mio::{event::Source, unix::SourceFd};
858    use crate::UnixSeqpacketListener;
859
860    impl Source for UnixSeqpacketListener
861    {
862        fn register(
863            &mut self,
864            registry: &mio::Registry,
865            token: mio::Token,
866            interests: mio::Interest,
867        ) -> io::Result<()> 
868        {
869            self.set_nonblocking(true)?;
870            
871            SourceFd(&self.fd.as_raw_fd()).register(registry, token, interests)
872        }
873    
874        fn reregister(
875            &mut self,
876            registry: &mio::Registry,
877            token: mio::Token,
878            interests: mio::Interest,
879        ) -> io::Result<()> 
880        {
881            SourceFd(&self.fd.as_raw_fd()).reregister(registry, token, interests)
882        }
883    
884        fn deregister(&mut self, registry: &mio::Registry) -> io::Result<()> 
885        {
886            SourceFd(&self.fd.as_raw_fd()).deregister(registry)
887        }
888    }
889}
890
891#[cfg(feature = "xio-rs")]
892pub mod xio_listener_enabled
893{
894    use xio_rs::{EsInterfaceRegistry, XioChannel, XioEventPipe, XioEventUid, XioResult, event_registry::XioRegistry};
895
896    use crate::UnixSeqpacketListener;
897
898    impl<ESSR: EsInterfaceRegistry> XioEventPipe<ESSR, Self> for UnixSeqpacketListener
899    {
900        fn connect_event_pipe(&mut self, ess: &XioRegistry<ESSR>, ev_uid: XioEventUid, channel: XioChannel) -> XioResult<()> 
901        {
902            self.set_nonblocking(true)?;
903            
904            ess.get_ev_sys().en_register(&self.fd, ev_uid, channel)
905        }
906    
907        fn modify_event_pipe(&mut self, ess: &XioRegistry<ESSR>, ev_uid: XioEventUid, channel: XioChannel) -> XioResult<()> 
908        {
909            ess.get_ev_sys().re_register(&self.fd, ev_uid, channel)
910        }
911    
912        fn disconnect_event_pipe(&mut self, ess: &XioRegistry<ESSR>) -> XioResult<()> 
913        {
914            ess.get_ev_sys().de_register(&self.fd)
915        }
916    }
917}
918
919impl UnixSeqpacketListener 
920{
921    /// Creates a socket that listens for seqpacket connections on the specified socket file.
922    pub 
923    fn bind<P: AsRef<Path>>(path: P) -> Result<Self, io::Error> 
924    {
925        let addr = UnixSocketAddr::from_path(path.as_ref())?;
926        
927        return Self::bind_unix_addr(&addr);
928    }
929
930    /// Creates a socket that listens for seqpacket connections on the specified address.
931    pub 
932    fn bind_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error> 
933    {
934        let socket = Socket::<SocketSeqPkt>::new(false)?;
935
936        socket.set_unix_local_addr(addr)?;
937        socket.start_listening()?;
938        
939        return Ok(UnixSeqpacketListener { fd: socket.into() });
940    }
941
942    /// Returns the address the socket is listening on.
943    pub 
944    fn local_unix_addr(&self) -> Result<UnixSocketAddr, io::Error> 
945    {
946        get_unix_local_addr(&self)
947    }
948
949    /// Accepts a new incoming connection to this listener.
950    /// 
951    /// Rustdocs: 
952    /// > This function will block the calling thread until a new Unix connection
953    /// > is established. When established, the corresponding [`UnixSeqpacketConn`] and
954    /// > the remote peer's address will be returned.
955    /// 
956    /// [`UnixSeqpacketConn`]: uds_fork::UnixSeqpacketConn
957    ///
958    /// # Examples
959    ///
960    /// ```no_run
961    /// use uds_fork::UnixSeqpacketListener;
962    ///
963    /// fn main() -> std::io::Result<()> 
964    /// {
965    ///     let listener = UnixSeqpacketListener::bind("/path/to/the/socket")?;
966    ///
967    ///     match listener.accept()
968    ///     {
969    ///         Ok((socket, addr)) => 
970    ///             println!("Got a client: {addr:?}"),
971    ///         Err(e) => 
972    ///             println!("accept function failed: {e:?}"),
973    ///     }
974    /// 
975    ///     return Ok(());
976    /// }
977    /// ```
978    #[inline]
979    pub 
980    fn accept(&self)-> Result<(UnixSeqpacketConn, UnixSocketAddr), io::Error> 
981    {
982        self.accept_unix_addr()
983    }
984
985    /// Accepts a new incoming connection to this listener.
986    /// 
987    /// See [Self::accept].
988    pub 
989    fn accept_unix_addr(&self)-> Result<(UnixSeqpacketConn, UnixSocketAddr), io::Error> 
990    {
991        let (socket, addr) = Socket::<SocketSeqPkt>::accept_from(&self, false)?;
992        let conn = UnixSeqpacketConn { fd: socket.into() };
993        
994        return Ok((conn, addr));
995    }
996
997    /// Returns the value of the `SO_ERROR` option.
998    ///
999    /// This might never produce any errors for listeners. It is therefore
1000    /// unlikely to be useful, but is provided for parity with
1001    /// `std::unix::net::UnixListener`.
1002    pub 
1003    fn take_error(&self) -> Result<Option<io::Error>, io::Error> 
1004    {
1005        take_error(&self)
1006    }
1007
1008    /// Creates a new file descriptor listening for the same connections.
1009    pub 
1010    fn try_clone(&self) -> Result<Self, io::Error> 
1011    {
1012        let cloned = Socket::<SocketSeqPkt>::try_clone_from(&self)?;
1013        
1014        return Ok(UnixSeqpacketListener { fd: cloned.into() });
1015    }
1016
1017    /// Sets a maximum duration to wait in a single `accept()` on this socket.
1018    ///
1019    /// `None` disables a previously set timeout.
1020    /// An error is returned if the duration is zero.
1021    ///
1022    /// # Operating System Support
1023    ///
1024    /// Only Linux appers to apply timeouts to `accept()`.  
1025    /// On macOS, FreeBSD and NetBSD, timeouts are silently ignored.  
1026    /// On Illumos setting timeouts for all unix domain sockets silently fails.
1027    ///
1028    /// On OSes where timeouts are known to not work, this function will
1029    /// return an error even if setting the timeout didn't fail.
1030    ///
1031    /// # Examples
1032    ///
1033    #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
1034    #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
1035    /// # use uds_fork::{UnixSeqpacketListener, UnixSocketAddr};
1036    /// # use std::io::ErrorKind;
1037    /// # use std::time::Duration;
1038    /// #
1039    /// # let addr = UnixSocketAddr::new("@set_timeout").unwrap();
1040    /// let listener = UnixSeqpacketListener::bind_unix_addr(&addr).unwrap();
1041    /// listener.set_timeout(Some(Duration::new(0, 200_000_000))).unwrap();
1042    /// let err = listener.accept_unix_addr().unwrap_err();
1043    /// assert_eq!(err.kind(), ErrorKind::WouldBlock);
1044    /// ```
1045    pub 
1046    fn set_timeout(&self,  timeout: Option<Duration>) -> Result<(), io::Error> 
1047    {
1048        let res = set_timeout(&self, TimeoutDirection::Read, timeout);
1049
1050        #[cfg(any(
1051                target_vendor="apple", target_os="freebsd",
1052                target_os="netbsd",
1053                target_os="illumos", target_os="solaris",
1054            ))]
1055        {
1056            if res.is_ok() == true && timeout.is_some() == true
1057            {
1058                return Err(
1059                    io::Error::new(
1060                        ErrorKind::InvalidInput,
1061                        "listener timeouts are not supported on this OS"
1062                    )
1063                );
1064            }
1065        }
1066
1067        return res;
1068    }
1069
1070    /// Returns the timeout for `accept()` on this socket.
1071    ///
1072    /// `None` is returned if there is no timeout.
1073    ///
1074    /// Even if a timeout has is set, it is ignored by `accept()` on
1075    /// most operating systems except Linux.
1076    ///
1077    /// # Examples
1078    ///
1079    #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
1080    #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
1081    /// # use uds_fork::{UnixSeqpacketListener, UnixSocketAddr};
1082    /// # use std::time::Duration;
1083    /// #
1084    /// # let addr = UnixSocketAddr::new("@timeout").unwrap();
1085    /// let listener = UnixSeqpacketListener::bind_unix_addr(&addr).unwrap();
1086    /// assert_eq!(listener.timeout().unwrap(), None);
1087    /// let timeout = Some(Duration::new(2, 0));
1088    /// listener.set_timeout(timeout).unwrap();
1089    /// assert_eq!(listener.timeout().unwrap(), timeout);
1090    /// ```
1091    pub 
1092    fn timeout(&self) -> Result<Option<Duration>, io::Error> 
1093    {
1094        get_timeout(&self, TimeoutDirection::Read)
1095    }
1096
1097    /// Enables or disables nonblocking-ness of [`accept_unix_addr()`](#method.accept_unix addr).
1098    ///
1099    /// The returned connnections will still be in blocking mode regardsless.
1100    ///
1101    /// Consider using the nonblocking variant of this type instead;
1102    /// this method mostly exists for feature parity with std's `UnixListener`.
1103    ///
1104    /// # Examples
1105    ///
1106    #[cfg_attr(not(target_vendor="apple"), doc="```")]
1107    #[cfg_attr(target_vendor="apple", doc="```no_run")]
1108    /// # use std::io::ErrorKind;
1109    /// # use uds_fork::{UnixSocketAddr, UnixSeqpacketListener};
1110    /// use tempfile::TempDir;
1111    /// 
1112    /// let dir = tempfile::tempdir().unwrap();
1113    /// let mut file_path = dir.path().join("nonblocking_seqpacket_listener1.socket");
1114    /// 
1115    /// let addr = UnixSocketAddr::from_path(&file_path).unwrap();
1116    /// let listener = UnixSeqpacketListener::bind_unix_addr(&addr).expect("create listener");
1117    /// listener.set_nonblocking(true).expect("enable noblocking mode");
1118    /// assert_eq!(listener.accept_unix_addr().unwrap_err().kind(), ErrorKind::WouldBlock);
1119    /// ```
1120    pub 
1121    fn set_nonblocking(&self,  nonblocking: bool) -> Result<(), io::Error> 
1122    {
1123        set_nonblocking(&self, nonblocking)
1124    }
1125
1126    /// Returns an iterator over incoming connections.
1127    /// 
1128    /// Rustdoc:
1129    /// > The iterator will never return [`None`] and will also not yield the
1130    /// > peer's [`UnixSocketAddr`] structure.
1131    /// 
1132    /// ```no_run
1133    /// use std::thread;
1134    /// use uds_fork::{UnixSeqpacketConn, UnixSeqpacketListener};
1135    ///
1136    /// fn handle_client(stream: UnixSeqpacketConn) 
1137    /// {
1138    ///     // ...
1139    /// }
1140    ///
1141    /// fn main() -> std::io::Result<()> 
1142    /// {
1143    ///     let listener = UnixSeqpacketListener::bind("/path/to/the/socket")?;
1144    ///
1145    ///     for stream in listener.incoming() 
1146    ///     {
1147    ///         match stream 
1148    ///         {
1149    ///             Ok(stream) => 
1150    ///             {
1151    ///                 thread::spawn(|| handle_client(stream));
1152    ///             },
1153    ///             Err(err) => 
1154    ///             {
1155    ///                 break;
1156    ///             }
1157    ///         }
1158    ///     }
1159    /// 
1160    ///     return Ok(());
1161    /// }
1162    /// ```
1163    pub 
1164    fn incoming(&self) -> Incoming<'_> 
1165    {
1166        Incoming { listener: self }
1167    }
1168}
1169
1170/// A rust std API.
1171/// 
1172/// From Rustdocs:
1173/// > An iterator over incoming connections to a [`UnixListener`].
1174/// >
1175/// > It will never return [`None`].
1176/// 
1177/// # Examples
1178///
1179/// ```no_run
1180/// use std::thread;
1181/// use uds_fork::{UnixSeqpacketConn, UnixSeqpacketListener};
1182///
1183/// fn handle_client(stream: UnixSeqpacketConn) {
1184///     // ...
1185/// }
1186///
1187/// fn main() -> std::io::Result<()> 
1188/// {
1189///     let listener = UnixSeqpacketListener::bind("/path/to/the/socket")?;
1190///
1191///     for stream in listener.incoming() 
1192///     {
1193///         match stream 
1194///         {
1195///             Ok(stream) => 
1196///             {
1197///                 thread::spawn(|| handle_client(stream));
1198///             }
1199///             Err(err) => 
1200///             {
1201///                 break;
1202///             }
1203///         }
1204///     }
1205///     return Ok(());
1206/// }
1207/// ```
1208#[derive(Debug)]
1209pub struct Incoming<'a> 
1210{
1211    listener: &'a UnixSeqpacketListener,
1212}
1213
1214impl<'a> Iterator for Incoming<'a> 
1215{
1216    type Item = io::Result<UnixSeqpacketConn>;
1217
1218    fn next(&mut self) -> Option<io::Result<UnixSeqpacketConn>> 
1219    {
1220        Some(self.listener.accept().map(|s| s.0))
1221    }
1222
1223    fn size_hint(&self) -> (usize, Option<usize>) 
1224    {
1225        (usize::MAX, None)
1226    }
1227}
1228
1229impl<'a> IntoIterator for &'a UnixSeqpacketListener 
1230{
1231    type Item = io::Result<UnixSeqpacketConn>;
1232    type IntoIter = Incoming<'a>;
1233
1234    fn into_iter(self) -> Incoming<'a> 
1235    {
1236        self.incoming()
1237    }
1238}
1239
1240
1241
1242/// A non-blocking unix domain sequential-packet connection.
1243///
1244/// Differs from [`uds_fork::UnixSeqpacketConn`](../struct.UnixSeqpacketConn.html)
1245/// in that all operations that send or receive data will return an `Error` of
1246/// kind `ErrorKind::WouldBlock` instead of blocking.
1247/// This is done by creating the socket as non-blocking, and not by passing
1248/// `MSG_DONTWAIT`. If creating this type from a raw file descriptor, ensure
1249/// the fd is set to nonblocking before using it through this type.
1250/// 
1251/// # Registering with Xio (xio-rs) a feature = "xio-rs"
1252/// 
1253/// A `XioEventPipe` is implemented on this function. See [UnixSeqpacketConn]
1254/// for an examples.
1255/// 
1256/// See examples below.
1257/// 
1258/// # Registering with Mio (mio) a feature = "mio"
1259/// 
1260/// A `Source` is implemented on the instance. See [UnixSeqpacketConn]
1261/// for an examples.
1262/// 
1263/// # Examples
1264///
1265/// Sending or receiving when it would block a normal socket:
1266///
1267#[cfg_attr(not(target_vendor="apple"), doc="```")]
1268#[cfg_attr(target_vendor="apple", doc="```no_run")]
1269/// use uds_fork::nonblocking::UnixSeqpacketConn;
1270/// use std::io::ErrorKind;
1271///
1272/// let (a, b) = UnixSeqpacketConn::pair().expect("create nonblocking seqpacket pair");
1273///
1274/// // trying to receive when there are no packets waiting
1275/// assert_eq!(a.recv(&mut[0]).unwrap_err().kind(), ErrorKind::WouldBlock);
1276///
1277/// // trying to send when the OS buffer for the connection is full
1278/// loop {
1279///     if let Err(error) = a.send(&[0u8; 1000]) {
1280///         assert_eq!(error.kind(), ErrorKind::WouldBlock);
1281///         break;
1282///     }
1283/// }
1284/// ```
1285//#[deprecated = "Use UnixSeqpacketListener set_nonblocking(true)!"]
1286#[derive(Debug)]
1287#[repr(transparent)]
1288pub struct NonblockingUnixSeqpacketConn 
1289{
1290    usc: UnixSeqpacketConn,
1291}
1292
1293impl From<OwnedFd> for NonblockingUnixSeqpacketConn
1294{
1295    fn from(value: OwnedFd) -> Self 
1296    {
1297        let usc = UnixSeqpacketConn::from(value);
1298        usc.set_nonblocking(true).unwrap();
1299
1300        return Self{ usc: usc };
1301    }
1302}
1303
1304impl From<NonblockingUnixSeqpacketConn> for OwnedFd
1305{
1306    fn from(value: NonblockingUnixSeqpacketConn) -> Self 
1307    {
1308        return value.usc.fd;
1309    }
1310}
1311
1312impl FromRawFd for NonblockingUnixSeqpacketConn
1313{
1314    unsafe 
1315    fn from_raw_fd(fd: RawFd) -> Self 
1316    {
1317        let usc = unsafe{ UnixSeqpacketConn::from_raw_fd(fd) };
1318        usc.set_nonblocking(true).unwrap();
1319
1320        return Self{ usc: usc };
1321    }
1322}
1323
1324impl AsRawFd for NonblockingUnixSeqpacketConn
1325{
1326    fn as_raw_fd(&self) -> RawFd 
1327    {
1328        self.usc.as_raw_fd()
1329    }
1330}
1331impl IntoRawFd for NonblockingUnixSeqpacketConn
1332{
1333    fn into_raw_fd(self) -> RawFd 
1334    {
1335        self.usc.into_raw_fd()
1336    }
1337}
1338
1339impl AsFd for NonblockingUnixSeqpacketConn
1340{
1341    fn as_fd(&self) -> BorrowedFd<'_> 
1342    {
1343        self.usc.as_fd()
1344    }
1345}
1346
1347impl Deref for NonblockingUnixSeqpacketConn
1348{
1349    type Target = UnixSeqpacketConn;
1350
1351    fn deref(&self) -> &Self::Target 
1352    {
1353        &self.usc
1354    }
1355}
1356
1357impl DerefMut for NonblockingUnixSeqpacketConn
1358{
1359    fn deref_mut(&mut self) -> &mut Self::Target 
1360    {
1361        &mut self.usc
1362    }
1363}
1364
1365
1366#[cfg(feature = "mio")]
1367pub mod mio_non_blk_conn_enabled
1368{
1369    use std::io;
1370
1371    use mio::event::Source;
1372    use super::NonblockingUnixSeqpacketConn;
1373
1374    impl Source for NonblockingUnixSeqpacketConn
1375    {
1376        fn register(
1377            &mut self,
1378            registry: &mio::Registry,
1379            token: mio::Token,
1380            interests: mio::Interest,
1381        ) -> io::Result<()> 
1382        {
1383            self.usc.register(registry, token, interests)
1384        }
1385    
1386        fn reregister(
1387            &mut self,
1388            registry: &mio::Registry,
1389            token: mio::Token,
1390            interests: mio::Interest,
1391        ) -> io::Result<()> 
1392        {
1393            self.usc.reregister(registry, token, interests)
1394        }
1395    
1396        fn deregister(&mut self, registry: &mio::Registry) -> io::Result<()> 
1397        {
1398            self.usc.deregister(registry)
1399        }
1400    }
1401}
1402
1403#[cfg(feature = "xio-rs")]
1404pub mod xio_non_blk_conn_enabled
1405{
1406    use xio_rs::{EsInterfaceRegistry, XioChannel, XioEventPipe, XioEventUid, XioResult, event_registry::XioRegistry};
1407
1408    use super::NonblockingUnixSeqpacketConn;
1409
1410    impl<ESSR: EsInterfaceRegistry> XioEventPipe<ESSR, Self> for NonblockingUnixSeqpacketConn
1411    {
1412        fn connect_event_pipe(&mut self, ess: &XioRegistry<ESSR>, ev_uid: XioEventUid, channel: XioChannel) -> XioResult<()> 
1413        {
1414            self.usc.connect_event_pipe(ess, ev_uid, channel)
1415        }
1416    
1417        fn modify_event_pipe(&mut self, ess: &XioRegistry<ESSR>, ev_uid: XioEventUid, channel: XioChannel) -> XioResult<()> 
1418        {
1419            self.usc.modify_event_pipe(ess, ev_uid, channel)
1420        }
1421    
1422        fn disconnect_event_pipe(&mut self, ess: &XioRegistry<ESSR>) -> XioResult<()> 
1423        {
1424            self.usc.disconnect_event_pipe(ess)
1425        }
1426    }
1427}
1428
1429// can't Deref<Target=UnixSeqpacketConn> because that would include try_clone()
1430// and later set_(read|write)_timeout()
1431impl NonblockingUnixSeqpacketConn 
1432{
1433    /// Connects to an unix seqpacket server listening at `path`.
1434    ///
1435    /// This is a wrapper around [`connect_unix_addr()`](#method.connect_unix_addr)
1436    /// for convenience and compatibility with std.
1437    pub 
1438    fn connect<P: AsRef<Path>>(path: P) -> Result<Self, io::Error> 
1439    {
1440        let addr = UnixSocketAddr::from_path(&path)?;
1441
1442        return Self::connect_unix_addr(&addr);
1443    }
1444
1445    /// Connects to an unix seqpacket server listening at `addr`.
1446    pub 
1447    fn connect_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error> 
1448    {
1449        let socket = Socket::<SocketSeqPkt>::new(true)?;
1450        socket.set_unix_peer_addr(addr)?;
1451        
1452        return Ok(
1453            NonblockingUnixSeqpacketConn 
1454            {
1455                usc: UnixSeqpacketConn { fd: socket.into() }
1456            }
1457        );
1458    }
1459    
1460    /// Binds to an address before connecting to a listening seqpacet socket.
1461    pub 
1462    fn connect_from_to_unix_addr(from: &UnixSocketAddr,  to: &UnixSocketAddr) -> Result<Self, io::Error> 
1463    {
1464        let socket = Socket::<SocketSeqPkt>::new(true)?;
1465        socket.set_unix_local_addr(from)?;
1466        socket.set_unix_peer_addr(to)?;
1467        
1468        return Ok(
1469            NonblockingUnixSeqpacketConn 
1470            {
1471                usc: UnixSeqpacketConn { fd: socket.into() }
1472            }
1473        );
1474    }
1475
1476    /// Creates a pair of unix-domain seqpacket conneections connected to each other.
1477    ///
1478    /// # Examples
1479    ///
1480    #[cfg_attr(not(target_vendor="apple"), doc="```")]
1481    #[cfg_attr(target_vendor="apple", doc="```no_run")]
1482    /// let (a, b) = uds_fork::UnixSeqpacketConn::pair().unwrap();
1483    /// assert!(a.local_unix_addr().unwrap().is_unnamed());
1484    /// assert!(b.local_unix_addr().unwrap().is_unnamed());
1485    ///
1486    /// a.send(b"hello").unwrap();
1487    /// b.recv(&mut[0; 20]).unwrap();
1488    /// ```
1489    pub 
1490    fn pair() -> Result<(Self, Self), io::Error> 
1491    {
1492        let pair = Socket::<SocketSeqPkt>::pair(true)?;
1493        
1494        return Ok(
1495            (
1496                Self{ usc: UnixSeqpacketConn { fd: pair.0.into() } },
1497                Self{ usc: UnixSeqpacketConn { fd: pair.1.into() } },
1498            )
1499        );
1500    }
1501
1502    pub 
1503    fn try_clone(&self) -> Result<Self, io::Error> 
1504    {
1505        let cloned = Socket::<SocketSeqPkt>::try_clone_from(self)?;
1506
1507        return Ok(
1508            NonblockingUnixSeqpacketConn 
1509            {
1510                usc: UnixSeqpacketConn { fd: cloned.into() }
1511            }
1512        );
1513    }
1514}
1515
1516
1517/// A non-blocking unix domain listener for sequential-packet connections.
1518///
1519/// Differs from [`UnixSeqpacketListener`](../struct.UnixSeqpacketListener.html)
1520/// in that [`accept()`](struct.NonblockingUnixSeqpacketListener.html#method.accept)
1521/// returns non-blocking [connection sockets](struct.NonblockingUnixSeqpacketConn.html)
1522/// and doesn't block if no client `connect()`ions are pending.
1523///
1524/// # Registering with Xio (xio-rs) a feature = "xio-rs"
1525/// 
1526/// A `XioEventPipe` is implemented on this function. See [UnixSeqpacketListener]
1527/// for an examples.
1528/// 
1529/// See examples below.
1530/// 
1531/// # Registering with Mio (mio) a feature = "mio"
1532/// 
1533/// A `Source` is implemented on the instance. See [UnixSeqpacketListener]
1534/// for an examples.
1535///
1536/// # Examples
1537///
1538#[cfg_attr(not(target_vendor="apple"), doc="```")]
1539#[cfg_attr(target_vendor="apple", doc="```no_run")]
1540/// use uds_fork::nonblocking::{UnixSeqpacketListener, UnixSeqpacketConn};
1541/// use tempfile::TempDir;
1542/// use std::io::ErrorKind;
1543///
1544/// let dir = tempfile::tempdir().unwrap();
1545/// let mut file_path = dir.path().join("nonblocking_seqpacket_listener2.socket");
1546/// 
1547/// let listener = UnixSeqpacketListener::bind(&file_path)
1548///     .expect("Cannot create nonblocking seqpacket listener");
1549///
1550/// // doesn't block if no connections are waiting:
1551/// assert_eq!(listener.accept_unix_addr().unwrap_err().kind(), ErrorKind::WouldBlock);
1552///
1553/// // returned connections are nonblocking:
1554/// let _client = UnixSeqpacketConn::connect(&file_path).unwrap();
1555/// let (conn, _addr) = listener.accept_unix_addr().unwrap();
1556/// assert_eq!(conn.recv(&mut[0u8; 20]).unwrap_err().kind(), ErrorKind::WouldBlock);
1557/// ```
1558#[derive(Debug)]
1559#[repr(transparent)]
1560pub struct NonblockingUnixSeqpacketListener 
1561{
1562    usl: UnixSeqpacketListener,
1563}
1564
1565impl From<OwnedFd> for NonblockingUnixSeqpacketListener
1566{
1567    fn from(ofd: OwnedFd) -> Self 
1568    {
1569        let usl = UnixSeqpacketListener::from(ofd);
1570        usl.set_nonblocking(true).unwrap();
1571
1572        return Self{ usl };
1573    }
1574}
1575
1576impl FromRawFd for NonblockingUnixSeqpacketListener
1577{
1578    unsafe 
1579    fn from_raw_fd(fd: RawFd) -> Self 
1580    {
1581        let usl = unsafe{ UnixSeqpacketListener::from_raw_fd(fd) };
1582        usl.set_nonblocking(true).unwrap();
1583
1584        return Self{ usl };
1585    }
1586}
1587
1588
1589impl From<NonblockingUnixSeqpacketListener> for OwnedFd
1590{
1591    fn from(value: NonblockingUnixSeqpacketListener) -> Self 
1592    {
1593        return value.usl.fd;
1594    }
1595}
1596
1597
1598impl AsRawFd for NonblockingUnixSeqpacketListener
1599{
1600    fn as_raw_fd(&self) -> RawFd 
1601    {
1602        self.usl.as_raw_fd()
1603    }
1604}
1605
1606impl IntoRawFd for NonblockingUnixSeqpacketListener
1607{
1608    fn into_raw_fd(self) -> RawFd 
1609    {
1610        self.usl.into_raw_fd()
1611    }
1612}
1613
1614impl AsFd for NonblockingUnixSeqpacketListener
1615{
1616    fn as_fd(&self) -> BorrowedFd<'_> 
1617    {
1618        self.usl.as_fd()
1619    }
1620}
1621
1622
1623impl Deref for NonblockingUnixSeqpacketListener
1624{
1625    type Target = UnixSeqpacketListener;
1626
1627    fn deref(&self) -> &Self::Target 
1628    {
1629        &self.usl
1630    }
1631}
1632
1633impl DerefMut for NonblockingUnixSeqpacketListener
1634{
1635    fn deref_mut(&mut self) -> &mut Self::Target 
1636    {
1637        &mut self.usl
1638    }
1639}
1640
1641impl NonblockingUnixSeqpacketListener 
1642{
1643    /// Creates a socket that listens for seqpacket connections on the specified socket file.
1644    pub 
1645    fn bind<P: AsRef<Path>>(path: P) -> Result<Self, io::Error> 
1646    {
1647        let addr = UnixSocketAddr::from_path(&path)?;
1648
1649        return Self::bind_unix_addr(&addr);
1650    }
1651
1652    /// Creates a socket that listens for seqpacket connections on the specified address.
1653    pub 
1654    fn bind_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error> 
1655    {
1656        let socket = Socket::<SocketSeqPkt>::new(true)?;
1657        socket.set_unix_local_addr(addr)?;
1658        socket.start_listening()?;
1659
1660        return Ok( Self{ usl: UnixSeqpacketListener{ fd: socket.into() }} );
1661    }
1662
1663    /// Accepts a non-blocking connection, non-blockingly.
1664    ///
1665    /// # Examples
1666    ///
1667    /// Doesn't block if no connections are waiting:
1668    ///
1669    #[cfg_attr(not(target_vendor="apple"), doc="```")]
1670    #[cfg_attr(target_vendor="apple", doc="```no_run")]
1671    /// # use uds_fork::nonblocking::UnixSeqpacketListener;
1672    /// # use std::io::ErrorKind;
1673    /// # use tempfile::TempDir;
1674    /// 
1675    /// let dir = tempfile::tempdir().unwrap();
1676    /// let mut file_path = dir.path().join("nonblocking_seqpacket_listener3.socket");
1677    /// 
1678    /// let listener = UnixSeqpacketListener::bind(&file_path)
1679    ///     .expect("Cannot create nonblocking seqpacket listener");
1680    /// assert_eq!(listener.accept_unix_addr().unwrap_err().kind(), ErrorKind::WouldBlock);
1681    /// ```
1682    pub 
1683    fn accept_unix_addr(&self) -> Result<(NonblockingUnixSeqpacketConn, UnixSocketAddr), io::Error> 
1684    {
1685        let (socket, addr) = Socket::<SocketSeqPkt>::accept_from(&self, true)?;
1686        let conn = NonblockingUnixSeqpacketConn { usc: UnixSeqpacketConn{ fd: socket.into() }};
1687        
1688        return Ok((conn, addr));
1689    }
1690}
1691
1692#[cfg(feature = "mio")]
1693pub mod mio_non_blk_listener_enabled
1694{
1695    use std::{io, os::fd::AsRawFd};
1696
1697    use mio::{event::Source, unix::SourceFd};
1698    use super::NonblockingUnixSeqpacketListener;
1699
1700    impl Source for NonblockingUnixSeqpacketListener
1701    {
1702        fn register(
1703            &mut self,
1704            registry: &mio::Registry,
1705            token: mio::Token,
1706            interests: mio::Interest,
1707        ) -> io::Result<()> 
1708        {
1709            self.usl.register(registry, token, interests)
1710        }
1711    
1712        fn reregister(
1713            &mut self,
1714            registry: &mio::Registry,
1715            token: mio::Token,
1716            interests: mio::Interest,
1717        ) -> io::Result<()> 
1718        {
1719            self.usl.reregister(registry, token, interests)
1720        }
1721    
1722        fn deregister(&mut self, registry: &mio::Registry) -> io::Result<()> 
1723        {
1724            self.usl.deregister(registry)
1725        }
1726    }
1727}
1728
1729#[cfg(feature = "xio-rs")]
1730pub mod xio_non_blk_listener_enabled
1731{
1732    use xio_rs::{EsInterfaceRegistry, XioChannel, XioEventPipe, XioEventUid, XioResult, event_registry::XioRegistry};
1733
1734    use super::NonblockingUnixSeqpacketListener;
1735
1736    impl<ESSR: EsInterfaceRegistry> XioEventPipe<ESSR, Self> for NonblockingUnixSeqpacketListener
1737    {
1738        fn connect_event_pipe(&mut self, ess: &XioRegistry<ESSR>, ev_uid: XioEventUid, channel: XioChannel) -> XioResult<()> 
1739        {
1740 
1741            self.usl.connect_event_pipe(ess, ev_uid, channel)
1742        }
1743    
1744        fn modify_event_pipe(&mut self, ess: &XioRegistry<ESSR>, ev_uid: XioEventUid, channel: XioChannel) -> XioResult<()> 
1745        {
1746            self.usl.modify_event_pipe(ess, ev_uid, channel)
1747        }
1748    
1749        fn disconnect_event_pipe(&mut self, ess: &XioRegistry<ESSR>) -> XioResult<()> 
1750        {
1751            self.usl.disconnect_event_pipe(ess)
1752        }
1753    }
1754}