uds_fork/seqpacket.rs
1use std::
2{
3 io::{self, IoSlice, IoSliceMut},
4 net::Shutdown,
5 os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd},
6 path::Path,
7 time::Duration
8};
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/// # Examples
44///
45/// What is sent separately is received separately:
46///
47#[cfg_attr(not(target_vendor="apple"), doc="```")]
48#[cfg_attr(target_vendor="apple", doc="```no_run")]
49/// let (a, b) = uds_fork::UnixSeqpacketConn::pair().expect("Cannot create seqpacket pair");
50///
51/// a.send(b"first").unwrap();
52/// a.send(b"second").unwrap();
53///
54/// let mut buffer_big_enough_for_both = [0; 20];
55/// let len = b.recv(&mut buffer_big_enough_for_both).unwrap();
56/// assert_eq!(&buffer_big_enough_for_both[..len], b"first");
57/// let len = b.recv(&mut buffer_big_enough_for_both).unwrap();
58/// assert_eq!(&buffer_big_enough_for_both[..len], b"second");
59/// ```
60///
61/// Connect to a listener on a socket file and write to it:
62///
63#[cfg_attr(not(target_vendor="apple"), doc="```")]
64#[cfg_attr(target_vendor="apple", doc="```no_run")]
65/// use uds_fork::{UnixSeqpacketListener, UnixSeqpacketConn};
66///
67/// # let _ = std::fs::remove_file("/tmp/seqpacket.socket"); // pre-emptively delete just in case
68/// let listener = UnixSeqpacketListener::bind("/tmp/seqpacket.socket")
69/// .expect("create seqpacket listener");
70/// let conn = UnixSeqpacketConn::connect("/tmp/seqpacket.socket")
71/// .expect("connect to seqpacket listener");
72///
73/// let message = "Hello, listener";
74/// let sent = conn.send(message.as_bytes()).unwrap();
75/// assert_eq!(sent, message.len());
76///
77/// std::fs::remove_file("/tmp/seqpacket.socket").unwrap(); // clean up after ourselves
78/// ```
79///
80/// Connect to a listener on an abstract address:
81///
82#[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
83#[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
84/// use uds_fork::{UnixSeqpacketListener, UnixSeqpacketConn, UnixSocketAddr};
85///
86/// let addr = UnixSocketAddr::new("@seqpacket example").unwrap();
87/// let listener = UnixSeqpacketListener::bind_unix_addr(&addr)
88/// .expect("create abstract seqpacket listener");
89/// let _client = UnixSeqpacketConn::connect_unix_addr(&addr)
90/// .expect("connect to abstract seqpacket listener");
91/// let (_server, _addr) = listener.accept_unix_addr().unwrap();
92/// ```
93#[derive(Debug)]
94#[repr(transparent)]
95pub struct UnixSeqpacketConn
96{
97 fd: OwnedFd,
98}
99
100impl From<UnixSeqpacketConn> for OwnedFd
101{
102 fn from(value: UnixSeqpacketConn) -> Self
103 {
104 return value.fd;
105 }
106}
107
108impl FromRawFd for UnixSeqpacketConn
109{
110 unsafe
111 fn from_raw_fd(fd: RawFd) -> Self
112 {
113 return
114 UnixSeqpacketConn { fd: unsafe { OwnedFd::from_raw_fd(fd) } };
115 }
116}
117
118impl AsRawFd for UnixSeqpacketConn
119{
120 fn as_raw_fd(&self) -> RawFd
121 {
122 self.fd.as_raw_fd()
123 }
124}
125impl IntoRawFd for UnixSeqpacketConn
126{
127 fn into_raw_fd(self) -> RawFd
128 {
129 self.fd.into_raw_fd()
130 }
131}
132
133impl AsFd for UnixSeqpacketConn
134{
135 fn as_fd(&self) -> BorrowedFd<'_>
136 {
137 self.fd.as_fd()
138 }
139}
140
141impl UnixSeqpacketConn
142{
143 /// Connects to an unix seqpacket server listening at `path`.
144 ///
145 /// This is a wrapper around [`connect_unix_addr()`](#method.connect_unix_addr)
146 /// for convenience and compatibility with std.
147 pub
148 fn connect<P: AsRef<Path>>(path: P) -> Result<Self, io::Error>
149 {
150 let addr = UnixSocketAddr::from_path(&path)?;
151 Self::connect_unix_addr(&addr)
152 }
153
154 /// Connects to an unix seqpacket server listening at `addr`.
155 pub
156 fn connect_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error>
157 {
158 let socket = Socket::<SocketSeqPkt>::new(false)?;
159 socket.set_unix_addr(SetAddr::PEER, addr)?;
160
161 return Ok(UnixSeqpacketConn { fd: socket.into() });
162 }
163
164 /// Binds to an address before connecting to a listening seqpacet socket.
165 pub
166 fn connect_from_to_unix_addr(from: &UnixSocketAddr, to: &UnixSocketAddr) -> Result<Self, io::Error>
167 {
168 let socket = Socket::<SocketSeqPkt>::new(false)?;
169 socket.set_unix_addr(SetAddr::LOCAL, from)?;
170 socket.set_unix_addr(SetAddr::PEER, to)?;
171
172 return Ok(UnixSeqpacketConn { fd: socket.into() });
173 }
174
175 /// Creates a pair of unix-domain seqpacket conneections connected to each other.
176 ///
177 /// # Examples
178 ///
179 #[cfg_attr(not(target_vendor="apple"), doc="```")]
180 #[cfg_attr(target_vendor="apple", doc="```no_run")]
181 /// let (a, b) = uds_fork::UnixSeqpacketConn::pair().unwrap();
182 /// assert!(a.local_unix_addr().unwrap().is_unnamed());
183 /// assert!(b.local_unix_addr().unwrap().is_unnamed());
184 ///
185 /// a.send(b"hello").unwrap();
186 /// b.recv(&mut[0; 20]).unwrap();
187 /// ```
188 pub
189 fn pair() -> Result<(Self, Self), io::Error>
190 {
191 let pair = Socket::<SocketSeqPkt>::pair(false)?;
192
193 return Ok(
194 (
195 UnixSeqpacketConn { fd: pair.0.into() },
196 UnixSeqpacketConn { fd: pair.1.into() }
197 )
198 );
199 }
200
201 /// Returns the address of this side of the connection.
202 pub
203 fn local_unix_addr(&self) -> Result<UnixSocketAddr, io::Error>
204 {
205 get_unix_addr(&self, GetAddr::LOCAL)
206 }
207
208 /// Returns the address of the other side of the connection.
209 pub
210 fn peer_unix_addr(&self) -> Result<UnixSocketAddr, io::Error>
211 {
212 get_unix_addr(&self, GetAddr::PEER)
213 }
214
215 /// Returns information about the process of the peer when the connection was established.
216 ///
217 /// See documentation of the returned type for details.
218 pub
219 fn initial_peer_credentials(&self) -> Result<ConnCredentials, io::Error>
220 {
221 peer_credentials(&self)
222 }
223
224 /// Returns the SELinux security context of the process that created the other
225 /// end of this connection.
226 ///
227 /// Will return an error on other operating systems than Linux or Android,
228 /// and also if running inside kubernetes.
229 /// On success the number of bytes used is returned. (like `Read`)
230 ///
231 /// The default security context is `unconfined`, without any trailing NUL.
232 /// A buffor of 50 bytes is probably always big enough.
233 pub
234 fn initial_peer_selinux_context(&self, buf: &mut[u8]) -> Result<usize, io::Error>
235 {
236 selinux_context(&self, buf)
237 }
238
239
240 /// Sends a packet to the peer.
241 pub
242 fn send(&self, packet: &[u8]) -> Result<usize, io::Error>
243 {
244 let ptr = packet.as_ptr() as *const c_void;
245 let flags = MSG_NOSIGNAL | MSG_EOR;
246 let sent = cvt_r!(unsafe { send(self.fd.as_raw_fd(), ptr, packet.len(), flags) })?;
247 Ok(sent as usize)
248 }
249
250 /// Sends a packet to the peer.
251 pub
252 fn send_flags(&self, packet: &[u8], flags: i32) -> Result<usize, io::Error>
253 {
254 let ptr = packet.as_ptr() as *const c_void;
255 let sent = cvt_r!(unsafe { send(self.fd.as_raw_fd(), ptr, packet.len(), flags) })?;
256 Ok(sent as usize)
257 }
258
259 /// Receives a packet from the peer.
260 pub
261 fn recv(&self, buffer: &mut[u8]) -> Result<usize, io::Error>
262 {
263 let ptr = buffer.as_ptr() as *mut c_void;
264 let received = cvt_r!(unsafe { recv(self.fd.as_raw_fd(), ptr, buffer.len(), MSG_NOSIGNAL) })?;
265 Ok(received as usize)
266 }
267
268 /// Sends a packet assembled from multiple byte slices.
269 pub
270 fn send_vectored(&self, slices: &[IoSlice]) -> Result<usize, io::Error>
271 {
272 // Can't use writev() because we need to pass flags,
273 // and the flags accepted by pwritev2() aren't the one we need to pass.
274 send_ancillary(&self, None, MSG_EOR, slices, Vec::new(), None)
275 }
276 /// Reads a packet into multiple buffers.
277 ///
278 /// The returned `bool` indicates whether the packet was truncated due to
279 /// too short buffers.
280 pub
281 fn recv_vectored(&self, buffers: &mut[IoSliceMut]) -> Result<(usize, bool), io::Error>
282 {
283 recv_ancillary(&self, None, 0, buffers, &mut[])
284 .map(|(bytes, ancillary)| (bytes, ancillary.message_truncated()) )
285 }
286
287 /// Sends a packet with associated file descriptors.
288 pub
289 fn send_fds(&self, bytes: &[u8], fds: Vec<OwnedFd>) -> Result<usize, io::Error>
290 {
291 send_ancillary(&self, None, MSG_EOR, &[IoSlice::new(bytes)], fds, None)
292 }
293
294 /// Receives a packet and associated file descriptors.
295 pub
296 fn recv_fds(&self, byte_buffer: &mut[u8], fd_buffer: &mut Vec<OwnedFd>) -> Result<(usize, bool, usize), io::Error>
297 {
298 recv_fds(&self, None, &mut[IoSliceMut::new(byte_buffer)], Some(fd_buffer))
299 }
300
301 /// Receives a packet without removing it from the incoming queue.
302 ///
303 /// # Examples
304 ///
305 #[cfg_attr(not(target_vendor="apple"), doc="```")]
306 #[cfg_attr(target_vendor="apple", doc="```no_run")]
307 /// let (a, b) = uds_fork::UnixSeqpacketConn::pair().unwrap();
308 /// a.send(b"hello").unwrap();
309 /// let mut buf = [0u8; 10];
310 /// assert_eq!(b.peek(&mut buf[..1]).unwrap(), 1);
311 /// assert_eq!(&buf[..2], &[b'h', 0]);
312 /// assert_eq!(b.peek(&mut buf).unwrap(), 5);
313 /// assert_eq!(&buf[..5], b"hello");
314 /// assert_eq!(b.recv(&mut buf).unwrap(), 5);
315 /// assert_eq!(&buf[..5], b"hello");
316 /// ```
317 pub
318 fn peek(&self, buffer: &mut[u8]) -> Result<usize, io::Error>
319 {
320 let ptr = buffer.as_ptr() as *mut c_void;
321 let flags = MSG_NOSIGNAL | MSG_PEEK;
322 let received = cvt_r!(unsafe { recv(self.fd.as_raw_fd(), ptr, buffer.len(), flags) })?;
323 Ok(received as usize)
324 }
325
326 /// Receives a packet without removing it from the incoming queue.
327 ///
328 /// The returned `bool` indicates whether the packet was truncated due to
329 /// the combined buffers being too small.
330 pub
331 fn peek_vectored(&self, buffers: &mut[IoSliceMut]) -> Result<(usize, bool), io::Error>
332 {
333 recv_ancillary(&self, None, MSG_PEEK, buffers, &mut[])
334 .map(|(bytes, ancillary)| (bytes, ancillary.message_truncated()) )
335 }
336
337 /// Returns the value of the `SO_ERROR` option.
338 ///
339 /// This might only provide errors generated from nonblocking `connect()`s,
340 /// which this library doesn't support. It is therefore unlikely to be
341 /// useful, but is provided for parity with stream counterpart in std.
342 ///
343 /// # Examples
344 ///
345 #[cfg_attr(not(target_vendor="apple"), doc="```")]
346 #[cfg_attr(target_vendor="apple", doc="```no_run")]
347 /// let (a, b) = uds_fork::UnixSeqpacketConn::pair().unwrap();
348 /// drop(b);
349 ///
350 /// assert!(a.send(b"anyone there?").is_err());
351 /// assert!(a.take_error().unwrap().is_none());
352 /// ```
353 pub
354 fn take_error(&self) -> Result<Option<io::Error>, io::Error>
355 {
356 take_error(&self)
357 }
358
359
360 /// Creates a new file descriptor also pointing to this side of this connection.
361 ///
362 /// # Examples
363 ///
364 /// Both new and old can send and receive, and share queues:
365 ///
366 #[cfg_attr(not(target_vendor="apple"), doc="```")]
367 #[cfg_attr(target_vendor="apple", doc="```no_run")]
368 /// let (a1, b) = uds_fork::nonblocking::UnixSeqpacketConn::pair().unwrap();
369 /// let a2 = a1.try_clone().unwrap();
370 ///
371 /// a1.send(b"first").unwrap();
372 /// a2.send(b"second").unwrap();
373 ///
374 /// let mut buf = [0u8; 20];
375 /// let len = b.recv(&mut buf).unwrap();
376 /// assert_eq!(&buf[..len], b"first");
377 /// b.send(b"hello first").unwrap();
378 /// let len = b.recv(&mut buf).unwrap();
379 /// assert_eq!(&buf[..len], b"second");
380 /// b.send(b"hello second").unwrap();
381 ///
382 /// let len = a2.recv(&mut buf).unwrap();
383 /// assert_eq!(&buf[..len], b"hello first");
384 /// let len = a1.recv(&mut buf).unwrap();
385 /// assert_eq!(&buf[..len], b"hello second");
386 /// ```
387 ///
388 /// Clone can still be used after the first one has been closed:
389 ///
390 #[cfg_attr(not(target_vendor="apple"), doc="```")]
391 #[cfg_attr(target_vendor="apple", doc="```no_run")]
392 /// let (a, b1) = uds_fork::nonblocking::UnixSeqpacketConn::pair().unwrap();
393 /// a.send(b"hello").unwrap();
394 ///
395 /// let b2 = b1.try_clone().unwrap();
396 /// drop(b1);
397 /// assert_eq!(b2.recv(&mut[0; 10]).unwrap(), "hello".len());
398 /// ```
399 pub
400 fn try_clone(&self) -> Result<Self, io::Error>
401 {
402 let cloned = Socket::<SocketSeqPkt>::try_clone_from(self.fd.as_fd())?;
403
404 return Ok(UnixSeqpacketConn { fd: cloned.into() });
405 }
406
407 /// Sets the read timeout to the duration specified.
408 ///
409 /// If the value specified is `None`, then `recv()` and its variants will
410 /// block indefinitely.
411 /// An error is returned if the duration is zero.
412 ///
413 /// The duration is rounded to microsecond precission.
414 /// Currently it's rounded down except if that would make it all zero.
415 ///
416 /// # Operating System Support
417 ///
418 /// On Illumos (and pressumably also Solaris) timeouts appears not to work
419 /// for unix domain sockets.
420 ///
421 /// # Examples
422 ///
423 #[cfg_attr(not(any(target_vendor="apple", target_os="illumos", target_os="solaris")), doc="```")]
424 #[cfg_attr(any(target_vendor="apple", target_os="illumos", target_os="solaris"), doc="```no_run")]
425 /// use std::io::ErrorKind;
426 /// use std::time::Duration;
427 /// use uds_fork::UnixSeqpacketConn;
428 ///
429 /// let (a, b) = UnixSeqpacketConn::pair().unwrap();
430 /// a.set_read_timeout(Some(Duration::new(0, 2_000_000))).unwrap();
431 /// let error = a.recv(&mut[0; 1024]).unwrap_err();
432 /// assert_eq!(error.kind(), ErrorKind::WouldBlock);
433 /// ```
434 pub
435 fn set_read_timeout(&self, timeout: Option<Duration>) -> Result<(), io::Error>
436 {
437 set_timeout(self.fd.as_fd(), TimeoutDirection::READ, timeout)
438 }
439 /// Returns the read timeout of this socket.
440 ///
441 /// `None` is returned if there is no timeout.
442 ///
443 /// Note that subsecond parts might have been be rounded by the OS
444 /// (in addition to the rounding to microsecond in `set_read_timeout()`).
445 ///
446 /// # Examples
447 ///
448 #[cfg_attr(not(any(target_vendor="apple", target_os="illumos", target_os="solaris")), doc="```")]
449 #[cfg_attr(any(target_vendor="apple", target_os="illumos", target_os="solaris"), doc="```no_run")]
450 /// use uds_fork::UnixSeqpacketConn;
451 /// use std::time::Duration;
452 ///
453 /// let timeout = Some(Duration::new(2, 0));
454 /// let conn = UnixSeqpacketConn::pair().unwrap().0;
455 /// conn.set_read_timeout(timeout).unwrap();
456 /// assert_eq!(conn.read_timeout().unwrap(), timeout);
457 /// ```
458 pub
459 fn read_timeout(&self) -> Result<Option<Duration>, io::Error>
460 {
461 get_timeout(self.fd.as_fd(), TimeoutDirection::READ)
462 }
463
464 /// Sets the write timeout to the duration specified.
465 ///
466 /// If the value specified is `None`, then `send()` and its variants will
467 /// block indefinitely.
468 /// An error is returned if the duration is zero.
469 ///
470 /// # Operating System Support
471 ///
472 /// On Illumos (and pressumably also Solaris) timeouts appears not to work
473 /// for unix domain sockets.
474 ///
475 /// # Examples
476 ///
477 #[cfg_attr(not(any(target_vendor="apple", target_os="illumos", target_os="solaris")), doc="```")]
478 #[cfg_attr(any(target_vendor="apple", target_os="illumos", target_os="solaris"), doc="```no_run")]
479 /// # use std::io::ErrorKind;
480 /// # use std::time::Duration;
481 /// # use uds_fork::UnixSeqpacketConn;
482 /// #
483 /// let (conn, _other) = UnixSeqpacketConn::pair().unwrap();
484 /// conn.set_write_timeout(Some(Duration::new(0, 500 * 1000))).unwrap();
485 /// loop {
486 /// if let Err(e) = conn.send(&[0; 1000]) {
487 /// assert_eq!(e.kind(), ErrorKind::WouldBlock, "{}", e);
488 /// break
489 /// }
490 /// }
491 /// ```
492 pub
493 fn set_write_timeout(&self, timeout: Option<Duration>)-> Result<(), io::Error>
494 {
495 set_timeout(self.fd.as_fd(), TimeoutDirection::WRITE, timeout)
496 }
497
498 /// Returns the write timeout of this socket.
499 ///
500 /// `None` is returned if there is no timeout.
501 ///
502 /// # Examples
503 ///
504 #[cfg_attr(not(target_vendor="apple"), doc="```")]
505 #[cfg_attr(target_vendor="apple", doc="```no_run")]
506 /// let conn = uds_fork::UnixSeqpacketConn::pair().unwrap().0;
507 /// assert!(conn.write_timeout().unwrap().is_none());
508 /// ```
509 pub
510 fn write_timeout(&self) -> Result<Option<Duration>, io::Error>
511 {
512 get_timeout(self.fd.as_fd(), TimeoutDirection::WRITE)
513 }
514
515 /// Enables or disables nonblocking mode.
516 ///
517 /// Consider using the nonblocking variant of this type instead.
518 /// This method mainly exists for feature parity with std's `UnixStream`.
519 ///
520 /// # Examples
521 ///
522 /// Trying to receive when there are no packets waiting:
523 ///
524 #[cfg_attr(not(target_vendor="apple"), doc="```")]
525 #[cfg_attr(target_vendor="apple", doc="```no_run")]
526 /// # use std::io::ErrorKind;
527 /// # use uds_fork::UnixSeqpacketConn;
528 /// let (a, b) = UnixSeqpacketConn::pair().expect("create seqpacket pair");
529 /// a.set_nonblocking(true).unwrap();
530 /// assert_eq!(a.recv(&mut[0; 20]).unwrap_err().kind(), ErrorKind::WouldBlock);
531 /// ```
532 ///
533 /// Trying to send when the OS buffer for the connection is full:
534 ///
535 #[cfg_attr(not(target_vendor="apple"), doc="```")]
536 #[cfg_attr(target_vendor="apple", doc="```no_run")]
537 /// # use std::io::ErrorKind;
538 /// # use uds_fork::UnixSeqpacketConn;
539 /// let (a, b) = UnixSeqpacketConn::pair().expect("create seqpacket pair");
540 /// a.set_nonblocking(true).unwrap();
541 /// loop {
542 /// if let Err(error) = a.send(&[b'#'; 1000]) {
543 /// assert_eq!(error.kind(), ErrorKind::WouldBlock);
544 /// break;
545 /// }
546 /// }
547 /// ```
548 pub
549 fn set_nonblocking(&self, nonblocking: bool) -> Result<(), io::Error>
550 {
551 set_nonblocking(&self, nonblocking)
552 }
553
554 /// Shuts down the read, write, or both halves of this connection.
555 pub
556 fn shutdown(&self, how: Shutdown) -> io::Result<()>
557 {
558 let how = match how {
559 Shutdown::Read => libc::SHUT_RD,
560 Shutdown::Write => libc::SHUT_WR,
561 Shutdown::Both => libc::SHUT_RDWR,
562 };
563 unsafe { cvt!(libc::shutdown(self.as_raw_fd(), how)) }?;
564 Ok(())
565 }
566}
567
568
569
570/// An unix domain listener for sequential packet connections.
571///
572/// See [`UnixSeqpacketConn`](struct.UnixSeqpacketConn.html) for a description
573/// of this type of connection.
574///
575/// # Examples
576///
577#[cfg_attr(not(target_vendor="apple"), doc="```")]
578#[cfg_attr(target_vendor="apple", doc="```no_run")]
579/// # let _ = std::fs::remove_file("/tmp/seqpacket_listener.socket");
580/// let listener = uds_fork::UnixSeqpacketListener::bind("/tmp/seqpacket_listener.socket")
581/// .expect("Create seqpacket listener");
582/// let _client = uds_fork::UnixSeqpacketConn::connect("/tmp/seqpacket_listener.socket").unwrap();
583/// let (conn, _addr) = listener.accept_unix_addr().unwrap();
584/// conn.send(b"Welcome").unwrap();
585/// # std::fs::remove_file("/tmp/seqpacket_listener.socket").unwrap();
586/// ```
587#[derive(Debug)]
588#[repr(transparent)]
589pub struct UnixSeqpacketListener
590{
591 fd: OwnedFd
592}
593
594
595impl FromRawFd for UnixSeqpacketListener
596{
597 unsafe
598 fn from_raw_fd(fd: RawFd) -> Self
599 {
600 return
601 Self{ fd: unsafe { OwnedFd::from_raw_fd(fd) } };
602 }
603}
604
605impl AsRawFd for UnixSeqpacketListener
606{
607 fn as_raw_fd(&self) -> RawFd
608 {
609 self.fd.as_raw_fd()
610 }
611}
612
613impl IntoRawFd for UnixSeqpacketListener
614{
615 fn into_raw_fd(self) -> RawFd
616 {
617 self.fd.into_raw_fd()
618 }
619}
620
621impl AsFd for UnixSeqpacketListener
622{
623 fn as_fd(&self) -> BorrowedFd<'_>
624 {
625 self.fd.as_fd()
626 }
627}
628
629impl UnixSeqpacketListener
630{
631 /// Creates a socket that listens for seqpacket connections on the specified socket file.
632 pub
633 fn bind<P: AsRef<Path>>(path: P) -> Result<Self, io::Error>
634 {
635 let addr = UnixSocketAddr::from_path(path.as_ref())?;
636
637 return Self::bind_unix_addr(&addr);
638 }
639
640 /// Creates a socket that listens for seqpacket connections on the specified address.
641 pub
642 fn bind_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error>
643 {
644 let socket = Socket::<SocketSeqPkt>::new(false)?;
645
646 socket.set_unix_addr(SetAddr::LOCAL, addr)?;
647 socket.start_listening()?;
648
649 return Ok(UnixSeqpacketListener { fd: socket.into() });
650 }
651
652 /// Returns the address the socket is listening on.
653 pub
654 fn local_unix_addr(&self) -> Result<UnixSocketAddr, io::Error>
655 {
656 get_unix_addr(&self, GetAddr::LOCAL)
657 }
658
659 /// Accepts a new incoming connection to this listener.
660 pub
661 fn accept_unix_addr(&self)-> Result<(UnixSeqpacketConn, UnixSocketAddr), io::Error>
662 {
663 let (socket, addr) = Socket::<SocketSeqPkt>::accept_from(&self, false)?;
664 let conn = UnixSeqpacketConn { fd: socket.into() };
665
666 return Ok((conn, addr));
667 }
668
669 /// Returns the value of the `SO_ERROR` option.
670 ///
671 /// This might never produce any errors for listeners. It is therefore
672 /// unlikely to be useful, but is provided for parity with
673 /// `std::unix::net::UnixListener`.
674 pub
675 fn take_error(&self) -> Result<Option<io::Error>, io::Error>
676 {
677 take_error(&self)
678 }
679
680 /// Creates a new file descriptor listening for the same connections.
681 pub
682 fn try_clone(&self) -> Result<Self, io::Error>
683 {
684 let cloned = Socket::<SocketSeqPkt>::try_clone_from(&self)?;
685
686 return Ok(UnixSeqpacketListener { fd: cloned.into() });
687 }
688
689 /// Sets a maximum duration to wait in a single `accept()` on this socket.
690 ///
691 /// `None` disables a previously set timeout.
692 /// An error is returned if the duration is zero.
693 ///
694 /// # Operating System Support
695 ///
696 /// Only Linux appers to apply timeouts to `accept()`.
697 /// On macOS, FreeBSD and NetBSD, timeouts are silently ignored.
698 /// On Illumos setting timeouts for all unix domain sockets silently fails.
699 ///
700 /// On OSes where timeouts are known to not work, this function will
701 /// return an error even if setting the timeout didn't fail.
702 ///
703 /// # Examples
704 ///
705 #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
706 #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
707 /// # use uds_fork::{UnixSeqpacketListener, UnixSocketAddr};
708 /// # use std::io::ErrorKind;
709 /// # use std::time::Duration;
710 /// #
711 /// # let addr = UnixSocketAddr::new("@set_timeout").unwrap();
712 /// let listener = UnixSeqpacketListener::bind_unix_addr(&addr).unwrap();
713 /// listener.set_timeout(Some(Duration::new(0, 200_000_000))).unwrap();
714 /// let err = listener.accept_unix_addr().unwrap_err();
715 /// assert_eq!(err.kind(), ErrorKind::WouldBlock);
716 /// ```
717 pub
718 fn set_timeout(&self, timeout: Option<Duration>) -> Result<(), io::Error>
719 {
720 match set_timeout(&self, TimeoutDirection::READ, timeout)
721 {
722 #[cfg(any(
723 target_vendor="apple", target_os="freebsd",
724 target_os="netbsd",
725 target_os="illumos", target_os="solaris",
726 ))]
727 Ok(()) if timeout.is_some() => Err(io::Error::new(
728 ErrorKind::InvalidInput,
729 "listener timeouts are not supported on this OS"
730 )),
731 result => result
732 }
733 }
734
735 /// Returns the timeout for `accept()` on this socket.
736 ///
737 /// `None` is returned if there is no timeout.
738 ///
739 /// Even if a timeout has is set, it is ignored by `accept()` on
740 /// most operating systems except Linux.
741 ///
742 /// # Examples
743 ///
744 #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
745 #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
746 /// # use uds_fork::{UnixSeqpacketListener, UnixSocketAddr};
747 /// # use std::time::Duration;
748 /// #
749 /// # let addr = UnixSocketAddr::new("@timeout").unwrap();
750 /// let listener = UnixSeqpacketListener::bind_unix_addr(&addr).unwrap();
751 /// assert_eq!(listener.timeout().unwrap(), None);
752 /// let timeout = Some(Duration::new(2, 0));
753 /// listener.set_timeout(timeout).unwrap();
754 /// assert_eq!(listener.timeout().unwrap(), timeout);
755 /// ```
756 pub
757 fn timeout(&self) -> Result<Option<Duration>, io::Error>
758 {
759 get_timeout(&self, TimeoutDirection::READ)
760 }
761
762 /// Enables or disables nonblocking-ness of [`accept_unix_addr()`](#method.accept_unix addr).
763 ///
764 /// The returned connnections will still be in blocking mode regardsless.
765 ///
766 /// Consider using the nonblocking variant of this type instead;
767 /// this method mostly exists for feature parity with std's `UnixListener`.
768 ///
769 /// # Examples
770 ///
771 #[cfg_attr(not(target_vendor="apple"), doc="```")]
772 #[cfg_attr(target_vendor="apple", doc="```no_run")]
773 /// # use std::io::ErrorKind;
774 /// # use uds_fork::{UnixSocketAddr, UnixSeqpacketListener};
775 /// #
776 /// # let addr = UnixSocketAddr::from_path("/tmp/nonblocking_seqpacket_listener.socket").unwrap();
777 /// # let _ = std::fs::remove_file("/tmp/nonblocking_seqpacket_listener.socket");
778 /// let listener = UnixSeqpacketListener::bind_unix_addr(&addr).expect("create listener");
779 /// listener.set_nonblocking(true).expect("enable noblocking mode");
780 /// assert_eq!(listener.accept_unix_addr().unwrap_err().kind(), ErrorKind::WouldBlock);
781 /// # std::fs::remove_file("/tmp/nonblocking_seqpacket_listener.socket").expect("delete socket file");
782 /// ```
783 pub
784 fn set_nonblocking(&self, nonblocking: bool) -> Result<(), io::Error>
785 {
786 set_nonblocking(&self, nonblocking)
787 }
788}
789
790
791
792/// A non-blocking unix domain sequential-packet connection.
793///
794/// Differs from [`uds_fork::UnixSeqpacketConn`](../struct.UnixSeqpacketConn.html)
795/// in that all operations that send or receive data will return an `Error` of
796/// kind `ErrorKind::WouldBlock` instead of blocking.
797/// This is done by creating the socket as non-blocking, and not by passing
798/// `MSG_DONTWAIT`. If creating this type from a raw file descriptor, ensure
799/// the fd is set to nonblocking before using it through this type.
800///
801/// # Examples
802///
803/// Sending or receiving when it would block a normal socket:
804///
805#[cfg_attr(not(target_vendor="apple"), doc="```")]
806#[cfg_attr(target_vendor="apple", doc="```no_run")]
807/// use uds_fork::nonblocking::UnixSeqpacketConn;
808/// use std::io::ErrorKind;
809///
810/// let (a, b) = UnixSeqpacketConn::pair().expect("create nonblocking seqpacket pair");
811///
812/// // trying to receive when there are no packets waiting
813/// assert_eq!(a.recv(&mut[0]).unwrap_err().kind(), ErrorKind::WouldBlock);
814///
815/// // trying to send when the OS buffer for the connection is full
816/// loop {
817/// if let Err(error) = a.send(&[0u8; 1000]) {
818/// assert_eq!(error.kind(), ErrorKind::WouldBlock);
819/// break;
820/// }
821/// }
822/// ```
823#[derive(Debug)]
824#[repr(transparent)]
825pub struct NonblockingUnixSeqpacketConn
826{
827 fd: OwnedFd,
828}
829
830impl From<NonblockingUnixSeqpacketConn> for OwnedFd
831{
832 fn from(value: NonblockingUnixSeqpacketConn) -> Self
833 {
834 return value.fd;
835 }
836}
837
838impl FromRawFd for NonblockingUnixSeqpacketConn
839{
840 unsafe
841 fn from_raw_fd(fd: RawFd) -> Self
842 {
843 return
844 Self{ fd: unsafe { OwnedFd::from_raw_fd(fd) } };
845 }
846}
847
848impl AsRawFd for NonblockingUnixSeqpacketConn
849{
850 fn as_raw_fd(&self) -> RawFd
851 {
852 self.fd.as_raw_fd()
853 }
854}
855impl IntoRawFd for NonblockingUnixSeqpacketConn
856{
857 fn into_raw_fd(self) -> RawFd
858 {
859 self.fd.into_raw_fd()
860 }
861}
862
863impl AsFd for NonblockingUnixSeqpacketConn
864{
865 fn as_fd(&self) -> BorrowedFd<'_>
866 {
867 self.fd.as_fd()
868 }
869}
870
871
872// can't Deref<Target=UnixSeqpacketConn> because that would include try_clone()
873// and later set_(read|write)_timeout()
874impl NonblockingUnixSeqpacketConn
875{
876 /// Connects to an unix seqpacket server listening at `path`.
877 ///
878 /// This is a wrapper around [`connect_unix_addr()`](#method.connect_unix_addr)
879 /// for convenience and compatibility with std.
880 pub
881 fn connect<P: AsRef<Path>>(path: P) -> Result<Self, io::Error>
882 {
883 let addr = UnixSocketAddr::from_path(&path)?;
884
885 return Self::connect_unix_addr(&addr);
886 }
887
888 /// Connects to an unix seqpacket server listening at `addr`.
889 pub
890 fn connect_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error>
891 {
892 let socket = Socket::<SocketSeqPkt>::new(true)?;
893 socket.set_unix_addr(SetAddr::PEER, addr)?;
894
895 return Ok(NonblockingUnixSeqpacketConn { fd: socket.into() });
896 }
897
898 /// Binds to an address before connecting to a listening seqpacket socket.
899 pub
900 fn connect_from_to_unix_addr(from: &UnixSocketAddr, to: &UnixSocketAddr) -> Result<Self, io::Error>
901 {
902 let socket = Socket::<SocketSeqPkt>::new(true)?;
903 socket.set_unix_addr(SetAddr::LOCAL, from)?;
904 socket.set_unix_addr(SetAddr::PEER, to)?;
905
906 return Ok(NonblockingUnixSeqpacketConn { fd: socket.into() });
907 }
908
909 /// Creates a pair of nonblocking unix-domain seqpacket conneections connected to each other.
910 ///
911 /// # Examples
912 ///
913 #[cfg_attr(not(target_vendor="apple"), doc="```")]
914 #[cfg_attr(target_vendor="apple", doc="```no_run")]
915 /// let (a, b) = uds_fork::nonblocking::UnixSeqpacketConn::pair().unwrap();
916 /// assert!(a.local_unix_addr().unwrap().is_unnamed());
917 /// assert!(b.local_unix_addr().unwrap().is_unnamed());
918 /// assert_eq!(b.recv(&mut[0; 20]).unwrap_err().kind(), std::io::ErrorKind::WouldBlock);
919 /// a.send(b"hello").unwrap();
920 /// assert_eq!(b.recv(&mut[0; 20]).unwrap(), 5);
921 /// ```
922 pub
923 fn pair() -> Result<(Self, Self), io::Error>
924 {
925 let pair = Socket::<SocketSeqPkt>::pair(true)?;
926
927 return Ok(
928 (
929 NonblockingUnixSeqpacketConn { fd: pair.0.into() },
930 NonblockingUnixSeqpacketConn { fd: pair.1.into() }
931 )
932 );
933 }
934
935 /// Returns the address of this side of the connection.
936 pub
937 fn local_unix_addr(&self) -> Result<UnixSocketAddr, io::Error>
938 {
939 get_unix_addr(&self, GetAddr::LOCAL)
940 }
941
942 /// Returns the address of the other side of the connection.
943 pub
944 fn peer_unix_addr(&self) -> Result<UnixSocketAddr, io::Error>
945 {
946 get_unix_addr(&self, GetAddr::PEER)
947 }
948
949 /// Returns information about the process of the peer when the connection was established.
950 ///
951 /// See documentation of the returned type for details.
952 pub
953 fn initial_peer_credentials(&self) -> Result<ConnCredentials, io::Error>
954 {
955 peer_credentials(&self)
956 }
957
958 /// Returns the SELinux security context of the process that created the other
959 /// end of this connection.
960 ///
961 /// Will return an error on other operating systems than Linux or Android,
962 /// and also if running inside kubernetes.
963 /// On success the number of bytes used is returned. (like `Read`)
964 ///
965 /// The default security context is `unconfined`, without any trailing NUL.
966 /// A buffor of 50 bytes is probably always big enough.
967 pub
968 fn initial_peer_selinux_context(&self, buf: &mut[u8]) -> Result<usize, io::Error>
969 {
970 selinux_context(&self, buf)
971 }
972
973 /// Sends a packet to the peer.
974 pub
975 fn send(&self, packet: &[u8]) -> Result<usize, io::Error>
976 {
977 let ptr = packet.as_ptr() as *const c_void;
978 let flags = MSG_NOSIGNAL | MSG_EOR;
979 let sent = cvt_r!(unsafe { send(self.fd.as_raw_fd(), ptr, packet.len(), flags) })?;
980
981 return Ok(sent as usize);
982 }
983
984 pub
985 fn send_flags(&self, packet: &[u8], flags: i32) -> Result<usize, io::Error>
986 {
987 let ptr = packet.as_ptr() as *const c_void;
988 let sent = cvt_r!(unsafe { send(self.fd.as_raw_fd(), ptr, packet.len(), flags) })?;
989
990 return Ok(sent as usize);
991 }
992
993 /// Receives a packet from the peer.
994 pub
995 fn recv(&self, buffer: &mut[u8]) -> Result<usize, io::Error>
996 {
997 let ptr = buffer.as_ptr() as *mut c_void;
998 let received = cvt_r!(unsafe { recv(self.fd.as_raw_fd(), ptr, buffer.len(), MSG_NOSIGNAL) })?;
999
1000 return Ok(received as usize);
1001 }
1002 /// Sends a packet assembled from multiple byte slices.
1003 pub fn send_vectored(&self, slices: &[IoSlice]) -> Result<usize, io::Error>
1004 {
1005 // Can't use writev() because we need to pass flags,
1006 // and the flags accepted by pwritev2() aren't the one we need to pass.
1007 send_ancillary(&self, None, MSG_EOR, slices, Vec::new(), None)
1008 }
1009
1010 /// Reads a packet into multiple buffers.
1011 ///
1012 /// The returned `bool` indicates whether the packet was truncated due to
1013 /// too short buffers.
1014 pub
1015 fn recv_vectored(&self, buffers: &mut[IoSliceMut]) -> Result<(usize, bool), io::Error>
1016 {
1017 recv_ancillary(&self, None, 0, buffers, &mut[])
1018 .map(|(bytes, ancillary)| (bytes, ancillary.message_truncated()) )
1019 }
1020
1021 /// Sends a packet with associated file descriptors.
1022 pub
1023 fn send_fds(&self, bytes: &[u8], fds: Vec<OwnedFd>) -> Result<usize, io::Error>
1024 {
1025 send_ancillary(&self, None, MSG_EOR, &[IoSlice::new(bytes)], fds, None)
1026 }
1027
1028 /// Receives a packet and associated file descriptors.
1029 pub
1030 fn recv_fds(&self, byte_buffer: &mut[u8], fd_buffer: &mut Vec<OwnedFd>) -> Result<(usize, bool, usize), io::Error>
1031 {
1032 recv_fds(&self, None, &mut[IoSliceMut::new(byte_buffer)], Some(fd_buffer))
1033 }
1034
1035 /// Receives a packet without removing it from the incoming queue.
1036 ///
1037 /// # Examples
1038 ///
1039 #[cfg_attr(not(target_vendor="apple"), doc="```")]
1040 #[cfg_attr(target_vendor="apple", doc="```no_run")]
1041 /// # use std::io::ErrorKind::*;
1042 /// let (a, b) = uds_fork::nonblocking::UnixSeqpacketConn::pair().unwrap();
1043 /// let mut buf = [0u8; 10];
1044 /// assert_eq!(b.peek(&mut buf).unwrap_err().kind(), WouldBlock);
1045 /// a.send(b"hello").unwrap();
1046 /// assert_eq!(b.peek(&mut buf).unwrap(), 5);
1047 /// assert_eq!(&buf[..5], b"hello");
1048 /// assert_eq!(b.recv(&mut buf).unwrap(), 5);
1049 /// assert_eq!(&buf[..5], b"hello");
1050 /// assert_eq!(b.peek(&mut buf).unwrap_err().kind(), WouldBlock);
1051 /// ```
1052 pub
1053 fn peek(&self, buffer: &mut[u8]) -> Result<usize, io::Error>
1054 {
1055 let ptr = buffer.as_ptr() as *mut c_void;
1056 let flags = MSG_NOSIGNAL | MSG_PEEK;
1057 let received = cvt_r!(unsafe { recv(self.fd.as_raw_fd(), ptr, buffer.len(), flags) })?;
1058
1059 return Ok(received as usize);
1060 }
1061
1062 /// Receives a packet without removing it from the incoming queue.
1063 ///
1064 /// The returned `bool` indicates whether the packet was truncated due to
1065 /// the combined buffers being too small.
1066 pub
1067 fn peek_vectored(&self, buffers: &mut[IoSliceMut]) -> Result<(usize, bool), io::Error>
1068 {
1069 recv_ancillary(&self, None, MSG_PEEK, buffers, &mut[])
1070 .map(|(bytes, ancillary)| (bytes, ancillary.message_truncated()) )
1071 }
1072
1073 /// Returns the value of the `SO_ERROR` option.
1074 ///
1075 /// This might only provide errors generated from nonblocking `connect()`s,
1076 /// which this library doesn't support. It is therefore unlikely to be
1077 /// useful, but is provided for parity with `mio`s `UnixStream`.
1078 ///
1079 /// # Examples
1080 ///
1081 #[cfg_attr(not(target_vendor="apple"), doc="```")]
1082 #[cfg_attr(target_vendor="apple", doc="```no_run")]
1083 /// let (a, _b) = uds_fork::nonblocking::UnixSeqpacketConn::pair().unwrap();
1084 ///
1085 /// assert!(a.recv(&mut[0u8; 1024]).is_err());
1086 /// assert!(a.take_error().unwrap().is_none());
1087 /// ```
1088 pub
1089 fn take_error(&self) -> Result<Option<io::Error>, io::Error>
1090 {
1091 take_error(&self)
1092 }
1093
1094
1095 /// Creates a new file descriptor also pointing to this side of this connection.
1096 ///
1097 /// # Examples
1098 ///
1099 #[cfg_attr(not(target_vendor="apple"), doc="```")]
1100 #[cfg_attr(target_vendor="apple", doc="```no_run")]
1101 /// # use uds_fork::nonblocking::UnixSeqpacketConn;
1102 /// # use std::io::ErrorKind;
1103 /// #
1104 /// let (a1, b) = UnixSeqpacketConn::pair().unwrap();
1105 /// b.send(b"first come first serve").unwrap();
1106 /// let a2 = a1.try_clone().unwrap();
1107 /// a2.recv(&mut[0u8; 10]).unwrap();
1108 /// assert_eq!(a1.recv(&mut[0u8; 10]).unwrap_err().kind(), ErrorKind::WouldBlock);
1109 ///
1110 /// b.send(b"more").unwrap();
1111 /// a1.recv(&mut[0u8; 10]).unwrap();
1112 /// assert_eq!(a2.recv(&mut[0u8; 10]).unwrap_err().kind(), ErrorKind::WouldBlock);
1113 /// ```
1114 pub
1115 fn try_clone(&self) -> Result<Self, io::Error>
1116 {
1117 let cloned = Socket::<SocketSeqPkt>::try_clone_from(&self)?;
1118 // nonblockingness is shared and therefore inherited
1119
1120 return Ok(NonblockingUnixSeqpacketConn { fd: cloned.into() });
1121 }
1122
1123 /// Shuts down the read, write, or both halves of this connection.
1124 pub
1125 fn shutdown(&self, how: Shutdown) -> io::Result<()>
1126 {
1127 let how =
1128 match how
1129 {
1130 Shutdown::Read => libc::SHUT_RD,
1131 Shutdown::Write => libc::SHUT_WR,
1132 Shutdown::Both => libc::SHUT_RDWR,
1133 };
1134
1135 unsafe { cvt!(libc::shutdown(self.as_raw_fd(), how)) }?;
1136
1137 return Ok(());
1138 }
1139}
1140
1141
1142/// A non-blocking unix domain listener for sequential-packet connections.
1143///
1144/// Differs from [`UnixSeqpacketListener`](../struct.UnixSeqpacketListener.html)
1145/// in that [`accept()`](struct.NonblockingUnixSeqpacketListener.html#method.accept)
1146/// returns non-blocking [connection sockets](struct.NonblockingUnixSeqpacketConn.html)
1147/// and doesn't block if no client `connect()`ions are pending.
1148///
1149/// This type can be used with mio if the `mio_08` feature is enabled:
1150///
1151/// ```toml
1152/// uds = { version = "x.y", features=["mio_08"] }
1153/// ```
1154///
1155/// # Examples
1156///
1157#[cfg_attr(not(target_vendor="apple"), doc="```")]
1158#[cfg_attr(target_vendor="apple", doc="```no_run")]
1159/// use uds_fork::nonblocking::{UnixSeqpacketListener, UnixSeqpacketConn};
1160/// use std::io::ErrorKind;
1161///
1162/// # let _ = std::fs::remove_file("/tmp/nonblocking_seqpacket_listener.socket");
1163/// let listener = UnixSeqpacketListener::bind("/tmp/nonblocking_seqpacket_listener.socket")
1164/// .expect("Cannot create nonblocking seqpacket listener");
1165///
1166/// // doesn't block if no connections are waiting:
1167/// assert_eq!(listener.accept_unix_addr().unwrap_err().kind(), ErrorKind::WouldBlock);
1168///
1169/// // returned connections are nonblocking:
1170/// let _client = UnixSeqpacketConn::connect("/tmp/nonblocking_seqpacket_listener.socket").unwrap();
1171/// let (conn, _addr) = listener.accept_unix_addr().unwrap();
1172/// assert_eq!(conn.recv(&mut[0u8; 20]).unwrap_err().kind(), ErrorKind::WouldBlock);
1173/// #
1174/// # std::fs::remove_file("/tmp/nonblocking_seqpacket_listener.socket").unwrap();
1175/// ```
1176#[derive(Debug)]
1177#[repr(transparent)]
1178pub struct NonblockingUnixSeqpacketListener
1179{
1180 fd: OwnedFd
1181}
1182
1183impl FromRawFd for NonblockingUnixSeqpacketListener
1184{
1185 unsafe
1186 fn from_raw_fd(fd: RawFd) -> Self
1187 {
1188 return
1189 Self{ fd: unsafe { OwnedFd::from_raw_fd(fd) } };
1190 }
1191}
1192
1193impl AsRawFd for NonblockingUnixSeqpacketListener
1194{
1195 fn as_raw_fd(&self) -> RawFd
1196 {
1197 self.fd.as_raw_fd()
1198 }
1199}
1200
1201impl IntoRawFd for NonblockingUnixSeqpacketListener
1202{
1203 fn into_raw_fd(self) -> RawFd
1204 {
1205 self.fd.into_raw_fd()
1206 }
1207}
1208
1209impl AsFd for NonblockingUnixSeqpacketListener
1210{
1211 fn as_fd(&self) -> BorrowedFd<'_>
1212 {
1213 self.fd.as_fd()
1214 }
1215}
1216
1217impl NonblockingUnixSeqpacketListener
1218{
1219 /// Creates a socket that listens for seqpacket connections on the specified socket file.
1220 pub
1221 fn bind<P: AsRef<Path>>(path: P) -> Result<Self, io::Error>
1222 {
1223 let addr = UnixSocketAddr::from_path(&path)?;
1224
1225 return Self::bind_unix_addr(&addr);
1226 }
1227
1228 /// Creates a socket that listens for seqpacket connections on the specified address.
1229 pub
1230 fn bind_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error>
1231 {
1232 let socket = Socket::<SocketSeqPkt>::new(true)?;
1233 socket.set_unix_addr(SetAddr::LOCAL, addr)?;
1234 socket.start_listening()?;
1235
1236 return Ok(NonblockingUnixSeqpacketListener { fd: socket.into() });
1237 }
1238
1239 /// Returns the address this listener was bound to.
1240 pub
1241 fn local_unix_addr(&self) -> Result<UnixSocketAddr, io::Error>
1242 {
1243 get_unix_addr(&self, GetAddr::LOCAL)
1244 }
1245
1246 /// Accepts a non-blocking connection, non-blockingly.
1247 ///
1248 /// # Examples
1249 ///
1250 /// Doesn't block if no connections are waiting:
1251 ///
1252 #[cfg_attr(not(target_vendor="apple"), doc="```")]
1253 #[cfg_attr(target_vendor="apple", doc="```no_run")]
1254 /// # use uds_fork::nonblocking::UnixSeqpacketListener;
1255 /// # use std::io::ErrorKind;
1256 /// #
1257 /// let _ = std::fs::remove_file("/tmp/nonblocking_seqpacket_listener.socket");
1258 /// let listener = UnixSeqpacketListener::bind("/tmp/nonblocking_seqpacket_listener.socket")
1259 /// .expect("Cannot create nonblocking seqpacket listener");
1260 /// assert_eq!(listener.accept_unix_addr().unwrap_err().kind(), ErrorKind::WouldBlock);
1261 /// std::fs::remove_file("/tmp/nonblocking_seqpacket_listener.socket").unwrap();
1262 /// ```
1263 pub
1264 fn accept_unix_addr(&self) -> Result<(NonblockingUnixSeqpacketConn, UnixSocketAddr), io::Error>
1265 {
1266 let (socket, addr) = Socket::<SocketSeqPkt>::accept_from(&self, true)?;
1267 let conn = NonblockingUnixSeqpacketConn { fd: socket.into() };
1268
1269 return Ok((conn, addr));
1270 }
1271
1272 /// Returns the value of the `SO_ERROR` option.
1273 ///
1274 /// This might never produce any errors for listeners. It is therefore
1275 /// unlikely to be useful, but is provided for parity with `mio`s
1276 /// `UnixListener`.
1277 ///
1278 /// # Examples
1279 ///
1280 #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
1281 #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
1282 /// let listener = uds_fork::nonblocking::UnixSeqpacketListener::bind_unix_addr(
1283 /// &uds_fork::UnixSocketAddr::new("@nonblocking_take_error").unwrap()
1284 /// ).unwrap();
1285 ///
1286 /// assert!(listener.accept_unix_addr().is_err());
1287 /// assert!(listener.take_error().unwrap().is_none());
1288 /// ```
1289 pub
1290 fn take_error(&self) -> Result<Option<io::Error>, io::Error>
1291 {
1292 take_error(&self)
1293 }
1294
1295 /// Creates a new file descriptor listening for the same connections.
1296 pub
1297 fn try_clone(&self) -> Result<Self, io::Error>
1298 {
1299 let cloned = Socket::<SocketSeqPkt>::try_clone_from(&self)?;
1300 // nonblockingness is shared and therefore inherited
1301
1302 return Ok(NonblockingUnixSeqpacketListener { fd: cloned.into() });
1303 }
1304}