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, &[], 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)],
435 fds.iter().map(|fd| fd.as_raw_fd()).collect::<Vec<RawFd>>().as_slice(), None)
436 }
437
438 /// Sends a packet with associated file descriptors. Raw descriptors.
439 pub unsafe
440 fn send_fds_raw(&self, bytes: &[u8], fds: &[RawFd]) -> Result<usize, io::Error>
441 {
442 send_ancillary(&self, None, MSG_EOR, &[IoSlice::new(bytes)],
443 fds, None)
444 }
445
446 /// Receives a packet and associated file descriptors. A legacy method which
447 /// was in this crate since its author added it.
448 ///
449 /// A FDs are placed into Vec with the specific capacity.
450 ///
451 /// A FDs will be truncated if the capacity is not large enough.
452 ///
453 /// See a
454 #[cfg_attr(not(feature="unsatable_preview"), doc="Self::recv_vectored_with_ancillary")]
455 #[cfg_attr(feature="unsatable_preview", doc="[Self::recv_vectored_with_ancillary]")]
456 /// for a new stdlib approach.
457 ///
458 /// # Returns
459 ///
460 /// * 0 - amount of bytes received
461 ///
462 /// * 1 - is truncated
463 ///
464 /// * 2 - a fd buffer length
465 pub
466 fn recv_fds(&self, byte_buffer: &mut[u8], fd_buf: &mut Vec<OwnedFd>) -> Result<(usize, bool, usize), io::Error>
467 {
468 recv_fds(&self, None, &mut[IoSliceMut::new(byte_buffer)], fd_buf)
469 }
470
471 /// Receives a packet and associated file descriptors. A legacy method which
472 /// was in this crate since its author added it.
473 ///
474 /// A FDs are placed into pre-allocated mutable slice. Received valies are stored
475 /// in reception sequence. The first [Option::None] does mean the rest are None too.
476 ///
477 /// A FDs will be truncated if the length of the slice is not enough.
478 ///
479 /// See a
480 #[cfg_attr(not(feature="unsatable_preview"), doc="Self::recv_vectored_with_ancillary")]
481 #[cfg_attr(feature="unsatable_preview", doc="[Self::recv_vectored_with_ancillary]")]
482 /// for a new stdlib approach.
483 ///
484 /// # Returns
485 ///
486 /// * 0 - amount of bytes received
487 ///
488 /// * 1 - is truncated
489 ///
490 /// * 2 - a fd buffer length
491 pub
492 fn recv_slice_fds(&self, buf: &mut[u8], fd_buf: &mut [Option<OwnedFd>]) -> Result<(usize, usize), io::Error>
493 {
494 recv_slice_fds(self, None, &mut[IoSliceMut::new(buf)], fd_buf)
495 .map(|(bytes, _, fds)| (bytes, fds) )
496 }
497
498 /// A old (provided by crate, legacy) parser of the ancillary data.
499 ///
500 /// Returns an iterator to the ancillary data.
501 ///
502 /// # Returns
503 ///
504 /// A [Result] is returned with tuple:
505 ///
506 /// * `0` - a count of bytes.
507 ///
508 /// * `1` - [Ancillary] a ancillary iterator.
509 ///
510 pub
511 fn recv_vectored_ancillary<'a>(
512 &self,
513 flags: i32,
514 bufs: &mut [IoSliceMut<'_>],
515 ancillary: &'a mut AncillaryBuf,
516 ) -> Result<(usize, Ancillary<'a>), io::Error>
517 {
518 recv_ancillary(self, None, flags, bufs, ancillary)
519 }
520
521 /// A new (provided by std) parser of the ancillary data
522 ///
523 /// Unstable and extremely unsafe. Rust devs did not provide an access
524 /// to the internal reference to the buffer in [SocketAncillary], so
525 /// there is no access to the buffer and its length. For this reason a
526 /// very bad approach to overcome this is used.
527 ///
528 /// > Receives data and ancillary data from socket.
529 /// >
530 /// > On success, returns the number of bytes read, if the data was
531 /// > truncated and the address from whence the msg came.
532 ///
533 /// # Returns
534 ///
535 /// A [Result] is returned with tuple:
536 ///
537 /// * `0` - a count of bytes.
538 ///
539 /// * `1` - was msg truncated
540 ///
541 /// # Example
542 ///
543 /// ```ignore
544 /// let mut buf = [0_u8; 256];
545 /// let bufs = &mut [IoSliceMut::new(&mut buf[..])];
546 ///
547 /// let mut ancillary_buffer = [0; 128];
548 /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
549 ///
550 /// let (count, trunc) =
551 /// freya_side_b.recv_vectored_with_ancillary(bufs, &mut ancillary).unwrap();
552 /// ```
553 #[cfg(feature = "unsatable_preview")]
554 pub
555 fn recv_vectored_with_ancillary(
556 &self,
557 flags: i32,
558 bufs: &mut [IoSliceMut<'_>],
559 ancillary: &mut SocketAncillary<'_>,
560 ) -> Result<(usize, bool), io::Error>
561 {
562 unsafe { recv_ancillary_std(&self, flags, bufs, ancillary) }
563 .map(|(count, trunc, _)| (count, trunc))
564 }
565
566 /// A new (provided by std) parser of the ancillary data
567 ///
568 /// Unstable and extremely unsafe. Rust devs did not provide an access
569 /// to the internal reference to the buffer in [SocketAncillary], so
570 /// there is no access to the buffer and its length. For this reason a
571 /// very bad approach to overcome this is used.
572 ///
573 /// > Receives data and ancillary data providing the source of msg.
574 /// >
575 /// > On success, returns the number of bytes read, if the data was
576 /// > truncated and the address from whence the msg came.
577 ///
578 /// # Returns
579 ///
580 /// A [Result] is returned with tuple:
581 ///
582 /// * `0` - a count of bytes.
583 ///
584 /// * `1` - was msg truncated
585 ///
586 /// * `2` - a source address
587 ///
588 /// # Example
589 ///
590 /// ```ignore
591 /// let mut buf = [0_u8; 256];
592 /// let bufs = &mut [IoSliceMut::new(&mut buf[..])];
593 ///
594 /// let mut ancillary_buffer = [0; 128];
595 /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
596 ///
597 /// let (count, trunc, from) =
598 /// freya_side_b.recv_vectored_with_ancillary(bufs, &mut ancillary).unwrap();
599 /// ```
600 #[cfg(feature = "unsatable_preview")]
601 pub
602 fn recv_vectored_with_ancillary_from(
603 &self,
604 flags: i32,
605 bufs: &mut [IoSliceMut<'_>],
606 ancillary: &mut SocketAncillary<'_>,
607 ) -> Result<(usize, bool, UnixSocketAddr), io::Error>
608 {
609 unsafe { recv_ancillary_std(&self, flags, bufs, ancillary) }
610 }
611
612 /// A new (provided by std) parser of the ancillary data.
613 ///
614 /// Rust #![feature(unix_socket_ancillary_data)]
615 ///
616 /// Unstable and extremely unsafe. Rust devs did not provide an access
617 /// to the internal reference to the buffer in [SocketAncillary], so
618 /// there is no access to the buffer and its length. For this reason a
619 /// very bad approach to overcome this is used.
620 ///
621 /// > Sends data and ancillary data on the current socket.
622 /// >
623 /// > On success, returns the number of bytes written.
624 ///
625 /// Crate: feature = unsatable_preview
626 ///
627 /// # Arguments
628 ///
629 /// * `flags` - a flags which are passed to [libc::recvmsg].
630 ///
631 /// * `bufs` - an [IoSlice] buffers.
632 ///
633 /// * `ancillary` - packed ancillary data
634 ///
635 /// # Example
636 ///
637 /// ```ignore
638 /// let buf0 = b"Here I come";
639 /// let mut ancillary_buffer = [0; 128];
640 /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
641 ///
642 /// let fds = [OwnedFd::from(a).into_raw_fd(), OwnedFd::from(b).into_raw_fd(), OwnedFd::from(aa).into_raw_fd()];
643 ///
644 /// ancillary.add_fds(&fds[..]);
645 ///
646 /// freya_side_a.send_vectored_with_ancillary(&[IoSlice::new(buf0.as_slice())], &mut ancillary)
647 /// .expect("send stdin, stdout and stderr");
648 ///
649 /// ```
650 #[cfg(feature = "unsatable_preview")]
651 pub
652 fn send_vectored_with_ancillary(
653 &self,
654 flags: i32,
655 bufs: &[IoSlice<'_>],
656 ancillary: &mut SocketAncillary<'_>,
657 ) -> io::Result<usize>
658 {
659 unsafe { send_ancillary_std(&self, None, flags, bufs, ancillary) }
660 }
661
662 /// A new (provided by std) parser of the ancillary data.
663 ///
664 /// Rust #![feature(unix_socket_ancillary_data)]
665 ///
666 /// Unstable and extremely unsafe. Rust devs did not provide an access
667 /// to the internal reference to the buffer in [SocketAncillary], so
668 /// there is no access to the buffer and its length. For this reason a
669 /// very bad approach to overcome this is used.
670 ///
671 /// > Sends data and ancillary data on the socket to the specified address.
672 /// >
673 /// > On success, returns the number of bytes written.
674 ///
675 /// Crate: feature = unsatable_preview
676 ///
677 /// # Arguments
678 ///
679 /// * `flags` - a flags which are passed to [libc::recvmsg].
680 ///
681 /// * `to` - a destination.
682 ///
683 /// * `bufs` - an [IoSlice] buffers.
684 ///
685 /// * `ancillary` - packed ancillary data
686 ///
687 /// # Example
688 ///
689 /// ```ignore
690 /// let buf0 = b"Here I come";
691 /// let mut ancillary_buffer = [0; 128];
692 /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
693 ///
694 /// let fds =
695 /// [OwnedFd::from(a).into_raw_fd(), OwnedFd::from(b).into_raw_fd(), OwnedFd::from(aa).into_raw_fd()];
696 ///
697 /// ancillary.add_fds(&fds[..]);
698 ///
699 /// let dst = UnixSocketAddr::from_abstract("@test");
700 ///
701 /// freya_side_a
702 /// .send_vectored_with_ancillary_to(0, &dst, &[IoSlice::new(buf0.as_slice())], &mut ancillary)
703 /// .expect("send stdin, stdout and stderr");
704 ///
705 /// ```
706 #[cfg(feature = "unsatable_preview")]
707 pub
708 fn send_vectored_with_ancillary_to(
709 &self,
710 flags: i32,
711 to: &UnixSocketAddr,
712 bufs: &[IoSlice<'_>],
713 ancillary: &mut SocketAncillary<'_>,
714 ) -> io::Result<usize>
715 {
716 unsafe { send_ancillary_std(&self, Some(to), flags, bufs, ancillary) }
717 }
718
719 /// Receives a packet without removing it from the incoming queue.
720 ///
721 /// # Examples
722 ///
723 #[cfg_attr(not(target_vendor="apple"), doc="```")]
724 #[cfg_attr(target_vendor="apple", doc="```no_run")]
725 /// let (a, b) = uds_fork::UnixSeqpacketConn::pair().unwrap();
726 /// a.send(b"hello").unwrap();
727 /// let mut buf = [0u8; 10];
728 /// assert_eq!(b.peek(&mut buf[..1]).unwrap(), 1);
729 /// assert_eq!(&buf[..2], &[b'h', 0]);
730 /// assert_eq!(b.peek(&mut buf).unwrap(), 5);
731 /// assert_eq!(&buf[..5], b"hello");
732 /// assert_eq!(b.recv(&mut buf).unwrap(), 5);
733 /// assert_eq!(&buf[..5], b"hello");
734 /// ```
735 pub
736 fn peek(&self, buffer: &mut[u8]) -> Result<usize, io::Error>
737 {
738 let ptr = buffer.as_ptr() as *mut c_void;
739 let flags = MSG_NOSIGNAL | MSG_PEEK;
740 let received = cvt_r!(unsafe { recv(self.fd.as_raw_fd(), ptr, buffer.len(), flags) })?;
741
742 return Ok(received as usize);
743 }
744
745 /// Receives a packet without removing it from the incoming queue.
746 ///
747 /// The returned `bool` indicates whether the packet was truncated due to
748 /// the combined buffers being too small.
749 pub
750 fn peek_vectored(&self, buffers: &mut[IoSliceMut]) -> Result<(usize, bool), io::Error>
751 {
752 recv_ancillary(&self, None, MSG_PEEK, buffers, &mut[])
753 .map(|(bytes, ancillary)| (bytes, ancillary.message_truncated()) )
754 }
755
756 /// Returns the value of the `SO_ERROR` option.
757 ///
758 /// This might only provide errors generated from nonblocking `connect()`s,
759 /// which this library doesn't support. It is therefore unlikely to be
760 /// useful, but is provided for parity with stream counterpart in std.
761 ///
762 /// # Examples
763 ///
764 #[cfg_attr(not(target_vendor="apple"), doc="```")]
765 #[cfg_attr(target_vendor="apple", doc="```no_run")]
766 /// let (a, b) = uds_fork::UnixSeqpacketConn::pair().unwrap();
767 /// drop(b);
768 ///
769 /// assert!(a.send(b"anyone there?").is_err());
770 /// assert!(a.take_error().unwrap().is_none());
771 /// ```
772 pub
773 fn take_error(&self) -> Result<Option<io::Error>, io::Error>
774 {
775 take_error(&self)
776 }
777
778
779 /// Creates a new file descriptor also pointing to this side of this connection.
780 ///
781 /// # Examples
782 ///
783 /// Both new and old can send and receive, and share queues:
784 ///
785 #[cfg_attr(not(target_vendor="apple"), doc="```")]
786 #[cfg_attr(target_vendor="apple", doc="```no_run")]
787 /// let (a1, b) = uds_fork::nonblocking::UnixSeqpacketConn::pair().unwrap();
788 /// let a2 = a1.try_clone().unwrap();
789 ///
790 /// a1.send(b"first").unwrap();
791 /// a2.send(b"second").unwrap();
792 ///
793 /// let mut buf = [0u8; 20];
794 /// let len = b.recv(&mut buf).unwrap();
795 /// assert_eq!(&buf[..len], b"first");
796 /// b.send(b"hello first").unwrap();
797 /// let len = b.recv(&mut buf).unwrap();
798 /// assert_eq!(&buf[..len], b"second");
799 /// b.send(b"hello second").unwrap();
800 ///
801 /// let len = a2.recv(&mut buf).unwrap();
802 /// assert_eq!(&buf[..len], b"hello first");
803 /// let len = a1.recv(&mut buf).unwrap();
804 /// assert_eq!(&buf[..len], b"hello second");
805 /// ```
806 ///
807 /// Clone can still be used after the first one has been closed:
808 ///
809 #[cfg_attr(not(target_vendor="apple"), doc="```")]
810 #[cfg_attr(target_vendor="apple", doc="```no_run")]
811 /// let (a, b1) = uds_fork::nonblocking::UnixSeqpacketConn::pair().unwrap();
812 /// a.send(b"hello").unwrap();
813 ///
814 /// let b2 = b1.try_clone().unwrap();
815 /// drop(b1);
816 /// assert_eq!(b2.recv(&mut[0; 10]).unwrap(), "hello".len());
817 /// ```
818 pub
819 fn try_clone(&self) -> Result<Self, io::Error>
820 {
821 let cloned = Socket::<SocketSeqPkt>::try_clone_from(self)?;
822
823 return Ok(UnixSeqpacketConn { fd: cloned.into() });
824 }
825
826 /// Sets the read timeout to the duration specified.
827 ///
828 /// If the value specified is `None`, then `recv()` and its variants will
829 /// block indefinitely.
830 /// An error is returned if the duration is zero.
831 ///
832 /// The duration is rounded to microsecond precission.
833 /// Currently it's rounded down except if that would make it all zero.
834 ///
835 /// # Operating System Support
836 ///
837 /// On Illumos (and pressumably also Solaris) timeouts appears not to work
838 /// for unix domain sockets.
839 ///
840 /// # Examples
841 ///
842 #[cfg_attr(not(any(target_vendor="apple", target_os="illumos", target_os="solaris")), doc="```")]
843 #[cfg_attr(any(target_vendor="apple", target_os="illumos", target_os="solaris"), doc="```no_run")]
844 /// use std::io::ErrorKind;
845 /// use std::time::Duration;
846 /// use uds_fork::UnixSeqpacketConn;
847 ///
848 /// let (a, b) = UnixSeqpacketConn::pair().unwrap();
849 /// a.set_read_timeout(Some(Duration::new(0, 2_000_000))).unwrap();
850 /// let error = a.recv(&mut[0; 1024]).unwrap_err();
851 /// assert_eq!(error.kind(), ErrorKind::WouldBlock);
852 /// ```
853 pub
854 fn set_read_timeout(&self, timeout: Option<Duration>) -> Result<(), io::Error>
855 {
856 set_timeout(self.fd.as_fd(), TimeoutDirection::Read, timeout)
857 }
858
859 /// Returns the read timeout of this socket.
860 ///
861 /// `None` is returned if there is no timeout.
862 ///
863 /// Note that subsecond parts might have been be rounded by the OS
864 /// (in addition to the rounding to microsecond in `set_read_timeout()`).
865 ///
866 /// # Examples
867 ///
868 #[cfg_attr(not(any(target_vendor="apple", target_os="illumos", target_os="solaris")), doc="```")]
869 #[cfg_attr(any(target_vendor="apple", target_os="illumos", target_os="solaris"), doc="```no_run")]
870 /// use uds_fork::UnixSeqpacketConn;
871 /// use std::time::Duration;
872 ///
873 /// let timeout = Some(Duration::new(2, 0));
874 /// let conn = UnixSeqpacketConn::pair().unwrap().0;
875 /// conn.set_read_timeout(timeout).unwrap();
876 /// assert_eq!(conn.read_timeout().unwrap(), timeout);
877 /// ```
878 pub
879 fn read_timeout(&self) -> Result<Option<Duration>, io::Error>
880 {
881 get_timeout(self.fd.as_fd(), TimeoutDirection::Read)
882 }
883
884 /// Sets the write timeout to the duration specified.
885 ///
886 /// If the value specified is `None`, then `send()` and its variants will
887 /// block indefinitely.
888 /// An error is returned if the duration is zero.
889 ///
890 /// # Operating System Support
891 ///
892 /// On Illumos (and pressumably also Solaris) timeouts appears not to work
893 /// for unix domain sockets.
894 ///
895 /// # Examples
896 ///
897 #[cfg_attr(not(any(target_vendor="apple", target_os="illumos", target_os="solaris")), doc="```")]
898 #[cfg_attr(any(target_vendor="apple", target_os="illumos", target_os="solaris"), doc="```no_run")]
899 /// # use std::io::ErrorKind;
900 /// # use std::time::Duration;
901 /// # use uds_fork::UnixSeqpacketConn;
902 /// #
903 /// let (conn, _other) = UnixSeqpacketConn::pair().unwrap();
904 /// conn.set_write_timeout(Some(Duration::new(0, 500 * 1000))).unwrap();
905 /// loop {
906 /// if let Err(e) = conn.send(&[0; 1000]) {
907 /// assert_eq!(e.kind(), ErrorKind::WouldBlock, "{}", e);
908 /// break
909 /// }
910 /// }
911 /// ```
912 pub
913 fn set_write_timeout(&self, timeout: Option<Duration>)-> Result<(), io::Error>
914 {
915 set_timeout(self.fd.as_fd(), TimeoutDirection::Write, timeout)
916 }
917
918 /// Returns the write timeout of this socket.
919 ///
920 /// `None` is returned if there is no timeout.
921 ///
922 /// # Examples
923 ///
924 #[cfg_attr(not(target_vendor="apple"), doc="```")]
925 #[cfg_attr(target_vendor="apple", doc="```no_run")]
926 /// let conn = uds_fork::UnixSeqpacketConn::pair().unwrap().0;
927 /// assert!(conn.write_timeout().unwrap().is_none());
928 /// ```
929 pub
930 fn write_timeout(&self) -> Result<Option<Duration>, io::Error>
931 {
932 get_timeout(self.fd.as_fd(), TimeoutDirection::Write)
933 }
934
935 /// Enables or disables nonblocking mode.
936 ///
937 /// Consider using the nonblocking variant of this type instead.
938 /// This method mainly exists for feature parity with std's `UnixStream`.
939 ///
940 /// # Examples
941 ///
942 /// Trying to receive when there are no packets waiting:
943 ///
944 #[cfg_attr(not(target_vendor="apple"), doc="```")]
945 #[cfg_attr(target_vendor="apple", doc="```no_run")]
946 /// # use std::io::ErrorKind;
947 /// # use uds_fork::UnixSeqpacketConn;
948 /// let (a, b) = UnixSeqpacketConn::pair().expect("create seqpacket pair");
949 /// a.set_nonblocking(true).unwrap();
950 /// assert_eq!(a.recv(&mut[0; 20]).unwrap_err().kind(), ErrorKind::WouldBlock);
951 /// ```
952 ///
953 /// Trying to send when the OS buffer for the connection is full:
954 ///
955 #[cfg_attr(not(target_vendor="apple"), doc="```")]
956 #[cfg_attr(target_vendor="apple", doc="```no_run")]
957 /// # use std::io::ErrorKind;
958 /// # use uds_fork::UnixSeqpacketConn;
959 /// let (a, b) = UnixSeqpacketConn::pair().expect("create seqpacket pair");
960 /// a.set_nonblocking(true).unwrap();
961 /// loop {
962 /// if let Err(error) = a.send(&[b'#'; 1000]) {
963 /// assert_eq!(error.kind(), ErrorKind::WouldBlock);
964 /// break;
965 /// }
966 /// }
967 /// ```
968 pub
969 fn set_nonblocking(&self, nonblocking: bool) -> Result<(), io::Error>
970 {
971 set_nonblocking(&self, nonblocking)
972 }
973
974 /// Shuts down the read, write, or both halves of this connection.
975 pub
976 fn shutdown(&self, how: Shutdown) -> io::Result<()>
977 {
978 let how =
979 match how
980 {
981 Shutdown::Read => libc::SHUT_RD,
982 Shutdown::Write => libc::SHUT_WR,
983 Shutdown::Both => libc::SHUT_RDWR,
984 };
985
986 unsafe { cvt!(libc::shutdown(self.as_raw_fd(), how)) }?;
987
988 return Ok(());
989 }
990
991 fn read_string(&self, buf: &mut String) -> io::Result<usize>
992 {
993 let mut read_size: u32 = 0;
994
995 let _ =
996 cvt!(unsafe { libc::ioctl(self.fd.as_raw_fd(), libc::FIONREAD, &mut read_size) })?;
997
998 let mut byte_buf = vec![0_u8; read_size as usize];
999
1000 let _ = self.recv(&mut byte_buf)?;
1001
1002 let str_slice =
1003 str::from_utf8(&byte_buf)
1004 .map_err(|e|
1005 io::Error::new(ErrorKind::Other, e)
1006 )?;
1007
1008 buf.push_str(str_slice);
1009
1010 return Ok(byte_buf.len());
1011 }
1012}
1013
1014impl io::Read for UnixSeqpacketConn
1015{
1016 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize>
1017 {
1018 self.recv(buf)
1019 }
1020
1021 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize>
1022 {
1023 self.recv_vectored(bufs).map(|(n, _)| n)
1024 }
1025
1026 fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize>
1027 {
1028 self.read_string(buf)
1029 }
1030}
1031
1032impl<'a> io::Read for &'a UnixSeqpacketConn
1033{
1034 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize>
1035 {
1036 self.recv(buf)
1037 }
1038
1039 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize>
1040 {
1041 self.recv_vectored(bufs).map(|(n, _)| n)
1042 }
1043
1044 fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize>
1045 {
1046 self.read_string(buf)
1047 }
1048}
1049
1050impl io::Write for UnixSeqpacketConn
1051{
1052 fn write(&mut self, buf: &[u8]) -> io::Result<usize>
1053 {
1054 self.send(buf)
1055 }
1056
1057 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize>
1058 {
1059 self.send_vectored(bufs)
1060 }
1061
1062 fn flush(&mut self) -> io::Result<()>
1063 {
1064 return Ok(());
1065 }
1066}
1067
1068/// An unix domain listener for sequential packet connections.
1069///
1070/// See [`UnixSeqpacketConn`](struct.UnixSeqpacketConn.html) for a description
1071/// of this type of connection.
1072///
1073/// # Registering with Xio (xio-rs) a feature = "xio-rs"
1074///
1075/// A `XioEventPipe` is implemented on this function. During initial registration
1076/// an attempt set `nonblocking` mode is performed during initial registration.
1077///
1078/// See examples below.
1079///
1080/// # Registering with Mio (mio) a feature = "mio"
1081///
1082/// A `Source` is implemented on the instance.During initial registration
1083/// an attempt set `nonblocking` mode is performed during initial registration.
1084///
1085/// # Examples
1086///
1087#[cfg_attr(not(target_vendor="apple"), doc="```")]
1088#[cfg_attr(target_vendor="apple", doc="```no_run")]
1089/// use tempfile::TempDir;
1090///
1091/// let dir = tempfile::tempdir().unwrap();
1092/// let mut file_path = dir.path().join("seqpacket_listener.socket");
1093///
1094/// let listener = uds_fork::UnixSeqpacketListener::bind(&file_path)
1095/// .expect("Create seqpacket listener");
1096/// let _client = uds_fork::UnixSeqpacketConn::connect(&file_path).unwrap();
1097/// let (conn, _addr) = listener.accept_unix_addr().unwrap();
1098/// conn.send(b"Welcome").unwrap();
1099/// ```
1100///
1101/// ### Xio
1102///
1103/// ```ignore
1104/// let listener = uds_fork::UnixSeqpacketListener::bind(file_path).unwrap();
1105///
1106/// let mut reg = XioPollRegistry::<ESS>::new().unwrap();
1107/// let mut event_buf = XioPollRegistry::<ESS>::allocate_events(128.try_into().unwrap());
1108///
1109/// // either
1110/// let a_wrapped =
1111/// reg.get_registry()
1112/// .en_register_wrap(listener, XioEventUid::manual(1), XioChannel::INPUT)
1113/// .unwrap();
1114///
1115/// // or
1116/// reg.get_registry()
1117/// .en_register&mut listener, XioEventUid::manual(1), XioChannel::INPUT)
1118/// .unwrap();
1119///
1120/// // so depending on the method, use either:
1121/// a_wrapped.inner();
1122///
1123/// // or continue using a directly
1124/// ```
1125///
1126/// ### Mio:
1127///
1128/// ```ignore
1129/// let listener = uds_fork::UnixSeqpacketListener::bind(file_path).unwrap();
1130///
1131/// let mut poll = Poll::new().expect("create mio poll");
1132/// let mut events = Events::with_capacity(10);
1133///
1134/// poll.registry()
1135/// .register(&mut listener, Token(1), Interest::READABLE)
1136/// .unwrap();
1137/// // ...
1138/// ```
1139#[derive(Debug)]
1140#[repr(transparent)]
1141pub struct UnixSeqpacketListener
1142{
1143 fd: OwnedFd
1144}
1145
1146
1147impl From<OwnedFd> for UnixSeqpacketListener
1148{
1149 fn from(ofd: OwnedFd) -> Self
1150 {
1151 let sa_fam = get_socket_family(&ofd).unwrap();
1152 let sa_type = get_socket_type(&ofd).unwrap() & 0x00000FFF;
1153
1154 if sa_fam as i32 != libc::AF_UNIX || sa_type != libc::SOCK_SEQPACKET
1155 {
1156 panic!("assertion trap: provided FD is not AF_UNIX & SOCK_SEQPACKET, {} {}",
1157 sa_fam, sa_type);
1158 }
1159
1160 return UnixSeqpacketListener{ fd: ofd };
1161 }
1162}
1163
1164impl From<UnixSeqpacketListener> for OwnedFd
1165{
1166 fn from(value: UnixSeqpacketListener) -> Self
1167 {
1168 return value.fd;
1169 }
1170}
1171
1172impl FromRawFd for UnixSeqpacketListener
1173{
1174 unsafe
1175 fn from_raw_fd(fd: RawFd) -> Self
1176 {
1177 UnixSeqpacketListener::from( unsafe { OwnedFd::from_raw_fd(fd) } )
1178 }
1179}
1180
1181impl AsRawFd for UnixSeqpacketListener
1182{
1183 fn as_raw_fd(&self) -> RawFd
1184 {
1185 self.fd.as_raw_fd()
1186 }
1187}
1188
1189impl IntoRawFd for UnixSeqpacketListener
1190{
1191 fn into_raw_fd(self) -> RawFd
1192 {
1193 self.fd.into_raw_fd()
1194 }
1195}
1196
1197impl AsFd for UnixSeqpacketListener
1198{
1199 fn as_fd(&self) -> BorrowedFd<'_>
1200 {
1201 self.fd.as_fd()
1202 }
1203}
1204
1205#[cfg(feature = "mio")]
1206pub mod mio_listener_enabled
1207{
1208 use std::{io, os::fd::AsRawFd};
1209
1210 use mio::{event::Source, unix::SourceFd};
1211 use crate::UnixSeqpacketListener;
1212
1213 impl Source for UnixSeqpacketListener
1214 {
1215 fn register(
1216 &mut self,
1217 registry: &mio::Registry,
1218 token: mio::Token,
1219 interests: mio::Interest,
1220 ) -> io::Result<()>
1221 {
1222 self.set_nonblocking(true)?;
1223
1224 SourceFd(&self.fd.as_raw_fd()).register(registry, token, interests)
1225 }
1226
1227 fn reregister(
1228 &mut self,
1229 registry: &mio::Registry,
1230 token: mio::Token,
1231 interests: mio::Interest,
1232 ) -> io::Result<()>
1233 {
1234 SourceFd(&self.fd.as_raw_fd()).reregister(registry, token, interests)
1235 }
1236
1237 fn deregister(&mut self, registry: &mio::Registry) -> io::Result<()>
1238 {
1239 SourceFd(&self.fd.as_raw_fd()).deregister(registry)
1240 }
1241 }
1242}
1243
1244#[cfg(feature = "xio-rs")]
1245pub mod xio_listener_enabled
1246{
1247 use xio_rs::{EsInterfaceRegistry, XioChannel, XioEventPipe, XioEventUid, XioResult, event_registry::XioRegistry};
1248
1249 use crate::UnixSeqpacketListener;
1250
1251 impl<ESSR: EsInterfaceRegistry> XioEventPipe<ESSR, Self> for UnixSeqpacketListener
1252 {
1253 fn connect_event_pipe(&mut self, ess: &XioRegistry<ESSR>, ev_uid: XioEventUid, channel: XioChannel) -> XioResult<()>
1254 {
1255 self.set_nonblocking(true)?;
1256
1257 ess.get_ev_sys().en_register(&self.fd, ev_uid, channel)
1258 }
1259
1260 fn modify_event_pipe(&mut self, ess: &XioRegistry<ESSR>, ev_uid: XioEventUid, channel: XioChannel) -> XioResult<()>
1261 {
1262 ess.get_ev_sys().re_register(&self.fd, ev_uid, channel)
1263 }
1264
1265 fn disconnect_event_pipe(&mut self, ess: &XioRegistry<ESSR>) -> XioResult<()>
1266 {
1267 ess.get_ev_sys().de_register(&self.fd)
1268 }
1269 }
1270}
1271
1272impl UnixSeqpacketListener
1273{
1274 /// Creates a socket that listens for seqpacket connections on the specified socket file.
1275 pub
1276 fn bind<P: AsRef<Path>>(path: P) -> Result<Self, io::Error>
1277 {
1278 let addr = UnixSocketAddr::from_path(path.as_ref())?;
1279
1280 return Self::bind_unix_addr(&addr);
1281 }
1282
1283 /// Creates a socket that listens for seqpacket connections on the specified address.
1284 pub
1285 fn bind_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error>
1286 {
1287 let socket = Socket::<SocketSeqPkt>::new(false)?;
1288
1289 socket.set_unix_local_addr(addr)?;
1290 socket.start_listening()?;
1291
1292 return Ok(UnixSeqpacketListener { fd: socket.into() });
1293 }
1294
1295 /// Returns the address the socket is listening on.
1296 pub
1297 fn local_unix_addr(&self) -> Result<UnixSocketAddr, io::Error>
1298 {
1299 get_unix_local_addr(&self)
1300 }
1301
1302 /// Accepts a new incoming connection to this listener.
1303 ///
1304 /// Rustdocs:
1305 /// > This function will block the calling thread until a new Unix connection
1306 /// > is established. When established, the corresponding [`UnixSeqpacketConn`] and
1307 /// > the remote peer's address will be returned.
1308 ///
1309 /// [`UnixSeqpacketConn`]: UnixSeqpacketConn
1310 ///
1311 /// # Examples
1312 ///
1313 /// ```no_run
1314 /// use uds_fork::UnixSeqpacketListener;
1315 ///
1316 /// fn main() -> std::io::Result<()>
1317 /// {
1318 /// let listener = UnixSeqpacketListener::bind("/path/to/the/socket")?;
1319 ///
1320 /// match listener.accept()
1321 /// {
1322 /// Ok((socket, addr)) =>
1323 /// println!("Got a client: {addr:?}"),
1324 /// Err(e) =>
1325 /// println!("accept function failed: {e:?}"),
1326 /// }
1327 ///
1328 /// return Ok(());
1329 /// }
1330 /// ```
1331 #[inline]
1332 pub
1333 fn accept(&self)-> Result<(UnixSeqpacketConn, UnixSocketAddr), io::Error>
1334 {
1335 self.accept_unix_addr()
1336 }
1337
1338 /// Accepts a new incoming connection to this listener.
1339 ///
1340 /// See [Self::accept].
1341 pub
1342 fn accept_unix_addr(&self)-> Result<(UnixSeqpacketConn, UnixSocketAddr), io::Error>
1343 {
1344 let (socket, addr) = Socket::<SocketSeqPkt>::accept_from(&self, false)?;
1345 let conn = UnixSeqpacketConn { fd: socket.into() };
1346
1347 return Ok((conn, addr));
1348 }
1349
1350 /// Returns the value of the `SO_ERROR` option.
1351 ///
1352 /// This might never produce any errors for listeners. It is therefore
1353 /// unlikely to be useful, but is provided for parity with
1354 /// `std::unix::net::UnixListener`.
1355 pub
1356 fn take_error(&self) -> Result<Option<io::Error>, io::Error>
1357 {
1358 take_error(&self)
1359 }
1360
1361 /// Creates a new file descriptor listening for the same connections.
1362 pub
1363 fn try_clone(&self) -> Result<Self, io::Error>
1364 {
1365 let cloned = Socket::<SocketSeqPkt>::try_clone_from(&self)?;
1366
1367 return Ok(UnixSeqpacketListener { fd: cloned.into() });
1368 }
1369
1370 /// Sets a maximum duration to wait in a single `accept()` on this socket.
1371 ///
1372 /// `None` disables a previously set timeout.
1373 /// An error is returned if the duration is zero.
1374 ///
1375 /// # Operating System Support
1376 ///
1377 /// Only Linux appers to apply timeouts to `accept()`.
1378 /// On macOS, FreeBSD and NetBSD, timeouts are silently ignored.
1379 /// On Illumos setting timeouts for all unix domain sockets silently fails.
1380 ///
1381 /// On OSes where timeouts are known to not work, this function will
1382 /// return an error even if setting the timeout didn't fail.
1383 ///
1384 /// # Examples
1385 ///
1386 #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
1387 #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
1388 /// # use uds_fork::{UnixSeqpacketListener, UnixSocketAddr};
1389 /// # use std::io::ErrorKind;
1390 /// # use std::time::Duration;
1391 /// #
1392 /// # let addr = UnixSocketAddr::new("@set_timeout").unwrap();
1393 /// let listener = UnixSeqpacketListener::bind_unix_addr(&addr).unwrap();
1394 /// listener.set_timeout(Some(Duration::new(0, 200_000_000))).unwrap();
1395 /// let err = listener.accept_unix_addr().unwrap_err();
1396 /// assert_eq!(err.kind(), ErrorKind::WouldBlock);
1397 /// ```
1398 pub
1399 fn set_timeout(&self, timeout: Option<Duration>) -> Result<(), io::Error>
1400 {
1401 let res = set_timeout(&self, TimeoutDirection::Read, timeout);
1402
1403 #[cfg(any(
1404 target_vendor="apple", target_os="freebsd",
1405 target_os="netbsd",
1406 target_os="illumos", target_os="solaris",
1407 ))]
1408 {
1409 if res.is_ok() == true && timeout.is_some() == true
1410 {
1411 return Err(
1412 io::Error::new(
1413 ErrorKind::InvalidInput,
1414 "listener timeouts are not supported on this OS"
1415 )
1416 );
1417 }
1418 }
1419
1420 return res;
1421 }
1422
1423 /// Returns the timeout for `accept()` on this socket.
1424 ///
1425 /// `None` is returned if there is no timeout.
1426 ///
1427 /// Even if a timeout has is set, it is ignored by `accept()` on
1428 /// most operating systems except Linux.
1429 ///
1430 /// # Examples
1431 ///
1432 #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
1433 #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
1434 /// # use uds_fork::{UnixSeqpacketListener, UnixSocketAddr};
1435 /// # use std::time::Duration;
1436 /// #
1437 /// # let addr = UnixSocketAddr::new("@timeout").unwrap();
1438 /// let listener = UnixSeqpacketListener::bind_unix_addr(&addr).unwrap();
1439 /// assert_eq!(listener.timeout().unwrap(), None);
1440 /// let timeout = Some(Duration::new(2, 0));
1441 /// listener.set_timeout(timeout).unwrap();
1442 /// assert_eq!(listener.timeout().unwrap(), timeout);
1443 /// ```
1444 pub
1445 fn timeout(&self) -> Result<Option<Duration>, io::Error>
1446 {
1447 get_timeout(&self, TimeoutDirection::Read)
1448 }
1449
1450 /// Enables or disables nonblocking-ness of [`accept_unix_addr()`](#method.accept_unix addr).
1451 ///
1452 /// The returned connnections will still be in blocking mode regardsless.
1453 ///
1454 /// Consider using the nonblocking variant of this type instead;
1455 /// this method mostly exists for feature parity with std's `UnixListener`.
1456 ///
1457 /// # Examples
1458 ///
1459 #[cfg_attr(not(target_vendor="apple"), doc="```")]
1460 #[cfg_attr(target_vendor="apple", doc="```no_run")]
1461 /// # use std::io::ErrorKind;
1462 /// # use uds_fork::{UnixSocketAddr, UnixSeqpacketListener};
1463 /// use tempfile::TempDir;
1464 ///
1465 /// let dir = tempfile::tempdir().unwrap();
1466 /// let mut file_path = dir.path().join("nonblocking_seqpacket_listener1.socket");
1467 ///
1468 /// let addr = UnixSocketAddr::from_path(&file_path).unwrap();
1469 /// let listener = UnixSeqpacketListener::bind_unix_addr(&addr).expect("create listener");
1470 /// listener.set_nonblocking(true).expect("enable noblocking mode");
1471 /// assert_eq!(listener.accept_unix_addr().unwrap_err().kind(), ErrorKind::WouldBlock);
1472 /// ```
1473 pub
1474 fn set_nonblocking(&self, nonblocking: bool) -> Result<(), io::Error>
1475 {
1476 set_nonblocking(&self, nonblocking)
1477 }
1478
1479 /// Returns an iterator over incoming connections.
1480 ///
1481 /// Rustdoc:
1482 /// > The iterator will never return [`None`] and will also not yield the
1483 /// > peer's [`UnixSocketAddr`] structure.
1484 ///
1485 /// ```no_run
1486 /// use std::thread;
1487 /// use uds_fork::{UnixSeqpacketConn, UnixSeqpacketListener};
1488 ///
1489 /// fn handle_client(stream: UnixSeqpacketConn)
1490 /// {
1491 /// // ...
1492 /// }
1493 ///
1494 /// fn main() -> std::io::Result<()>
1495 /// {
1496 /// let listener = UnixSeqpacketListener::bind("/path/to/the/socket")?;
1497 ///
1498 /// for stream in listener.incoming()
1499 /// {
1500 /// match stream
1501 /// {
1502 /// Ok(stream) =>
1503 /// {
1504 /// thread::spawn(|| handle_client(stream));
1505 /// },
1506 /// Err(err) =>
1507 /// {
1508 /// break;
1509 /// }
1510 /// }
1511 /// }
1512 ///
1513 /// return Ok(());
1514 /// }
1515 /// ```
1516 pub
1517 fn incoming(&self) -> Incoming<'_>
1518 {
1519 Incoming { listener: self }
1520 }
1521}
1522
1523/// A rust std API.
1524///
1525/// From Rustdocs:
1526/// > An iterator over incoming connections to a [`UnixListener`].
1527/// >
1528/// > It will never return [`None`].
1529///
1530/// # Examples
1531///
1532/// ```no_run
1533/// use std::thread;
1534/// use uds_fork::{UnixSeqpacketConn, UnixSeqpacketListener};
1535///
1536/// fn handle_client(stream: UnixSeqpacketConn) {
1537/// // ...
1538/// }
1539///
1540/// fn main() -> std::io::Result<()>
1541/// {
1542/// let listener = UnixSeqpacketListener::bind("/path/to/the/socket")?;
1543///
1544/// for stream in listener.incoming()
1545/// {
1546/// match stream
1547/// {
1548/// Ok(stream) =>
1549/// {
1550/// thread::spawn(|| handle_client(stream));
1551/// }
1552/// Err(err) =>
1553/// {
1554/// break;
1555/// }
1556/// }
1557/// }
1558/// return Ok(());
1559/// }
1560/// ```
1561#[derive(Debug)]
1562pub struct Incoming<'a>
1563{
1564 listener: &'a UnixSeqpacketListener,
1565}
1566
1567impl<'a> Iterator for Incoming<'a>
1568{
1569 type Item = io::Result<UnixSeqpacketConn>;
1570
1571 fn next(&mut self) -> Option<io::Result<UnixSeqpacketConn>>
1572 {
1573 Some(self.listener.accept().map(|s| s.0))
1574 }
1575
1576 fn size_hint(&self) -> (usize, Option<usize>)
1577 {
1578 (usize::MAX, None)
1579 }
1580}
1581
1582impl<'a> IntoIterator for &'a UnixSeqpacketListener
1583{
1584 type Item = io::Result<UnixSeqpacketConn>;
1585 type IntoIter = Incoming<'a>;
1586
1587 fn into_iter(self) -> Incoming<'a>
1588 {
1589 self.incoming()
1590 }
1591}
1592
1593
1594
1595/// A non-blocking unix domain sequential-packet connection.
1596///
1597/// Differs from [`uds_fork::UnixSeqpacketConn`](../struct.UnixSeqpacketConn.html)
1598/// in that all operations that send or receive data will return an `Error` of
1599/// kind `ErrorKind::WouldBlock` instead of blocking.
1600/// This is done by creating the socket as non-blocking, and not by passing
1601/// `MSG_DONTWAIT`. If creating this type from a raw file descriptor, ensure
1602/// the fd is set to nonblocking before using it through this type.
1603///
1604/// # Registering with Xio (xio-rs) a feature = "xio-rs"
1605///
1606/// A `XioEventPipe` is implemented on this function. See [UnixSeqpacketConn]
1607/// for an examples.
1608///
1609/// See examples below.
1610///
1611/// # Registering with Mio (mio) a feature = "mio"
1612///
1613/// A `Source` is implemented on the instance. See [UnixSeqpacketConn]
1614/// for an examples.
1615///
1616/// # Examples
1617///
1618/// Sending or receiving when it would block a normal socket:
1619///
1620#[cfg_attr(not(target_vendor="apple"), doc="```")]
1621#[cfg_attr(target_vendor="apple", doc="```no_run")]
1622/// use uds_fork::nonblocking::UnixSeqpacketConn;
1623/// use std::io::ErrorKind;
1624///
1625/// let (a, b) = UnixSeqpacketConn::pair().expect("create nonblocking seqpacket pair");
1626///
1627/// // trying to receive when there are no packets waiting
1628/// assert_eq!(a.recv(&mut[0]).unwrap_err().kind(), ErrorKind::WouldBlock);
1629///
1630/// // trying to send when the OS buffer for the connection is full
1631/// loop {
1632/// if let Err(error) = a.send(&[0u8; 1000]) {
1633/// assert_eq!(error.kind(), ErrorKind::WouldBlock);
1634/// break;
1635/// }
1636/// }
1637/// ```
1638//#[deprecated = "Use UnixSeqpacketListener set_nonblocking(true)!"]
1639#[derive(Debug)]
1640#[repr(transparent)]
1641pub struct NonblockingUnixSeqpacketConn
1642{
1643 usc: UnixSeqpacketConn,
1644}
1645
1646impl From<OwnedFd> for NonblockingUnixSeqpacketConn
1647{
1648 fn from(value: OwnedFd) -> Self
1649 {
1650 let usc = UnixSeqpacketConn::from(value);
1651 usc.set_nonblocking(true).unwrap();
1652
1653 return Self{ usc: usc };
1654 }
1655}
1656
1657impl From<NonblockingUnixSeqpacketConn> for OwnedFd
1658{
1659 fn from(value: NonblockingUnixSeqpacketConn) -> Self
1660 {
1661 return value.usc.fd;
1662 }
1663}
1664
1665impl FromRawFd for NonblockingUnixSeqpacketConn
1666{
1667 unsafe
1668 fn from_raw_fd(fd: RawFd) -> Self
1669 {
1670 let usc = unsafe{ UnixSeqpacketConn::from_raw_fd(fd) };
1671 usc.set_nonblocking(true).unwrap();
1672
1673 return Self{ usc: usc };
1674 }
1675}
1676
1677impl AsRawFd for NonblockingUnixSeqpacketConn
1678{
1679 fn as_raw_fd(&self) -> RawFd
1680 {
1681 self.usc.as_raw_fd()
1682 }
1683}
1684impl IntoRawFd for NonblockingUnixSeqpacketConn
1685{
1686 fn into_raw_fd(self) -> RawFd
1687 {
1688 self.usc.into_raw_fd()
1689 }
1690}
1691
1692impl AsFd for NonblockingUnixSeqpacketConn
1693{
1694 fn as_fd(&self) -> BorrowedFd<'_>
1695 {
1696 self.usc.as_fd()
1697 }
1698}
1699
1700impl Deref for NonblockingUnixSeqpacketConn
1701{
1702 type Target = UnixSeqpacketConn;
1703
1704 fn deref(&self) -> &Self::Target
1705 {
1706 &self.usc
1707 }
1708}
1709
1710impl DerefMut for NonblockingUnixSeqpacketConn
1711{
1712 fn deref_mut(&mut self) -> &mut Self::Target
1713 {
1714 &mut self.usc
1715 }
1716}
1717
1718
1719#[cfg(feature = "mio")]
1720pub mod mio_non_blk_conn_enabled
1721{
1722 use std::io;
1723
1724 use mio::event::Source;
1725 use super::NonblockingUnixSeqpacketConn;
1726
1727 impl Source for NonblockingUnixSeqpacketConn
1728 {
1729 fn register(
1730 &mut self,
1731 registry: &mio::Registry,
1732 token: mio::Token,
1733 interests: mio::Interest,
1734 ) -> io::Result<()>
1735 {
1736 self.usc.register(registry, token, interests)
1737 }
1738
1739 fn reregister(
1740 &mut self,
1741 registry: &mio::Registry,
1742 token: mio::Token,
1743 interests: mio::Interest,
1744 ) -> io::Result<()>
1745 {
1746 self.usc.reregister(registry, token, interests)
1747 }
1748
1749 fn deregister(&mut self, registry: &mio::Registry) -> io::Result<()>
1750 {
1751 self.usc.deregister(registry)
1752 }
1753 }
1754}
1755
1756#[cfg(feature = "xio-rs")]
1757pub mod xio_non_blk_conn_enabled
1758{
1759 use xio_rs::{EsInterfaceRegistry, XioChannel, XioEventPipe, XioEventUid, XioResult, event_registry::XioRegistry};
1760
1761 use super::NonblockingUnixSeqpacketConn;
1762
1763 impl<ESSR: EsInterfaceRegistry> XioEventPipe<ESSR, Self> for NonblockingUnixSeqpacketConn
1764 {
1765 fn connect_event_pipe(&mut self, ess: &XioRegistry<ESSR>, ev_uid: XioEventUid, channel: XioChannel) -> XioResult<()>
1766 {
1767 self.usc.connect_event_pipe(ess, ev_uid, channel)
1768 }
1769
1770 fn modify_event_pipe(&mut self, ess: &XioRegistry<ESSR>, ev_uid: XioEventUid, channel: XioChannel) -> XioResult<()>
1771 {
1772 self.usc.modify_event_pipe(ess, ev_uid, channel)
1773 }
1774
1775 fn disconnect_event_pipe(&mut self, ess: &XioRegistry<ESSR>) -> XioResult<()>
1776 {
1777 self.usc.disconnect_event_pipe(ess)
1778 }
1779 }
1780}
1781
1782// can't Deref<Target=UnixSeqpacketConn> because that would include try_clone()
1783// and later set_(read|write)_timeout()
1784impl NonblockingUnixSeqpacketConn
1785{
1786 /// Connects to an unix seqpacket server listening at `path`.
1787 ///
1788 /// This is a wrapper around [`connect_unix_addr()`](#method.connect_unix_addr)
1789 /// for convenience and compatibility with std.
1790 pub
1791 fn connect<P: AsRef<Path>>(path: P) -> Result<Self, io::Error>
1792 {
1793 let addr = UnixSocketAddr::from_path(&path)?;
1794
1795 return Self::connect_unix_addr(&addr);
1796 }
1797
1798 /// Connects to an unix seqpacket server listening at `addr`.
1799 pub
1800 fn connect_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error>
1801 {
1802 let socket = Socket::<SocketSeqPkt>::new(true)?;
1803 socket.set_unix_peer_addr(addr)?;
1804
1805 return Ok(
1806 NonblockingUnixSeqpacketConn
1807 {
1808 usc: UnixSeqpacketConn { fd: socket.into() }
1809 }
1810 );
1811 }
1812
1813 /// Binds to an address before connecting to a listening seqpacet socket.
1814 pub
1815 fn connect_from_to_unix_addr(from: &UnixSocketAddr, to: &UnixSocketAddr) -> Result<Self, io::Error>
1816 {
1817 let socket = Socket::<SocketSeqPkt>::new(true)?;
1818 socket.set_unix_local_addr(from)?;
1819 socket.set_unix_peer_addr(to)?;
1820
1821 return Ok(
1822 NonblockingUnixSeqpacketConn
1823 {
1824 usc: UnixSeqpacketConn { fd: socket.into() }
1825 }
1826 );
1827 }
1828
1829 /// Creates a pair of unix-domain seqpacket conneections connected to each other.
1830 ///
1831 /// # Examples
1832 ///
1833 #[cfg_attr(not(target_vendor="apple"), doc="```")]
1834 #[cfg_attr(target_vendor="apple", doc="```no_run")]
1835 /// let (a, b) = uds_fork::UnixSeqpacketConn::pair().unwrap();
1836 /// assert!(a.local_unix_addr().unwrap().is_unnamed());
1837 /// assert!(b.local_unix_addr().unwrap().is_unnamed());
1838 ///
1839 /// a.send(b"hello").unwrap();
1840 /// b.recv(&mut[0; 20]).unwrap();
1841 /// ```
1842 pub
1843 fn pair() -> Result<(Self, Self), io::Error>
1844 {
1845 let pair = Socket::<SocketSeqPkt>::pair(true)?;
1846
1847 return Ok(
1848 (
1849 Self{ usc: UnixSeqpacketConn { fd: pair.0.into() } },
1850 Self{ usc: UnixSeqpacketConn { fd: pair.1.into() } },
1851 )
1852 );
1853 }
1854
1855 pub
1856 fn try_clone(&self) -> Result<Self, io::Error>
1857 {
1858 let cloned = Socket::<SocketSeqPkt>::try_clone_from(self)?;
1859
1860 return Ok(
1861 NonblockingUnixSeqpacketConn
1862 {
1863 usc: UnixSeqpacketConn { fd: cloned.into() }
1864 }
1865 );
1866 }
1867}
1868
1869impl io::Read for NonblockingUnixSeqpacketConn
1870{
1871 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize>
1872 {
1873 self.recv(buf)
1874 }
1875
1876 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize>
1877 {
1878 self.recv_vectored(bufs).map(|(n, _)| n)
1879 }
1880}
1881
1882impl<'a> io::Read for &'a NonblockingUnixSeqpacketConn
1883{
1884 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize>
1885 {
1886 self.recv(buf)
1887 }
1888
1889 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize>
1890 {
1891 self.recv_vectored(bufs).map(|(n, _)| n)
1892 }
1893}
1894
1895impl io::Write for NonblockingUnixSeqpacketConn
1896{
1897 fn write(&mut self, buf: &[u8]) -> io::Result<usize>
1898 {
1899 self.send(buf)
1900 }
1901
1902 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize>
1903 {
1904 self.send_vectored(bufs)
1905 }
1906
1907 fn flush(&mut self) -> io::Result<()>
1908 {
1909 todo!()
1910 }
1911}
1912
1913
1914/// A non-blocking unix domain listener for sequential-packet connections.
1915///
1916/// Differs from [`UnixSeqpacketListener`](../struct.UnixSeqpacketListener.html)
1917/// in that [`accept()`](struct.NonblockingUnixSeqpacketListener.html#method.accept)
1918/// returns non-blocking [connection sockets](struct.NonblockingUnixSeqpacketConn.html)
1919/// and doesn't block if no client `connect()`ions are pending.
1920///
1921/// # Registering with Xio (xio-rs) a feature = "xio-rs"
1922///
1923/// A `XioEventPipe` is implemented on this function. See [UnixSeqpacketListener]
1924/// for an examples.
1925///
1926/// See examples below.
1927///
1928/// # Registering with Mio (mio) a feature = "mio"
1929///
1930/// A `Source` is implemented on the instance. See [UnixSeqpacketListener]
1931/// for an examples.
1932///
1933/// # Examples
1934///
1935#[cfg_attr(not(target_vendor="apple"), doc="```")]
1936#[cfg_attr(target_vendor="apple", doc="```no_run")]
1937/// use uds_fork::nonblocking::{UnixSeqpacketListener, UnixSeqpacketConn};
1938/// use tempfile::TempDir;
1939/// use std::io::ErrorKind;
1940///
1941/// let dir = tempfile::tempdir().unwrap();
1942/// let mut file_path = dir.path().join("nonblocking_seqpacket_listener2.socket");
1943///
1944/// let listener = UnixSeqpacketListener::bind(&file_path)
1945/// .expect("Cannot create nonblocking seqpacket listener");
1946///
1947/// // doesn't block if no connections are waiting:
1948/// assert_eq!(listener.accept_unix_addr().unwrap_err().kind(), ErrorKind::WouldBlock);
1949///
1950/// // returned connections are nonblocking:
1951/// let _client = UnixSeqpacketConn::connect(&file_path).unwrap();
1952/// let (conn, _addr) = listener.accept_unix_addr().unwrap();
1953/// assert_eq!(conn.recv(&mut[0u8; 20]).unwrap_err().kind(), ErrorKind::WouldBlock);
1954/// ```
1955#[derive(Debug)]
1956#[repr(transparent)]
1957pub struct NonblockingUnixSeqpacketListener
1958{
1959 usl: UnixSeqpacketListener,
1960}
1961
1962impl From<OwnedFd> for NonblockingUnixSeqpacketListener
1963{
1964 fn from(ofd: OwnedFd) -> Self
1965 {
1966 let usl = UnixSeqpacketListener::from(ofd);
1967 usl.set_nonblocking(true).unwrap();
1968
1969 return Self{ usl };
1970 }
1971}
1972
1973impl FromRawFd for NonblockingUnixSeqpacketListener
1974{
1975 unsafe
1976 fn from_raw_fd(fd: RawFd) -> Self
1977 {
1978 let usl = unsafe{ UnixSeqpacketListener::from_raw_fd(fd) };
1979 usl.set_nonblocking(true).unwrap();
1980
1981 return Self{ usl };
1982 }
1983}
1984
1985
1986impl From<NonblockingUnixSeqpacketListener> for OwnedFd
1987{
1988 fn from(value: NonblockingUnixSeqpacketListener) -> Self
1989 {
1990 return value.usl.fd;
1991 }
1992}
1993
1994
1995impl AsRawFd for NonblockingUnixSeqpacketListener
1996{
1997 fn as_raw_fd(&self) -> RawFd
1998 {
1999 self.usl.as_raw_fd()
2000 }
2001}
2002
2003impl IntoRawFd for NonblockingUnixSeqpacketListener
2004{
2005 fn into_raw_fd(self) -> RawFd
2006 {
2007 self.usl.into_raw_fd()
2008 }
2009}
2010
2011impl AsFd for NonblockingUnixSeqpacketListener
2012{
2013 fn as_fd(&self) -> BorrowedFd<'_>
2014 {
2015 self.usl.as_fd()
2016 }
2017}
2018
2019
2020impl Deref for NonblockingUnixSeqpacketListener
2021{
2022 type Target = UnixSeqpacketListener;
2023
2024 fn deref(&self) -> &Self::Target
2025 {
2026 &self.usl
2027 }
2028}
2029
2030impl DerefMut for NonblockingUnixSeqpacketListener
2031{
2032 fn deref_mut(&mut self) -> &mut Self::Target
2033 {
2034 &mut self.usl
2035 }
2036}
2037
2038impl NonblockingUnixSeqpacketListener
2039{
2040 /// Creates a socket that listens for seqpacket connections on the specified socket file.
2041 pub
2042 fn bind<P: AsRef<Path>>(path: P) -> Result<Self, io::Error>
2043 {
2044 let addr = UnixSocketAddr::from_path(&path)?;
2045
2046 return Self::bind_unix_addr(&addr);
2047 }
2048
2049 /// Creates a socket that listens for seqpacket connections on the specified address.
2050 pub
2051 fn bind_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error>
2052 {
2053 let socket = Socket::<SocketSeqPkt>::new(true)?;
2054 socket.set_unix_local_addr(addr)?;
2055 socket.start_listening()?;
2056
2057 return Ok( Self{ usl: UnixSeqpacketListener{ fd: socket.into() }} );
2058 }
2059
2060 /// Accepts a non-blocking connection, non-blockingly.
2061 ///
2062 /// # Examples
2063 ///
2064 /// Doesn't block if no connections are waiting:
2065 ///
2066 #[cfg_attr(not(target_vendor="apple"), doc="```")]
2067 #[cfg_attr(target_vendor="apple", doc="```no_run")]
2068 /// # use uds_fork::nonblocking::UnixSeqpacketListener;
2069 /// # use std::io::ErrorKind;
2070 /// # use tempfile::TempDir;
2071 ///
2072 /// let dir = tempfile::tempdir().unwrap();
2073 /// let mut file_path = dir.path().join("nonblocking_seqpacket_listener3.socket");
2074 ///
2075 /// let listener = UnixSeqpacketListener::bind(&file_path)
2076 /// .expect("Cannot create nonblocking seqpacket listener");
2077 /// assert_eq!(listener.accept_unix_addr().unwrap_err().kind(), ErrorKind::WouldBlock);
2078 /// ```
2079 pub
2080 fn accept_unix_addr(&self) -> Result<(NonblockingUnixSeqpacketConn, UnixSocketAddr), io::Error>
2081 {
2082 let (socket, addr) = Socket::<SocketSeqPkt>::accept_from(&self, true)?;
2083 let conn = NonblockingUnixSeqpacketConn { usc: UnixSeqpacketConn{ fd: socket.into() }};
2084
2085 return Ok((conn, addr));
2086 }
2087}
2088
2089
2090
2091#[cfg(feature = "mio")]
2092pub mod mio_non_blk_listener_enabled
2093{
2094 use std::{io, os::fd::AsRawFd};
2095
2096 use mio::{event::Source, unix::SourceFd};
2097 use super::NonblockingUnixSeqpacketListener;
2098
2099 impl Source for NonblockingUnixSeqpacketListener
2100 {
2101 fn register(
2102 &mut self,
2103 registry: &mio::Registry,
2104 token: mio::Token,
2105 interests: mio::Interest,
2106 ) -> io::Result<()>
2107 {
2108 self.usl.register(registry, token, interests)
2109 }
2110
2111 fn reregister(
2112 &mut self,
2113 registry: &mio::Registry,
2114 token: mio::Token,
2115 interests: mio::Interest,
2116 ) -> io::Result<()>
2117 {
2118 self.usl.reregister(registry, token, interests)
2119 }
2120
2121 fn deregister(&mut self, registry: &mio::Registry) -> io::Result<()>
2122 {
2123 self.usl.deregister(registry)
2124 }
2125 }
2126}
2127
2128#[cfg(feature = "xio-rs")]
2129pub mod xio_non_blk_listener_enabled
2130{
2131 use xio_rs::{EsInterfaceRegistry, XioChannel, XioEventPipe, XioEventUid, XioResult, event_registry::XioRegistry};
2132
2133 use super::NonblockingUnixSeqpacketListener;
2134
2135 impl<ESSR: EsInterfaceRegistry> XioEventPipe<ESSR, Self> for NonblockingUnixSeqpacketListener
2136 {
2137 fn connect_event_pipe(&mut self, ess: &XioRegistry<ESSR>, ev_uid: XioEventUid, channel: XioChannel) -> XioResult<()>
2138 {
2139
2140 self.usl.connect_event_pipe(ess, ev_uid, channel)
2141 }
2142
2143 fn modify_event_pipe(&mut self, ess: &XioRegistry<ESSR>, ev_uid: XioEventUid, channel: XioChannel) -> XioResult<()>
2144 {
2145 self.usl.modify_event_pipe(ess, ev_uid, channel)
2146 }
2147
2148 fn disconnect_event_pipe(&mut self, ess: &XioRegistry<ESSR>) -> XioResult<()>
2149 {
2150 self.usl.disconnect_event_pipe(ess)
2151 }
2152 }
2153}