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