uds_fork/traits.rs
1
2use std::
3{
4 ffi::c_void, io::{self, IoSlice, IoSliceMut}, os::
5 {
6 fd::{AsFd, OwnedFd, RawFd},
7 unix::{io::{AsRawFd, FromRawFd}, net::{UnixDatagram, UnixListener, UnixStream}}
8 }
9};
10
11use libc::{MSG_PEEK, recvfrom, sendto};
12
13use crate::addr::UnixSocketAddr;
14use crate::helpers::*;
15use crate::ancillary::*;
16use crate::credentials::*;
17
18/// Extension trait for `std::os::unix::net::UnixStream` and nonblocking equivalents.
19pub trait UnixStreamExt: AsFd + AsRawFd + FromRawFd
20{
21 /// Get the address of this socket, as a type that fully supports abstract addresses.
22 fn local_unix_addr(&self) -> Result<UnixSocketAddr, io::Error>
23 {
24 get_unix_local_addr(self)
25 }
26
27 /// Returns the address of the other end of this stream,
28 /// as a type that fully supports abstract addresses.
29 fn peer_unix_addr(&self) -> Result<UnixSocketAddr, io::Error>
30 {
31 get_unix_peer_addr(self)
32 }
33
34 /// Creates a connection to a listening path-based or abstract named socket.
35 fn connect_to_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error> where Self: Sized;
36
37 /// Creates a path-based or abstract-named socket and connects to a listening socket.
38 fn connect_from_to_unix_addr(from: &UnixSocketAddr, to: &UnixSocketAddr) -> Result<Self, io::Error>
39 where Self: Sized;
40
41 /// Sends file descriptors in addition to bytes.
42 fn send_fds(&self, bytes: &[u8], fds: Vec<OwnedFd>) -> Result<usize, io::Error>
43 {
44 let fds_raw = fds.iter().map(|fd| fd.as_raw_fd()).collect::<Vec<RawFd>>();
45
46 send_ancillary(self, None, 0, &[IoSlice::new(bytes)], &fds_raw, None)
47 }
48
49 /// Receives file descriptors in addition to bytes.
50 ///
51 /// A FDs are placed into pre-allocated mutable slice. Received valies are stored
52 /// in reception sequence. The first [Option::None] does mean the rest are None too.
53 fn recv_slice_fds(&self, buf: &mut[u8], fd_buf: &mut [Option<OwnedFd>]) -> Result<(usize, usize), io::Error>
54 {
55 recv_slice_fds(self, None, &mut[IoSliceMut::new(buf)], fd_buf)
56 .map(|(bytes, _, fds)| (bytes, fds) )
57 }
58
59 /// A FDs are placed into Vec with the specific capacity.
60 ///
61 /// A FDs will be truncated if the capacity is not large enough.
62 fn recv_fds(&self, buf: &mut[u8], fd_buf: &mut Vec<OwnedFd>) -> Result<(usize, usize), io::Error>
63 {
64 recv_fds(self, None, &mut[IoSliceMut::new(buf)], fd_buf)
65 .map(|(bytes, _, fds)| (bytes, fds) )
66 }
67
68 /// Returns the credentials of the process that created the other end of this stream.
69 fn initial_peer_credentials(&self) -> Result<ConnCredentials, io::Error>
70 {
71 peer_credentials(self)
72 }
73 /// Returns the SELinux security context of the process that created the other end of this stream.
74 ///
75 /// Will return an error on other operating systems than Linux or Android,
76 /// and also if running under kubernetes.
77 /// On success the number of bytes used is returned. (like `Read`)
78 ///
79 /// The default security context is `unconfined`, without any trailing NUL.
80 /// A buffor of 50 bytes is probably always big enough.
81 fn initial_peer_selinux_context(&self, buffer: &mut[u8]) -> Result<usize, io::Error>
82 {
83 selinux_context(self, buffer)
84 }
85}
86
87impl UnixStreamExt for UnixStream
88{
89 fn connect_to_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error>
90 {
91 let socket = Socket::<SocketStream>::new(false)?;
92 socket.set_unix_peer_addr(addr)?;
93
94 return Ok(Self::from( <Socket<SocketStream> as Into<OwnedFd>>::into(socket)));
95 }
96
97 fn connect_from_to_unix_addr(from: &UnixSocketAddr, to: &UnixSocketAddr) -> Result<Self, io::Error>
98 {
99 let socket = Socket::<SocketStream>::new(false)?;
100 socket.set_unix_local_addr(from)?;
101 socket.set_unix_peer_addr(to)?;
102
103 return Ok(Self::from( <Socket<SocketStream> as Into<OwnedFd>>::into(socket)));
104 }
105}
106
107#[cfg(feature = "mio")]
108impl UnixStreamExt for mio::net::UnixStream
109{
110 fn connect_to_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error>
111 {
112 let socket = Socket::<SocketStream>::new(true)?;
113 socket.set_unix_peer_addr(addr)?;
114
115 return Ok(Self::from( <Socket<SocketStream> as Into<OwnedFd>>::into(socket)));
116 }
117
118 fn connect_from_to_unix_addr(from: &UnixSocketAddr, to: &UnixSocketAddr) -> Result<Self, io::Error>
119 {
120 let socket = Socket::<SocketStream>::new(true)?;
121 socket.set_unix_local_addr(from)?;
122 socket.set_unix_peer_addr(to)?;
123
124 return Ok(Self::from( <Socket<SocketStream> as Into<OwnedFd>>::into(socket)));
125 }
126}
127
128/// Extension trait for using [`UnixSocketAddr`](struct.UnixSocketAddr.html) with `UnixListener` types.
129pub trait UnixListenerExt: AsFd + AsRawFd + FromRawFd
130{
131 /// The type represeting the stream connection returned by `accept_unix_addr()`.
132 type Conn: FromRawFd;
133
134 /// Creates a socket bound to a `UnixSocketAddr` and starts listening on it.
135 fn bind_unix_addr(on: &UnixSocketAddr) -> Result<Self, io::Error>
136 where Self: Sized;
137
138 /// Returns the address this socket is listening on.
139 fn local_unix_addr(&self) -> Result<UnixSocketAddr, io::Error>
140 {
141 get_unix_local_addr(self)
142 }
143
144 /// Accepts a connection and returns the client's address as
145 /// an `uds_fork::UnixSocketAddr`.
146 fn accept_unix_addr(&self) -> Result<(Self::Conn, UnixSocketAddr), io::Error>;
147}
148
149impl UnixListenerExt for UnixListener
150{
151 type Conn = UnixStream;
152
153 fn bind_unix_addr(on: &UnixSocketAddr) -> Result<Self, io::Error>
154 {
155 let socket = Socket::<SocketStream>::new(false)?;
156 socket.set_unix_local_addr(on)?;
157
158 socket.start_listening()?;
159
160 return
161 Ok(Self::from( <Socket<SocketStream> as Into<OwnedFd>>::into(socket)));
162 }
163
164 fn accept_unix_addr(&self) -> Result<(Self::Conn, UnixSocketAddr), io::Error>
165 {
166 let (socket, addr) = Socket::<SocketStream>::accept_from(self, false)?;
167 let conn =
168 Self::Conn::from(<Socket<SocketStream> as Into<OwnedFd>>::into(socket));
169
170 return Ok((conn, addr));
171 }
172}
173
174
175#[cfg(feature = "mio")]
176impl UnixListenerExt for mio::net::UnixListener
177{
178 type Conn = mio::net::UnixStream;
179
180 fn bind_unix_addr(on: &UnixSocketAddr) -> Result<Self, io::Error>
181 {
182 let socket = Socket::<SocketStream>::new(true)?;
183 socket.set_unix_local_addr(on)?;
184
185 socket.start_listening()?;
186
187 return
188 Ok(Self::from( <Socket<SocketStream> as Into<OwnedFd>>::into(socket)));
189 }
190
191 fn accept_unix_addr(&self) -> Result<(Self::Conn, UnixSocketAddr), io::Error>
192 {
193 let (socket, addr) = Socket::<SocketStream>::accept_from(self, true)?;
194
195 let conn =
196 Self::Conn::from(<Socket<SocketStream> as Into<OwnedFd>>::into(socket));
197
198 Ok((conn, addr))
199 }
200}
201
202/// Extension trait for `std::os::unix::net::UnixDatagram` and nonblocking equivalents.
203pub trait UnixDatagramExt: AsFd + AsRawFd + FromRawFd
204{
205 /// Create a socket bound to a path or abstract name.
206 ///
207 /// # Examples
208 ///
209 #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
210 #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
211 /// # use std::os::unix::net::UnixDatagram;
212 /// # use uds_fork::{UnixDatagramExt, UnixSocketAddr};
213 /// #
214 /// # fn main() -> Result<(), std::io::Error> {
215 /// let addr = UnixSocketAddr::new("@abstract")?;
216 /// let socket = UnixDatagram::bind_unix_addr(&addr)?;
217 /// # let _ = socket.send_to_unix_addr(b"where are you", &addr);
218 /// # Ok(())
219 /// # }
220 /// ```
221 ///
222 /// This is equivalent of:
223 ///
224 /// ```
225 /// # use std::os::unix::net::UnixDatagram;
226 /// # use uds_fork::{UnixDatagramExt, UnixSocketAddr};
227 /// #
228 /// # fn main() -> Result<(), std::io::Error> {
229 /// # let addr = UnixSocketAddr::new("/tmp/me")?;
230 /// let socket = UnixDatagram::unbound()?;
231 /// socket.bind_to_unix_addr(&addr)?;
232 /// # let _ = std::fs::remove_file("/tmp/me");
233 /// # Ok(())
234 /// # }
235 /// ```
236 fn bind_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error>
237 where Self: Sized;
238
239 /// Returns the address of this socket, as a type that fully supports abstract addresses.
240 fn local_unix_addr(&self) -> Result<UnixSocketAddr, io::Error>
241 {
242 get_unix_local_addr(self)
243 }
244
245 /// Returns the address of the connected socket, as a type that fully supports abstract addresses.
246 fn peer_unix_addr(&self) -> Result<UnixSocketAddr, io::Error>
247 {
248 get_unix_peer_addr(self)
249 }
250
251 /// Creates a path or abstract name for the socket.
252 fn bind_to_unix_addr(&self, addr: &UnixSocketAddr) -> Result<(), io::Error>
253 {
254 set_unix_local_addr(self, addr)
255 }
256
257 /// Connects the socket to a path-based or abstract named socket.
258 fn connect_to_unix_addr(&self, addr: &UnixSocketAddr) -> Result<(), io::Error>
259 {
260 set_unix_peer_addr(self, addr)
261 }
262
263 /// Sends to the specified address, using an address type that
264 /// supports abstract addresses.
265 ///
266 /// # Examples
267 ///
268 /// Send to an abstract address:
269 ///
270 #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
271 #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
272 /// # use std::os::unix::net::UnixDatagram;
273 /// # use uds_fork::{UnixDatagramExt, UnixSocketAddr};
274 /// #
275 /// let socket = UnixDatagram::unbound().expect("create datagram socket");
276 /// let _ = socket.send_to_unix_addr(
277 /// b"Is there anyone there?",
278 /// &UnixSocketAddr::from_abstract("somewhere").expect("OS supports abstract addresses"),
279 /// );
280 /// ```
281 fn send_to_unix_addr(&self, datagram: &[u8], addr: &UnixSocketAddr) -> Result<usize, io::Error>
282 {
283 let (sockaddr, socklen) = addr.as_raw_general();
284
285 return
286 unsafe {
287 cvt_r!(
288 sendto(
289 self.as_raw_fd(),
290 datagram.as_ptr() as *const c_void,
291 datagram.len(),
292 MSG_NOSIGNAL,
293 sockaddr,
294 socklen,
295 )
296 )
297 .map(|signed| signed as usize )
298 };
299 }
300 /// Sends a datagram created from multiple segments to the specified address,
301 /// using an address type that supports abstract addresses.
302 ///
303 /// # Examples
304 ///
305 /// Send a datagram with a fixed header:
306 ///
307 /// ```
308 /// # use std::os::unix::net::UnixDatagram;
309 /// # use std::io::IoSlice;
310 /// # use uds_fork::{UnixDatagramExt, UnixSocketAddr};
311 /// #
312 /// let socket = UnixDatagram::unbound().expect("create datagram socket");
313 /// let to = UnixSocketAddr::new("/var/run/someone.sock").unwrap();
314 /// let msg = [
315 /// IoSlice::new(b"hello "),
316 /// IoSlice::new(to.as_pathname().unwrap().to_str().unwrap().as_bytes()),
317 /// ];
318 /// let _ = socket.send_vectored_to_unix_addr(&msg, &to);
319 /// ```
320 fn send_vectored_to_unix_addr(&self, datagram: &[IoSlice], addr: &UnixSocketAddr) -> Result<usize, io::Error>
321 {
322 send_ancillary(self, Some(addr), 0, datagram, &[], None)
323 }
324
325 /// Receives from any peer, storing its address in a type that exposes
326 /// abstract addresses.
327 ///
328 /// # Examples
329 ///
330 /// Respond to the received datagram, regardsless of where it was sent from:
331 ///
332 /// ```
333 /// use std::os::unix::net::UnixDatagram;
334 /// use uds_fork::{UnixSocketAddr, UnixDatagramExt};
335 ///
336 /// let dir = tempfile::tempdir().unwrap();
337 /// let mut file_path = dir.path().join("echo.sock");
338 ///
339 /// let server = UnixDatagram::bind(&file_path).expect("create server socket");
340 ///
341 /// let mut cli_file_path = dir.path().join("echo_client.sock");
342 ///
343 /// let client_addr = UnixSocketAddr::new("@echo_client")
344 /// .or(UnixSocketAddr::new(cli_file_path.as_os_str().to_str().unwrap()))
345 /// .unwrap();
346 /// let client = UnixDatagram::unbound().expect("create client ocket");
347 /// client.bind_to_unix_addr(&client_addr).expect("create client socket");
348 /// client.connect_to_unix_addr(&UnixSocketAddr::new(file_path.as_os_str().to_str().unwrap()).unwrap())
349 /// .expect("connect to server");
350 /// client.send(b"hello").expect("send");
351 ///
352 /// let mut buf = [0; 1024];
353 /// let (len, from) = server.recv_from_unix_addr(&mut buf).expect("receive");
354 /// server.send_to_unix_addr(&buf[..len], &from).expect("respond");
355 ///
356 /// let len = client.recv(&mut buf).expect("receive response");
357 /// assert_eq!(&buf[..len], "hello".as_bytes());
358 ///
359 /// let _ = std::fs::remove_file(&file_path);
360 /// if let Some(client_path) = client_addr.as_pathname() {
361 /// let _ = std::fs::remove_file(client_path);
362 /// }
363 /// ```
364 fn recv_from_unix_addr(&self, buf: &mut[u8]) -> Result<(usize, UnixSocketAddr), io::Error>
365 {
366 UnixSocketAddr::new_from_ffi(
367 |addr, len|
368 {
369 unsafe {
370 cvt_r!(
371 recvfrom(
372 self.as_raw_fd(),
373 buf.as_ptr() as *mut c_void,
374 buf.len(),
375 MSG_NOSIGNAL,
376 addr,
377 len,
378 )
379 )
380 .map(|signed| signed as usize )
381 }
382 }
383 )
384 }
385 /// Uses multiple buffers to receive from any peer, storing its address in
386 /// a type that exposes abstract addresses.
387 fn recv_vectored_from_unix_addr(&self, bufs: &mut[IoSliceMut]) -> Result<(usize, UnixSocketAddr), io::Error>
388 {
389 let mut addr = UnixSocketAddr::default();
390
391 recv_slice_fds(self, Some(&mut addr), bufs, &mut [])
392 .map(|(bytes, _, _)| (bytes, addr) )
393 }
394
395 /// Reads the next datagram without removing it from the queue.
396 ///
397 /// # Examples
398 ///
399 /// Discard datagram if it's the wrong protocol:
400 ///
401 /// ```
402 /// # use std::os::unix::net::UnixDatagram;
403 /// # use uds_fork::{UnixSocketAddr, UnixDatagramExt};
404 /// #
405 /// let checker = UnixDatagram::bind("/tmp/checker.sock").expect("create receiver socket");
406 ///
407 /// let client = UnixDatagram::unbound().expect("create client ocket");
408 /// client.send_to(b"hello", "/tmp/checker.sock").expect("send");
409 ///
410 /// let mut header = [0; 4];
411 /// let (len, _from) = checker.peek_from_unix_addr(&mut header).expect("receive");
412 /// if len != 4 || header != *b"WTFP" {
413 /// let _ = checker.recv(&mut header); // discard
414 /// } else {
415 /// // call function that receives and processes it
416 /// }
417 /// #
418 /// # let _ = std::fs::remove_file("/tmp/checker.sock");
419 /// ```
420 fn peek_from_unix_addr(&self, buf: &mut[u8]) -> Result<(usize, UnixSocketAddr), io::Error>
421 {
422 UnixSocketAddr::new_from_ffi(
423 |addr, len|
424 {
425 unsafe
426 {
427 cvt_r!(
428 recvfrom(
429 self.as_raw_fd(),
430 buf.as_ptr() as *mut c_void,
431 buf.len(),
432 MSG_PEEK | MSG_NOSIGNAL,
433 addr,
434 len,
435 )
436 )
437 .map(|signed| signed as usize )
438 }
439 })
440 }
441
442 /// Uses multiple buffers to read the next datagram without removing it
443 /// from the queue.
444 ///
445 /// # Examples
446 ///
447 #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
448 #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
449 /// use std::os::unix::net::UnixDatagram;
450 /// use std::io::IoSliceMut;
451 /// use tempfile::TempDir;
452 /// use uds_fork::{UnixDatagramExt, UnixSocketAddr};
453 ///
454 /// let dir = tempfile::tempdir().unwrap();
455 /// let mut path = dir.path().join("datagram_server.sock");
456 ///
457 /// let server = UnixDatagram::bind(&path).unwrap();
458 ///
459 /// // get a random abstract address on Linux
460 /// let client = UnixDatagram::unbound().unwrap();
461 /// client.bind_to_unix_addr(&UnixSocketAddr::new_unspecified()).unwrap();
462 /// client.connect(&path).unwrap();
463 /// client.send(b"headerbodybody").unwrap();
464 ///
465 /// let (mut buf_a, mut buf_b) = ([0; 6], [0; 12]);
466 /// let mut vector = [IoSliceMut::new(&mut buf_a), IoSliceMut::new(&mut buf_b)];
467 /// let (bytes, addr) = server.peek_vectored_from_unix_addr(&mut vector).unwrap();
468 /// assert_eq!(addr, client.local_unix_addr().unwrap());
469 /// assert_eq!(bytes, 14);
470 /// assert_eq!(&buf_a, b"header");
471 /// assert_eq!(&buf_b[..8], b"bodybody");
472 /// #
473 /// ```
474 fn peek_vectored_from_unix_addr(&self, bufs: &mut[IoSliceMut]) -> Result<(usize, UnixSocketAddr), io::Error>
475 {
476 let mut addr = UnixSocketAddr::default();
477
478 recv_ancillary(self,Some(&mut addr),MSG_PEEK | MSG_NOSIGNAL, bufs,&mut[])
479 .map(|(bytes, _)| (bytes, addr) )
480 }
481
482 /// Sends file descriptors along with the datagram, on an unconnected socket.
483 fn send_fds_to(&self, datagram: &[u8], fds: Vec<OwnedFd>, addr: &UnixSocketAddr) -> Result<usize, io::Error>
484 {
485 let fds_raw = fds.iter().map(|fd| fd.as_raw_fd()).collect::<Vec<RawFd>>();
486
487 send_ancillary(self, Some(addr), 0, &[IoSlice::new(datagram)], &fds_raw, None)
488 }
489
490 unsafe
491 fn send_fds_to_raw(&self, datagram: &[u8], fds: &[RawFd], addr: &UnixSocketAddr) -> Result<usize, io::Error>
492 {
493 send_ancillary(self, Some(addr), 0, &[IoSlice::new(datagram)], fds, None)
494 }
495
496 /// Sends file descriptors along with the datagram, on a connected socket.
497 fn send_fds(&self, datagram: &[u8], fds: Vec<OwnedFd>) -> Result<usize, io::Error>
498 {
499 let fds_raw = fds.iter().map(|fd| fd.as_raw_fd()).collect::<Vec<RawFd>>();
500
501 send_ancillary(self, None, 0, &[IoSlice::new(datagram)], &fds_raw, None)
502 }
503
504 unsafe
505 fn send_fds_raw(&self, datagram: &[u8], fds: &[RawFd]) -> Result<usize, io::Error>
506 {
507 send_ancillary(self, None, 0, &[IoSlice::new(datagram)],
508 fds, None)
509 }
510
511 /// Receives file descriptors along with the datagram, on an unconnected socket
512 fn recv_slice_fds_from(&self, buf: &mut[u8], fd_buf: &mut [Option<OwnedFd>]) -> Result<(usize, usize, UnixSocketAddr), io::Error>
513 {
514 let mut addr = UnixSocketAddr::default();
515 recv_slice_fds(self, Some(&mut addr), &mut[IoSliceMut::new(buf)], fd_buf)
516 .map(|(bytes, _, fds)| (bytes, fds, addr) )
517 }
518
519 fn recv_fds_from(&self, buf: &mut[u8], fd_buf: &mut Vec<OwnedFd>) -> Result<(usize, usize, UnixSocketAddr), io::Error>
520 {
521 let mut addr = UnixSocketAddr::default();
522
523 recv_fds(self, Some(&mut addr), &mut[IoSliceMut::new(buf)], fd_buf)
524 .map(|(bytes, _, fds)| (bytes, fds, addr) )
525 }
526
527 /// Receives file descriptors along with the datagram, on a connected socket
528 fn recv_slice_fds(&self, buf: &mut[u8], fd_buf: &mut [Option<OwnedFd>]) -> Result<(usize, usize), io::Error>
529 {
530 recv_slice_fds(self, None, &mut[IoSliceMut::new(buf)], fd_buf)
531 .map(|(bytes, _, fds)| (bytes, fds) )
532 }
533
534
535 fn recv_fds(&self, buf: &mut[u8], fd_buf: &mut Vec<OwnedFd>) -> Result<(usize, usize), io::Error>
536 {
537 recv_fds(self, None, &mut[IoSliceMut::new(buf)], fd_buf)
538 .map(|(bytes, _, fds)| (bytes, fds) )
539 }
540
541
542 /// Returns the credentials of the process that created a socket pair.
543 ///
544 /// This information is only available on Linux, and only for sockets that
545 /// was created with `pair()` or the underlying `socketpair()`.
546 /// For sockets that have merely been "connected" to an address
547 /// or not connected at all, an error of kind `NotConnected`
548 /// or `InvalidInput` is returned.
549 ///
550 /// The use cases of this function gotta be very narrow:
551 ///
552 /// * It will return the credentials of the current process unless
553 /// the side of the socket this method is called on was received via
554 /// FD-passing or inherited from a parent.
555 /// * If it was created by the direct parent process,
556 /// one might as well use `getppid()` and go from there?
557 /// * A returned pid can be repurposed by the OS before the call returns.
558 /// * uids or groups will be those in effect when the pair was created,
559 /// and will not reflect changes in privileges.
560 ///
561 /// Despite these limitations, the feature is supported by Linux at least
562 /// (but not macOS or FreeBSD), so might as well expose it.
563 fn initial_pair_credentials(&self) -> Result<ConnCredentials, io::Error>
564 {
565 peer_credentials(self)
566 }
567 /// Returns the SELinux security context of the process that created a socket pair.
568 ///
569 /// Has the same limitations and gotchas as `initial_pair_credentials()`,
570 /// and will return an error on other OSes than Linux or Android
571 /// or if running under kubernetes.
572 ///
573 /// The default security context is the string `unconfined`.
574 fn initial_pair_selinux_context(&self, buffer: &mut[u8]) -> Result<usize, io::Error>
575 {
576 selinux_context(self, buffer)
577 }
578}
579
580impl UnixDatagramExt for UnixDatagram
581{
582 fn bind_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error>
583 {
584 return
585 UnixDatagram::unbound()
586 .map_or_else(
587 |e| Err(e),
588 |socket|
589 socket
590 .bind_to_unix_addr(addr)
591 .map_or_else(
592 |e| Err(e),
593 |_| Ok(socket)
594 )
595 );
596 }
597}
598
599#[cfg(feature = "mio")]
600impl UnixDatagramExt for mio::net::UnixDatagram
601{
602 fn bind_unix_addr(addr: &UnixSocketAddr) -> Result<Self, io::Error>
603 {
604 return
605 mio::net::UnixDatagram
606 ::unbound()
607 .map_or_else(
608 |e| Err(e),
609 |socket|
610 socket
611 .bind_to_unix_addr(addr)
612 .map_or_else(
613 |e| Err(e),
614 |_| Ok(socket)
615 )
616 );
617 }
618}