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.
5 //! Type-safe bindings for Zircon sockets.
7 use {AsHandleRef, HandleBased, Handle, HandleRef, Peered}
;
12 /// An object representing a Zircon
13 /// [socket](https://fuchsia.googlesource.com/zircon/+/master/docs/concepts.md#Message-Passing_Sockets-and-Channels).
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 {}
22 /// Create a socket, accessed through a pair of endpoints. Data written
23 /// into one may be read from the other.
26 /// [zx_socket_create](https://fuchsia.googlesource.com/zircon/+/master/docs/syscalls/socket_create.md).
27 pub fn create() -> Result
<(Socket
, Socket
), Status
> {
32 let status
= sys
::zx_socket_create(opts
, &mut out0
, &mut out1
);
35 Self::from(Handle
::from_raw(out0
)),
36 Self::from(Handle
::from_raw(out1
))
41 /// Write the given bytes into the socket.
42 /// Return value (on success) is number of bytes actually written.
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
> {
50 sys
::zx_socket_write(self.raw_handle(), opts
, bytes
.as_ptr(), bytes
.len(),
53 ok(status
).map(|()| actual
)
56 /// Read the given bytes from the socket.
57 /// Return value (on success) is number of bytes actually read.
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
> {
65 sys
::zx_socket_read(self.raw_handle(), opts
, bytes
.as_mut_ptr(),
66 bytes
.len(), &mut actual
)
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.
78 /// Close half of the socket, so attempts by the other side to write will fail.
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()) };
88 pub fn outstanding_read_bytes(&self) -> Result
<usize, Status
> {
89 let mut outstanding
= 0;
91 sys
::zx_socket_read(self.raw_handle(), 0, ptr
::null_mut(), 0, &mut outstanding
)
93 ok(status
).map(|()| outstanding
)
103 let (s1
, s2
) = Socket
::create().unwrap();
105 // Write in one end and read it back out the other.
106 assert_eq
!(s1
.write(b
"hello").unwrap(), 5);
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");
112 // Try reading when there is nothing to read.
113 assert_eq
!(s2
.read(&mut read_vec
), Err(Status
::SHOULD_WAIT
));
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
));
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");