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