]> git.proxmox.com Git - rustc.git/blob - vendor/fuchsia-zircon/src/socket.rs
New upstream version 1.46.0+dfsg1
[rustc.git] / vendor / fuchsia-zircon / src / socket.rs
1 // Copyright 2016 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 //! Type-safe bindings for Zircon sockets.
6
7 use {AsHandleRef, HandleBased, Handle, HandleRef, Peered};
8 use {sys, Status, ok};
9
10 use std::ptr;
11
12 /// An object representing a Zircon
13 /// [socket](https://fuchsia.googlesource.com/zircon/+/master/docs/concepts.md#Message-Passing_Sockets-and-Channels).
14 ///
15 /// As essentially a subtype of `Handle`, it can be freely interconverted.
16 #[derive(Debug, Eq, PartialEq)]
17 pub struct Socket(Handle);
18 impl_handle_based!(Socket);
19 impl Peered for Socket {}
20
21 impl Socket {
22 /// Create a socket, accessed through a pair of endpoints. Data written
23 /// into one may be read from the other.
24 ///
25 /// Wraps
26 /// [zx_socket_create](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/socket_create.md).
27 pub fn create() -> Result<(Socket, Socket), Status> {
28 unsafe {
29 let mut out0 = 0;
30 let mut out1 = 0;
31 let opts = 0;
32 let status = sys::zx_socket_create(opts, &mut out0, &mut out1);
33 ok(status)?;
34 Ok((
35 Self::from(Handle::from_raw(out0)),
36 Self::from(Handle::from_raw(out1))
37 ))
38 }
39 }
40
41 /// Write the given bytes into the socket.
42 /// Return value (on success) is number of bytes actually written.
43 ///
44 /// Wraps
45 /// [zx_socket_write](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/socket_write.md).
46 pub fn write(&self, bytes: &[u8]) -> Result<usize, Status> {
47 let mut actual = 0;
48 let opts = 0;
49 let status = unsafe {
50 sys::zx_socket_write(self.raw_handle(), opts, bytes.as_ptr(), bytes.len(),
51 &mut actual)
52 };
53 ok(status).map(|()| actual)
54 }
55
56 /// Read the given bytes from the socket.
57 /// Return value (on success) is number of bytes actually read.
58 ///
59 /// Wraps
60 /// [zx_socket_read](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/socket_read.md).
61 pub fn read(&self, bytes: &mut [u8]) -> Result<usize, Status> {
62 let mut actual = 0;
63 let opts = 0;
64 let status = unsafe {
65 sys::zx_socket_read(self.raw_handle(), opts, bytes.as_mut_ptr(),
66 bytes.len(), &mut actual)
67 };
68 ok(status)
69 .map(|()| actual)
70 .map_err(|status| {
71 // If an error is returned then actual is undefined, so to be safe
72 // we set it to 0 and ignore any data that is set in bytes.
73 actual = 0;
74 status
75 })
76 }
77
78 /// Close half of the socket, so attempts by the other side to write will fail.
79 ///
80 /// Implements the `ZX_SOCKET_HALF_CLOSE` option of
81 /// [zx_socket_write](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/socket_write.md).
82 pub fn half_close(&self) -> Result<(), Status> {
83 let status = unsafe { sys::zx_socket_write(self.raw_handle(), sys::ZX_SOCKET_HALF_CLOSE,
84 ptr::null(), 0, ptr::null_mut()) };
85 ok(status)
86 }
87
88 pub fn outstanding_read_bytes(&self) -> Result<usize, Status> {
89 let mut outstanding = 0;
90 let status = unsafe {
91 sys::zx_socket_read(self.raw_handle(), 0, ptr::null_mut(), 0, &mut outstanding)
92 };
93 ok(status).map(|()| outstanding)
94 }
95 }
96
97 #[cfg(test)]
98 mod tests {
99 use super::*;
100
101 #[test]
102 fn socket_basic() {
103 let (s1, s2) = Socket::create().unwrap();
104
105 // Write in one end and read it back out the other.
106 assert_eq!(s1.write(b"hello").unwrap(), 5);
107
108 let mut read_vec = vec![0; 8];
109 assert_eq!(s2.read(&mut read_vec).unwrap(), 5);
110 assert_eq!(&read_vec[0..5], b"hello");
111
112 // Try reading when there is nothing to read.
113 assert_eq!(s2.read(&mut read_vec), Err(Status::SHOULD_WAIT));
114
115 // Close the socket from one end.
116 assert!(s1.half_close().is_ok());
117 assert_eq!(s2.read(&mut read_vec), Err(Status::BAD_STATE));
118 assert_eq!(s1.write(b"fail"), Err(Status::BAD_STATE));
119
120 // Writing in the other direction should still work.
121 assert_eq!(s1.read(&mut read_vec), Err(Status::SHOULD_WAIT));
122 assert_eq!(s2.write(b"back").unwrap(), 4);
123 assert_eq!(s1.read(&mut read_vec).unwrap(), 4);
124 assert_eq!(&read_vec[0..4], b"back");
125 }
126 }