]>
Commit | Line | Data |
---|---|---|
fc512014 XL |
1 | #[cfg(any( |
2 | doc, | |
3 | target_os = "android", | |
4 | target_os = "dragonfly", | |
5 | target_os = "emscripten", | |
6 | target_os = "freebsd", | |
7 | target_os = "linux", | |
8 | target_os = "netbsd", | |
9 | target_os = "openbsd", | |
10 | ))] | |
11 | use super::{recv_vectored_with_ancillary_from, send_vectored_with_ancillary_to, SocketAncillary}; | |
12 | use super::{sockaddr_un, SocketAddr}; | |
13 | #[cfg(any( | |
14 | target_os = "android", | |
15 | target_os = "dragonfly", | |
16 | target_os = "emscripten", | |
17 | target_os = "freebsd", | |
18 | target_os = "linux", | |
19 | target_os = "netbsd", | |
20 | target_os = "openbsd", | |
21 | ))] | |
6a06907d | 22 | use crate::io::{IoSlice, IoSliceMut}; |
fc512014 XL |
23 | use crate::net::Shutdown; |
24 | use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; | |
25 | use crate::path::Path; | |
26 | use crate::sys::cvt; | |
27 | use crate::sys::net::Socket; | |
28 | use crate::sys_common::{AsInner, FromInner, IntoInner}; | |
29 | use crate::time::Duration; | |
30 | use crate::{fmt, io}; | |
31 | ||
32 | #[cfg(any( | |
33 | target_os = "linux", | |
34 | target_os = "android", | |
35 | target_os = "dragonfly", | |
36 | target_os = "freebsd", | |
37 | target_os = "openbsd", | |
38 | target_os = "netbsd", | |
39 | target_os = "haiku" | |
40 | ))] | |
41 | use libc::MSG_NOSIGNAL; | |
42 | #[cfg(not(any( | |
43 | target_os = "linux", | |
44 | target_os = "android", | |
45 | target_os = "dragonfly", | |
46 | target_os = "freebsd", | |
47 | target_os = "openbsd", | |
48 | target_os = "netbsd", | |
49 | target_os = "haiku" | |
50 | )))] | |
51 | const MSG_NOSIGNAL: libc::c_int = 0x0; | |
52 | ||
53 | /// A Unix datagram socket. | |
54 | /// | |
55 | /// # Examples | |
56 | /// | |
57 | /// ```no_run | |
58 | /// use std::os::unix::net::UnixDatagram; | |
59 | /// | |
60 | /// fn main() -> std::io::Result<()> { | |
61 | /// let socket = UnixDatagram::bind("/path/to/my/socket")?; | |
62 | /// socket.send_to(b"hello world", "/path/to/other/socket")?; | |
63 | /// let mut buf = [0; 100]; | |
64 | /// let (count, address) = socket.recv_from(&mut buf)?; | |
65 | /// println!("socket {:?} sent {:?}", address, &buf[..count]); | |
66 | /// Ok(()) | |
67 | /// } | |
68 | /// ``` | |
69 | #[stable(feature = "unix_socket", since = "1.10.0")] | |
70 | pub struct UnixDatagram(Socket); | |
71 | ||
72 | #[stable(feature = "unix_socket", since = "1.10.0")] | |
73 | impl fmt::Debug for UnixDatagram { | |
74 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | |
75 | let mut builder = fmt.debug_struct("UnixDatagram"); | |
76 | builder.field("fd", self.0.as_inner()); | |
77 | if let Ok(addr) = self.local_addr() { | |
78 | builder.field("local", &addr); | |
79 | } | |
80 | if let Ok(addr) = self.peer_addr() { | |
81 | builder.field("peer", &addr); | |
82 | } | |
83 | builder.finish() | |
84 | } | |
85 | } | |
86 | ||
87 | impl UnixDatagram { | |
88 | /// Creates a Unix datagram socket bound to the given path. | |
89 | /// | |
90 | /// # Examples | |
91 | /// | |
92 | /// ```no_run | |
93 | /// use std::os::unix::net::UnixDatagram; | |
94 | /// | |
95 | /// let sock = match UnixDatagram::bind("/path/to/the/socket") { | |
96 | /// Ok(sock) => sock, | |
97 | /// Err(e) => { | |
98 | /// println!("Couldn't bind: {:?}", e); | |
99 | /// return | |
100 | /// } | |
101 | /// }; | |
102 | /// ``` | |
103 | #[stable(feature = "unix_socket", since = "1.10.0")] | |
104 | pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixDatagram> { | |
105 | unsafe { | |
106 | let socket = UnixDatagram::unbound()?; | |
107 | let (addr, len) = sockaddr_un(path.as_ref())?; | |
108 | ||
109 | cvt(libc::bind(*socket.0.as_inner(), &addr as *const _ as *const _, len as _))?; | |
110 | ||
111 | Ok(socket) | |
112 | } | |
113 | } | |
114 | ||
115 | /// Creates a Unix Datagram socket which is not bound to any address. | |
116 | /// | |
117 | /// # Examples | |
118 | /// | |
119 | /// ```no_run | |
120 | /// use std::os::unix::net::UnixDatagram; | |
121 | /// | |
122 | /// let sock = match UnixDatagram::unbound() { | |
123 | /// Ok(sock) => sock, | |
124 | /// Err(e) => { | |
125 | /// println!("Couldn't unbound: {:?}", e); | |
126 | /// return | |
127 | /// } | |
128 | /// }; | |
129 | /// ``` | |
130 | #[stable(feature = "unix_socket", since = "1.10.0")] | |
131 | pub fn unbound() -> io::Result<UnixDatagram> { | |
132 | let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_DGRAM)?; | |
133 | Ok(UnixDatagram(inner)) | |
134 | } | |
135 | ||
136 | /// Creates an unnamed pair of connected sockets. | |
137 | /// | |
138 | /// Returns two `UnixDatagrams`s which are connected to each other. | |
139 | /// | |
140 | /// # Examples | |
141 | /// | |
142 | /// ```no_run | |
143 | /// use std::os::unix::net::UnixDatagram; | |
144 | /// | |
145 | /// let (sock1, sock2) = match UnixDatagram::pair() { | |
146 | /// Ok((sock1, sock2)) => (sock1, sock2), | |
147 | /// Err(e) => { | |
148 | /// println!("Couldn't unbound: {:?}", e); | |
149 | /// return | |
150 | /// } | |
151 | /// }; | |
152 | /// ``` | |
153 | #[stable(feature = "unix_socket", since = "1.10.0")] | |
154 | pub fn pair() -> io::Result<(UnixDatagram, UnixDatagram)> { | |
155 | let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_DGRAM)?; | |
156 | Ok((UnixDatagram(i1), UnixDatagram(i2))) | |
157 | } | |
158 | ||
159 | /// Connects the socket to the specified address. | |
160 | /// | |
161 | /// The [`send`] method may be used to send data to the specified address. | |
162 | /// [`recv`] and [`recv_from`] will only receive data from that address. | |
163 | /// | |
164 | /// [`send`]: UnixDatagram::send | |
165 | /// [`recv`]: UnixDatagram::recv | |
166 | /// [`recv_from`]: UnixDatagram::recv_from | |
167 | /// | |
168 | /// # Examples | |
169 | /// | |
170 | /// ```no_run | |
171 | /// use std::os::unix::net::UnixDatagram; | |
172 | /// | |
173 | /// fn main() -> std::io::Result<()> { | |
174 | /// let sock = UnixDatagram::unbound()?; | |
175 | /// match sock.connect("/path/to/the/socket") { | |
176 | /// Ok(sock) => sock, | |
177 | /// Err(e) => { | |
178 | /// println!("Couldn't connect: {:?}", e); | |
179 | /// return Err(e) | |
180 | /// } | |
181 | /// }; | |
182 | /// Ok(()) | |
183 | /// } | |
184 | /// ``` | |
185 | #[stable(feature = "unix_socket", since = "1.10.0")] | |
186 | pub fn connect<P: AsRef<Path>>(&self, path: P) -> io::Result<()> { | |
187 | unsafe { | |
188 | let (addr, len) = sockaddr_un(path.as_ref())?; | |
189 | ||
190 | cvt(libc::connect(*self.0.as_inner(), &addr as *const _ as *const _, len))?; | |
191 | } | |
192 | Ok(()) | |
193 | } | |
194 | ||
195 | /// Creates a new independently owned handle to the underlying socket. | |
196 | /// | |
197 | /// The returned `UnixDatagram` is a reference to the same socket that this | |
198 | /// object references. Both handles can be used to accept incoming | |
199 | /// connections and options set on one side will affect the other. | |
200 | /// | |
201 | /// # Examples | |
202 | /// | |
203 | /// ```no_run | |
204 | /// use std::os::unix::net::UnixDatagram; | |
205 | /// | |
206 | /// fn main() -> std::io::Result<()> { | |
207 | /// let sock = UnixDatagram::bind("/path/to/the/socket")?; | |
208 | /// let sock_copy = sock.try_clone().expect("try_clone failed"); | |
209 | /// Ok(()) | |
210 | /// } | |
211 | /// ``` | |
212 | #[stable(feature = "unix_socket", since = "1.10.0")] | |
213 | pub fn try_clone(&self) -> io::Result<UnixDatagram> { | |
214 | self.0.duplicate().map(UnixDatagram) | |
215 | } | |
216 | ||
217 | /// Returns the address of this socket. | |
218 | /// | |
219 | /// # Examples | |
220 | /// | |
221 | /// ```no_run | |
222 | /// use std::os::unix::net::UnixDatagram; | |
223 | /// | |
224 | /// fn main() -> std::io::Result<()> { | |
225 | /// let sock = UnixDatagram::bind("/path/to/the/socket")?; | |
226 | /// let addr = sock.local_addr().expect("Couldn't get local address"); | |
227 | /// Ok(()) | |
228 | /// } | |
229 | /// ``` | |
230 | #[stable(feature = "unix_socket", since = "1.10.0")] | |
231 | pub fn local_addr(&self) -> io::Result<SocketAddr> { | |
232 | SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) }) | |
233 | } | |
234 | ||
235 | /// Returns the address of this socket's peer. | |
236 | /// | |
237 | /// The [`connect`] method will connect the socket to a peer. | |
238 | /// | |
239 | /// [`connect`]: UnixDatagram::connect | |
240 | /// | |
241 | /// # Examples | |
242 | /// | |
243 | /// ```no_run | |
244 | /// use std::os::unix::net::UnixDatagram; | |
245 | /// | |
246 | /// fn main() -> std::io::Result<()> { | |
247 | /// let sock = UnixDatagram::unbound()?; | |
248 | /// sock.connect("/path/to/the/socket")?; | |
249 | /// | |
250 | /// let addr = sock.peer_addr().expect("Couldn't get peer address"); | |
251 | /// Ok(()) | |
252 | /// } | |
253 | /// ``` | |
254 | #[stable(feature = "unix_socket", since = "1.10.0")] | |
255 | pub fn peer_addr(&self) -> io::Result<SocketAddr> { | |
256 | SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) }) | |
257 | } | |
258 | ||
259 | fn recv_from_flags( | |
260 | &self, | |
261 | buf: &mut [u8], | |
262 | flags: libc::c_int, | |
263 | ) -> io::Result<(usize, SocketAddr)> { | |
264 | let mut count = 0; | |
265 | let addr = SocketAddr::new(|addr, len| unsafe { | |
266 | count = libc::recvfrom( | |
267 | *self.0.as_inner(), | |
268 | buf.as_mut_ptr() as *mut _, | |
269 | buf.len(), | |
270 | flags, | |
271 | addr, | |
272 | len, | |
273 | ); | |
274 | if count > 0 { | |
275 | 1 | |
276 | } else if count == 0 { | |
277 | 0 | |
278 | } else { | |
279 | -1 | |
280 | } | |
281 | })?; | |
282 | ||
283 | Ok((count as usize, addr)) | |
284 | } | |
285 | ||
286 | /// Receives data from the socket. | |
287 | /// | |
288 | /// On success, returns the number of bytes read and the address from | |
289 | /// whence the data came. | |
290 | /// | |
291 | /// # Examples | |
292 | /// | |
293 | /// ```no_run | |
294 | /// use std::os::unix::net::UnixDatagram; | |
295 | /// | |
296 | /// fn main() -> std::io::Result<()> { | |
297 | /// let sock = UnixDatagram::unbound()?; | |
298 | /// let mut buf = vec![0; 10]; | |
299 | /// let (size, sender) = sock.recv_from(buf.as_mut_slice())?; | |
300 | /// println!("received {} bytes from {:?}", size, sender); | |
301 | /// Ok(()) | |
302 | /// } | |
303 | /// ``` | |
304 | #[stable(feature = "unix_socket", since = "1.10.0")] | |
305 | pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { | |
306 | self.recv_from_flags(buf, 0) | |
307 | } | |
308 | ||
309 | /// Receives data from the socket. | |
310 | /// | |
311 | /// On success, returns the number of bytes read. | |
312 | /// | |
313 | /// # Examples | |
314 | /// | |
315 | /// ```no_run | |
316 | /// use std::os::unix::net::UnixDatagram; | |
317 | /// | |
318 | /// fn main() -> std::io::Result<()> { | |
319 | /// let sock = UnixDatagram::bind("/path/to/the/socket")?; | |
320 | /// let mut buf = vec![0; 10]; | |
321 | /// sock.recv(buf.as_mut_slice()).expect("recv function failed"); | |
322 | /// Ok(()) | |
323 | /// } | |
324 | /// ``` | |
325 | #[stable(feature = "unix_socket", since = "1.10.0")] | |
326 | pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> { | |
327 | self.0.read(buf) | |
328 | } | |
329 | ||
330 | /// Receives data and ancillary data from socket. | |
331 | /// | |
332 | /// On success, returns the number of bytes read, if the data was truncated and the address from whence the msg came. | |
333 | /// | |
334 | /// # Examples | |
335 | /// | |
336 | /// ```no_run | |
337 | /// #![feature(unix_socket_ancillary_data)] | |
338 | /// use std::os::unix::net::{UnixDatagram, SocketAncillary, AncillaryData}; | |
339 | /// use std::io::IoSliceMut; | |
340 | /// | |
341 | /// fn main() -> std::io::Result<()> { | |
342 | /// let sock = UnixDatagram::unbound()?; | |
343 | /// let mut buf1 = [1; 8]; | |
344 | /// let mut buf2 = [2; 16]; | |
345 | /// let mut buf3 = [3; 8]; | |
346 | /// let mut bufs = &mut [ | |
347 | /// IoSliceMut::new(&mut buf1), | |
348 | /// IoSliceMut::new(&mut buf2), | |
349 | /// IoSliceMut::new(&mut buf3), | |
350 | /// ][..]; | |
351 | /// let mut fds = [0; 8]; | |
352 | /// let mut ancillary_buffer = [0; 128]; | |
353 | /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]); | |
354 | /// let (size, _truncated, sender) = sock.recv_vectored_with_ancillary_from(bufs, &mut ancillary)?; | |
355 | /// println!("received {}", size); | |
356 | /// for ancillary_result in ancillary.messages() { | |
357 | /// if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() { | |
358 | /// for fd in scm_rights { | |
359 | /// println!("receive file descriptor: {}", fd); | |
360 | /// } | |
361 | /// } | |
362 | /// } | |
363 | /// Ok(()) | |
364 | /// } | |
365 | /// ``` | |
366 | #[cfg(any( | |
367 | target_os = "android", | |
368 | target_os = "dragonfly", | |
369 | target_os = "emscripten", | |
370 | target_os = "freebsd", | |
371 | target_os = "linux", | |
372 | target_os = "netbsd", | |
373 | target_os = "openbsd", | |
374 | ))] | |
375 | #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] | |
376 | pub fn recv_vectored_with_ancillary_from( | |
377 | &self, | |
378 | bufs: &mut [IoSliceMut<'_>], | |
379 | ancillary: &mut SocketAncillary<'_>, | |
380 | ) -> io::Result<(usize, bool, SocketAddr)> { | |
381 | let (count, truncated, addr) = recv_vectored_with_ancillary_from(&self.0, bufs, ancillary)?; | |
382 | let addr = addr?; | |
383 | ||
384 | Ok((count, truncated, addr)) | |
385 | } | |
386 | ||
387 | /// Receives data and ancillary data from socket. | |
388 | /// | |
389 | /// On success, returns the number of bytes read and if the data was truncated. | |
390 | /// | |
391 | /// # Examples | |
392 | /// | |
393 | /// ```no_run | |
394 | /// #![feature(unix_socket_ancillary_data)] | |
395 | /// use std::os::unix::net::{UnixDatagram, SocketAncillary, AncillaryData}; | |
396 | /// use std::io::IoSliceMut; | |
397 | /// | |
398 | /// fn main() -> std::io::Result<()> { | |
399 | /// let sock = UnixDatagram::unbound()?; | |
400 | /// let mut buf1 = [1; 8]; | |
401 | /// let mut buf2 = [2; 16]; | |
402 | /// let mut buf3 = [3; 8]; | |
403 | /// let mut bufs = &mut [ | |
404 | /// IoSliceMut::new(&mut buf1), | |
405 | /// IoSliceMut::new(&mut buf2), | |
406 | /// IoSliceMut::new(&mut buf3), | |
407 | /// ][..]; | |
408 | /// let mut fds = [0; 8]; | |
409 | /// let mut ancillary_buffer = [0; 128]; | |
410 | /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]); | |
411 | /// let (size, _truncated) = sock.recv_vectored_with_ancillary(bufs, &mut ancillary)?; | |
412 | /// println!("received {}", size); | |
413 | /// for ancillary_result in ancillary.messages() { | |
414 | /// if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() { | |
415 | /// for fd in scm_rights { | |
416 | /// println!("receive file descriptor: {}", fd); | |
417 | /// } | |
418 | /// } | |
419 | /// } | |
420 | /// Ok(()) | |
421 | /// } | |
422 | /// ``` | |
423 | #[cfg(any( | |
424 | target_os = "android", | |
425 | target_os = "dragonfly", | |
426 | target_os = "emscripten", | |
427 | target_os = "freebsd", | |
428 | target_os = "linux", | |
429 | target_os = "netbsd", | |
430 | target_os = "openbsd", | |
431 | ))] | |
432 | #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] | |
433 | pub fn recv_vectored_with_ancillary( | |
434 | &self, | |
435 | bufs: &mut [IoSliceMut<'_>], | |
436 | ancillary: &mut SocketAncillary<'_>, | |
437 | ) -> io::Result<(usize, bool)> { | |
438 | let (count, truncated, addr) = recv_vectored_with_ancillary_from(&self.0, bufs, ancillary)?; | |
439 | addr?; | |
440 | ||
441 | Ok((count, truncated)) | |
442 | } | |
443 | ||
444 | /// Sends data on the socket to the specified address. | |
445 | /// | |
446 | /// On success, returns the number of bytes written. | |
447 | /// | |
448 | /// # Examples | |
449 | /// | |
450 | /// ```no_run | |
451 | /// use std::os::unix::net::UnixDatagram; | |
452 | /// | |
453 | /// fn main() -> std::io::Result<()> { | |
454 | /// let sock = UnixDatagram::unbound()?; | |
455 | /// sock.send_to(b"omelette au fromage", "/some/sock").expect("send_to function failed"); | |
456 | /// Ok(()) | |
457 | /// } | |
458 | /// ``` | |
459 | #[stable(feature = "unix_socket", since = "1.10.0")] | |
460 | pub fn send_to<P: AsRef<Path>>(&self, buf: &[u8], path: P) -> io::Result<usize> { | |
461 | unsafe { | |
462 | let (addr, len) = sockaddr_un(path.as_ref())?; | |
463 | ||
464 | let count = cvt(libc::sendto( | |
465 | *self.0.as_inner(), | |
466 | buf.as_ptr() as *const _, | |
467 | buf.len(), | |
468 | MSG_NOSIGNAL, | |
469 | &addr as *const _ as *const _, | |
470 | len, | |
471 | ))?; | |
472 | Ok(count as usize) | |
473 | } | |
474 | } | |
475 | ||
476 | /// Sends data on the socket to the socket's peer. | |
477 | /// | |
478 | /// The peer address may be set by the `connect` method, and this method | |
479 | /// will return an error if the socket has not already been connected. | |
480 | /// | |
481 | /// On success, returns the number of bytes written. | |
482 | /// | |
483 | /// # Examples | |
484 | /// | |
485 | /// ```no_run | |
486 | /// use std::os::unix::net::UnixDatagram; | |
487 | /// | |
488 | /// fn main() -> std::io::Result<()> { | |
489 | /// let sock = UnixDatagram::unbound()?; | |
490 | /// sock.connect("/some/sock").expect("Couldn't connect"); | |
491 | /// sock.send(b"omelette au fromage").expect("send_to function failed"); | |
492 | /// Ok(()) | |
493 | /// } | |
494 | /// ``` | |
495 | #[stable(feature = "unix_socket", since = "1.10.0")] | |
496 | pub fn send(&self, buf: &[u8]) -> io::Result<usize> { | |
497 | self.0.write(buf) | |
498 | } | |
499 | ||
500 | /// Sends data and ancillary data on the socket to the specified address. | |
501 | /// | |
502 | /// On success, returns the number of bytes written. | |
503 | /// | |
504 | /// # Examples | |
505 | /// | |
506 | /// ```no_run | |
507 | /// #![feature(unix_socket_ancillary_data)] | |
508 | /// use std::os::unix::net::{UnixDatagram, SocketAncillary}; | |
6a06907d | 509 | /// use std::io::IoSlice; |
fc512014 XL |
510 | /// |
511 | /// fn main() -> std::io::Result<()> { | |
512 | /// let sock = UnixDatagram::unbound()?; | |
6a06907d XL |
513 | /// let buf1 = [1; 8]; |
514 | /// let buf2 = [2; 16]; | |
515 | /// let buf3 = [3; 8]; | |
516 | /// let bufs = &[ | |
517 | /// IoSlice::new(&buf1), | |
518 | /// IoSlice::new(&buf2), | |
519 | /// IoSlice::new(&buf3), | |
fc512014 XL |
520 | /// ][..]; |
521 | /// let fds = [0, 1, 2]; | |
522 | /// let mut ancillary_buffer = [0; 128]; | |
523 | /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]); | |
524 | /// ancillary.add_fds(&fds[..]); | |
6a06907d XL |
525 | /// sock.send_vectored_with_ancillary_to(bufs, &mut ancillary, "/some/sock") |
526 | /// .expect("send_vectored_with_ancillary_to function failed"); | |
fc512014 XL |
527 | /// Ok(()) |
528 | /// } | |
529 | /// ``` | |
530 | #[cfg(any( | |
531 | target_os = "android", | |
532 | target_os = "dragonfly", | |
533 | target_os = "emscripten", | |
534 | target_os = "freebsd", | |
535 | target_os = "linux", | |
536 | target_os = "netbsd", | |
537 | target_os = "openbsd", | |
538 | ))] | |
539 | #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] | |
540 | pub fn send_vectored_with_ancillary_to<P: AsRef<Path>>( | |
541 | &self, | |
6a06907d | 542 | bufs: &[IoSlice<'_>], |
fc512014 XL |
543 | ancillary: &mut SocketAncillary<'_>, |
544 | path: P, | |
545 | ) -> io::Result<usize> { | |
546 | send_vectored_with_ancillary_to(&self.0, Some(path.as_ref()), bufs, ancillary) | |
547 | } | |
548 | ||
549 | /// Sends data and ancillary data on the socket. | |
550 | /// | |
551 | /// On success, returns the number of bytes written. | |
552 | /// | |
553 | /// # Examples | |
554 | /// | |
555 | /// ```no_run | |
556 | /// #![feature(unix_socket_ancillary_data)] | |
557 | /// use std::os::unix::net::{UnixDatagram, SocketAncillary}; | |
6a06907d | 558 | /// use std::io::IoSlice; |
fc512014 XL |
559 | /// |
560 | /// fn main() -> std::io::Result<()> { | |
561 | /// let sock = UnixDatagram::unbound()?; | |
6a06907d XL |
562 | /// let buf1 = [1; 8]; |
563 | /// let buf2 = [2; 16]; | |
564 | /// let buf3 = [3; 8]; | |
565 | /// let bufs = &[ | |
566 | /// IoSlice::new(&buf1), | |
567 | /// IoSlice::new(&buf2), | |
568 | /// IoSlice::new(&buf3), | |
fc512014 XL |
569 | /// ][..]; |
570 | /// let fds = [0, 1, 2]; | |
571 | /// let mut ancillary_buffer = [0; 128]; | |
572 | /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]); | |
573 | /// ancillary.add_fds(&fds[..]); | |
6a06907d XL |
574 | /// sock.send_vectored_with_ancillary(bufs, &mut ancillary) |
575 | /// .expect("send_vectored_with_ancillary function failed"); | |
fc512014 XL |
576 | /// Ok(()) |
577 | /// } | |
578 | /// ``` | |
579 | #[cfg(any( | |
580 | target_os = "android", | |
581 | target_os = "dragonfly", | |
582 | target_os = "emscripten", | |
583 | target_os = "freebsd", | |
584 | target_os = "linux", | |
585 | target_os = "netbsd", | |
586 | target_os = "openbsd", | |
587 | ))] | |
588 | #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] | |
589 | pub fn send_vectored_with_ancillary( | |
590 | &self, | |
6a06907d | 591 | bufs: &[IoSlice<'_>], |
fc512014 XL |
592 | ancillary: &mut SocketAncillary<'_>, |
593 | ) -> io::Result<usize> { | |
594 | send_vectored_with_ancillary_to(&self.0, None, bufs, ancillary) | |
595 | } | |
596 | ||
597 | /// Sets the read timeout for the socket. | |
598 | /// | |
599 | /// If the provided value is [`None`], then [`recv`] and [`recv_from`] calls will | |
600 | /// block indefinitely. An [`Err`] is returned if the zero [`Duration`] | |
601 | /// is passed to this method. | |
602 | /// | |
603 | /// [`recv`]: UnixDatagram::recv | |
604 | /// [`recv_from`]: UnixDatagram::recv_from | |
605 | /// | |
606 | /// # Examples | |
607 | /// | |
608 | /// ``` | |
609 | /// use std::os::unix::net::UnixDatagram; | |
610 | /// use std::time::Duration; | |
611 | /// | |
612 | /// fn main() -> std::io::Result<()> { | |
613 | /// let sock = UnixDatagram::unbound()?; | |
614 | /// sock.set_read_timeout(Some(Duration::new(1, 0))) | |
615 | /// .expect("set_read_timeout function failed"); | |
616 | /// Ok(()) | |
617 | /// } | |
618 | /// ``` | |
619 | /// | |
620 | /// An [`Err`] is returned if the zero [`Duration`] is passed to this | |
621 | /// method: | |
622 | /// | |
623 | /// ```no_run | |
624 | /// use std::io; | |
625 | /// use std::os::unix::net::UnixDatagram; | |
626 | /// use std::time::Duration; | |
627 | /// | |
628 | /// fn main() -> std::io::Result<()> { | |
629 | /// let socket = UnixDatagram::unbound()?; | |
630 | /// let result = socket.set_read_timeout(Some(Duration::new(0, 0))); | |
631 | /// let err = result.unwrap_err(); | |
632 | /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput); | |
633 | /// Ok(()) | |
634 | /// } | |
635 | /// ``` | |
636 | #[stable(feature = "unix_socket", since = "1.10.0")] | |
637 | pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> { | |
638 | self.0.set_timeout(timeout, libc::SO_RCVTIMEO) | |
639 | } | |
640 | ||
641 | /// Sets the write timeout for the socket. | |
642 | /// | |
643 | /// If the provided value is [`None`], then [`send`] and [`send_to`] calls will | |
644 | /// block indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this | |
645 | /// method. | |
646 | /// | |
647 | /// [`send`]: UnixDatagram::send | |
648 | /// [`send_to`]: UnixDatagram::send_to | |
649 | /// | |
650 | /// # Examples | |
651 | /// | |
652 | /// ``` | |
653 | /// use std::os::unix::net::UnixDatagram; | |
654 | /// use std::time::Duration; | |
655 | /// | |
656 | /// fn main() -> std::io::Result<()> { | |
657 | /// let sock = UnixDatagram::unbound()?; | |
658 | /// sock.set_write_timeout(Some(Duration::new(1, 0))) | |
659 | /// .expect("set_write_timeout function failed"); | |
660 | /// Ok(()) | |
661 | /// } | |
662 | /// ``` | |
663 | /// | |
664 | /// An [`Err`] is returned if the zero [`Duration`] is passed to this | |
665 | /// method: | |
666 | /// | |
667 | /// ```no_run | |
668 | /// use std::io; | |
669 | /// use std::os::unix::net::UnixDatagram; | |
670 | /// use std::time::Duration; | |
671 | /// | |
672 | /// fn main() -> std::io::Result<()> { | |
673 | /// let socket = UnixDatagram::unbound()?; | |
674 | /// let result = socket.set_write_timeout(Some(Duration::new(0, 0))); | |
675 | /// let err = result.unwrap_err(); | |
676 | /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput); | |
677 | /// Ok(()) | |
678 | /// } | |
679 | /// ``` | |
680 | #[stable(feature = "unix_socket", since = "1.10.0")] | |
681 | pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> { | |
682 | self.0.set_timeout(timeout, libc::SO_SNDTIMEO) | |
683 | } | |
684 | ||
685 | /// Returns the read timeout of this socket. | |
686 | /// | |
687 | /// # Examples | |
688 | /// | |
689 | /// ``` | |
690 | /// use std::os::unix::net::UnixDatagram; | |
691 | /// use std::time::Duration; | |
692 | /// | |
693 | /// fn main() -> std::io::Result<()> { | |
694 | /// let sock = UnixDatagram::unbound()?; | |
695 | /// sock.set_read_timeout(Some(Duration::new(1, 0))) | |
696 | /// .expect("set_read_timeout function failed"); | |
697 | /// assert_eq!(sock.read_timeout()?, Some(Duration::new(1, 0))); | |
698 | /// Ok(()) | |
699 | /// } | |
700 | /// ``` | |
701 | #[stable(feature = "unix_socket", since = "1.10.0")] | |
702 | pub fn read_timeout(&self) -> io::Result<Option<Duration>> { | |
703 | self.0.timeout(libc::SO_RCVTIMEO) | |
704 | } | |
705 | ||
706 | /// Returns the write timeout of this socket. | |
707 | /// | |
708 | /// # Examples | |
709 | /// | |
710 | /// ``` | |
711 | /// use std::os::unix::net::UnixDatagram; | |
712 | /// use std::time::Duration; | |
713 | /// | |
714 | /// fn main() -> std::io::Result<()> { | |
715 | /// let sock = UnixDatagram::unbound()?; | |
716 | /// sock.set_write_timeout(Some(Duration::new(1, 0))) | |
717 | /// .expect("set_write_timeout function failed"); | |
718 | /// assert_eq!(sock.write_timeout()?, Some(Duration::new(1, 0))); | |
719 | /// Ok(()) | |
720 | /// } | |
721 | /// ``` | |
722 | #[stable(feature = "unix_socket", since = "1.10.0")] | |
723 | pub fn write_timeout(&self) -> io::Result<Option<Duration>> { | |
724 | self.0.timeout(libc::SO_SNDTIMEO) | |
725 | } | |
726 | ||
727 | /// Moves the socket into or out of nonblocking mode. | |
728 | /// | |
729 | /// # Examples | |
730 | /// | |
731 | /// ``` | |
732 | /// use std::os::unix::net::UnixDatagram; | |
733 | /// | |
734 | /// fn main() -> std::io::Result<()> { | |
735 | /// let sock = UnixDatagram::unbound()?; | |
736 | /// sock.set_nonblocking(true).expect("set_nonblocking function failed"); | |
737 | /// Ok(()) | |
738 | /// } | |
739 | /// ``` | |
740 | #[stable(feature = "unix_socket", since = "1.10.0")] | |
741 | pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { | |
742 | self.0.set_nonblocking(nonblocking) | |
743 | } | |
744 | ||
745 | /// Moves the socket to pass unix credentials as control message in [`SocketAncillary`]. | |
746 | /// | |
747 | /// Set the socket option `SO_PASSCRED`. | |
748 | /// | |
749 | /// # Examples | |
750 | /// | |
751 | #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")] | |
752 | #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")] | |
753 | /// #![feature(unix_socket_ancillary_data)] | |
754 | /// use std::os::unix::net::UnixDatagram; | |
755 | /// | |
756 | /// fn main() -> std::io::Result<()> { | |
757 | /// let sock = UnixDatagram::unbound()?; | |
758 | /// sock.set_passcred(true).expect("set_passcred function failed"); | |
759 | /// Ok(()) | |
760 | /// } | |
761 | /// ``` | |
762 | #[cfg(any(doc, target_os = "android", target_os = "linux",))] | |
763 | #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] | |
764 | pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { | |
765 | self.0.set_passcred(passcred) | |
766 | } | |
767 | ||
768 | /// Get the current value of the socket for passing unix credentials in [`SocketAncillary`]. | |
769 | /// This value can be change by [`set_passcred`]. | |
770 | /// | |
771 | /// Get the socket option `SO_PASSCRED`. | |
772 | /// | |
773 | /// [`set_passcred`]: UnixDatagram::set_passcred | |
774 | #[cfg(any(doc, target_os = "android", target_os = "linux",))] | |
775 | #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] | |
776 | pub fn passcred(&self) -> io::Result<bool> { | |
777 | self.0.passcred() | |
778 | } | |
779 | ||
780 | /// Returns the value of the `SO_ERROR` option. | |
781 | /// | |
782 | /// # Examples | |
783 | /// | |
784 | /// ```no_run | |
785 | /// use std::os::unix::net::UnixDatagram; | |
786 | /// | |
787 | /// fn main() -> std::io::Result<()> { | |
788 | /// let sock = UnixDatagram::unbound()?; | |
789 | /// if let Ok(Some(err)) = sock.take_error() { | |
790 | /// println!("Got error: {:?}", err); | |
791 | /// } | |
792 | /// Ok(()) | |
793 | /// } | |
794 | /// ``` | |
795 | #[stable(feature = "unix_socket", since = "1.10.0")] | |
796 | pub fn take_error(&self) -> io::Result<Option<io::Error>> { | |
797 | self.0.take_error() | |
798 | } | |
799 | ||
800 | /// Shut down the read, write, or both halves of this connection. | |
801 | /// | |
802 | /// This function will cause all pending and future I/O calls on the | |
803 | /// specified portions to immediately return with an appropriate value | |
804 | /// (see the documentation of [`Shutdown`]). | |
805 | /// | |
806 | /// ```no_run | |
807 | /// use std::os::unix::net::UnixDatagram; | |
808 | /// use std::net::Shutdown; | |
809 | /// | |
810 | /// fn main() -> std::io::Result<()> { | |
811 | /// let sock = UnixDatagram::unbound()?; | |
812 | /// sock.shutdown(Shutdown::Both).expect("shutdown function failed"); | |
813 | /// Ok(()) | |
814 | /// } | |
815 | /// ``` | |
816 | #[stable(feature = "unix_socket", since = "1.10.0")] | |
817 | pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { | |
818 | self.0.shutdown(how) | |
819 | } | |
820 | ||
821 | /// Receives data on the socket from the remote address to which it is | |
822 | /// connected, without removing that data from the queue. On success, | |
823 | /// returns the number of bytes peeked. | |
824 | /// | |
825 | /// Successive calls return the same data. This is accomplished by passing | |
826 | /// `MSG_PEEK` as a flag to the underlying `recv` system call. | |
827 | /// | |
828 | /// # Examples | |
829 | /// | |
830 | /// ```no_run | |
831 | /// #![feature(unix_socket_peek)] | |
832 | /// | |
833 | /// use std::os::unix::net::UnixDatagram; | |
834 | /// | |
835 | /// fn main() -> std::io::Result<()> { | |
836 | /// let socket = UnixDatagram::bind("/tmp/sock")?; | |
837 | /// let mut buf = [0; 10]; | |
838 | /// let len = socket.peek(&mut buf).expect("peek failed"); | |
839 | /// Ok(()) | |
840 | /// } | |
841 | /// ``` | |
842 | #[unstable(feature = "unix_socket_peek", issue = "76923")] | |
843 | pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { | |
844 | self.0.peek(buf) | |
845 | } | |
846 | ||
847 | /// Receives a single datagram message on the socket, without removing it from the | |
848 | /// queue. On success, returns the number of bytes read and the origin. | |
849 | /// | |
850 | /// The function must be called with valid byte array `buf` of sufficient size to | |
851 | /// hold the message bytes. If a message is too long to fit in the supplied buffer, | |
852 | /// excess bytes may be discarded. | |
853 | /// | |
854 | /// Successive calls return the same data. This is accomplished by passing | |
855 | /// `MSG_PEEK` as a flag to the underlying `recvfrom` system call. | |
856 | /// | |
857 | /// Do not use this function to implement busy waiting, instead use `libc::poll` to | |
858 | /// synchronize IO events on one or more sockets. | |
859 | /// | |
860 | /// # Examples | |
861 | /// | |
862 | /// ```no_run | |
863 | /// #![feature(unix_socket_peek)] | |
864 | /// | |
865 | /// use std::os::unix::net::UnixDatagram; | |
866 | /// | |
867 | /// fn main() -> std::io::Result<()> { | |
868 | /// let socket = UnixDatagram::bind("/tmp/sock")?; | |
869 | /// let mut buf = [0; 10]; | |
870 | /// let (len, addr) = socket.peek_from(&mut buf).expect("peek failed"); | |
871 | /// Ok(()) | |
872 | /// } | |
873 | /// ``` | |
874 | #[unstable(feature = "unix_socket_peek", issue = "76923")] | |
875 | pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { | |
876 | self.recv_from_flags(buf, libc::MSG_PEEK) | |
877 | } | |
878 | } | |
879 | ||
880 | #[stable(feature = "unix_socket", since = "1.10.0")] | |
881 | impl AsRawFd for UnixDatagram { | |
882 | fn as_raw_fd(&self) -> RawFd { | |
883 | *self.0.as_inner() | |
884 | } | |
885 | } | |
886 | ||
887 | #[stable(feature = "unix_socket", since = "1.10.0")] | |
888 | impl FromRawFd for UnixDatagram { | |
889 | unsafe fn from_raw_fd(fd: RawFd) -> UnixDatagram { | |
890 | UnixDatagram(Socket::from_inner(fd)) | |
891 | } | |
892 | } | |
893 | ||
894 | #[stable(feature = "unix_socket", since = "1.10.0")] | |
895 | impl IntoRawFd for UnixDatagram { | |
896 | fn into_raw_fd(self) -> RawFd { | |
897 | self.0.into_inner() | |
898 | } | |
899 | } |