1#![allow(clippy::bad_bit_mask)] use crate::{
10 AsHandleRef, HandleBased, HandleRef, NullableHandle, ObjectQuery, Peered, Property,
11 PropertyQuery, Status, Topic, ok, sys,
12};
13use bitflags::bitflags;
14use std::mem::MaybeUninit;
15
16#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
21#[repr(transparent)]
22pub struct Socket(NullableHandle);
23impl_handle_based!(Socket);
24impl Peered for Socket {}
25
26bitflags! {
27 #[repr(transparent)]
28 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
29 pub struct SocketOpts: u32 {
30 const STREAM = 0 << 0;
31 const DATAGRAM = 1 << 0;
32 }
33}
34
35bitflags! {
36 #[repr(transparent)]
37 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
38 pub struct SocketReadOpts: u32 {
39 const PEEK = 1 << 3;
40 }
41}
42
43bitflags! {
44 #[repr(transparent)]
45 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
46 pub struct SocketWriteOpts: u32 {
47 }
48}
49
50#[derive(Debug, PartialEq, Eq, Clone, Copy)]
53pub enum SocketWriteDisposition {
54 Enabled,
56 Disabled,
58}
59
60impl SocketWriteDisposition {
61 pub fn from_raw(raw: u32) -> Result<Option<SocketWriteDisposition>, Status> {
64 match raw {
65 0 => Ok(None),
66 sys::ZX_SOCKET_DISPOSITION_WRITE_ENABLED => Ok(Some(SocketWriteDisposition::Enabled)),
67 sys::ZX_SOCKET_DISPOSITION_WRITE_DISABLED => Ok(Some(SocketWriteDisposition::Disabled)),
68 _ => Err(Status::INVALID_ARGS),
69 }
70 }
71}
72
73impl From<SocketWriteDisposition> for u32 {
74 fn from(disposition: SocketWriteDisposition) -> Self {
75 match disposition {
76 SocketWriteDisposition::Enabled => sys::ZX_SOCKET_DISPOSITION_WRITE_ENABLED,
77 SocketWriteDisposition::Disabled => sys::ZX_SOCKET_DISPOSITION_WRITE_DISABLED,
78 }
79 }
80}
81
82#[repr(C)]
83#[derive(Debug, Copy, Clone, Eq, PartialEq)]
84pub struct SocketInfo {
85 pub options: SocketOpts,
86 pub rx_buf_max: usize,
87 pub rx_buf_size: usize,
88 pub rx_buf_available: usize,
89 pub tx_buf_max: usize,
90 pub tx_buf_size: usize,
91}
92
93impl Default for SocketInfo {
94 fn default() -> SocketInfo {
95 SocketInfo {
96 options: SocketOpts::STREAM,
97 rx_buf_max: 0,
98 rx_buf_size: 0,
99 rx_buf_available: 0,
100 tx_buf_max: 0,
101 tx_buf_size: 0,
102 }
103 }
104}
105
106impl From<sys::zx_info_socket_t> for SocketInfo {
107 fn from(socket: sys::zx_info_socket_t) -> SocketInfo {
108 SocketInfo {
109 options: SocketOpts::from_bits_truncate(socket.options),
110 rx_buf_max: socket.rx_buf_max,
111 rx_buf_size: socket.rx_buf_size,
112 rx_buf_available: socket.rx_buf_available,
113 tx_buf_max: socket.tx_buf_max,
114 tx_buf_size: socket.tx_buf_size,
115 }
116 }
117}
118
119struct SocketInfoQuery;
121unsafe impl ObjectQuery for SocketInfoQuery {
122 const TOPIC: Topic = Topic::SOCKET;
123 type InfoTy = sys::zx_info_socket_t;
124}
125
126impl Socket {
127 pub fn create_stream() -> (Socket, Socket) {
138 Self::try_create(SocketOpts::STREAM).expect("socket creation can't fail with valid options")
139 }
140
141 pub fn create_datagram() -> (Socket, Socket) {
152 Self::try_create(SocketOpts::DATAGRAM)
153 .expect("socket creation can't fail with valid options")
154 }
155
156 fn try_create(sock_opts: SocketOpts) -> Result<(Socket, Socket), Status> {
157 unsafe {
158 let mut out0 = 0;
159 let mut out1 = 0;
160 let status = sys::zx_socket_create(sock_opts.bits(), &mut out0, &mut out1);
161 ok(status)?;
162 Ok((
163 Self::from(NullableHandle::from_raw(out0)),
164 Self::from(NullableHandle::from_raw(out1)),
165 ))
166 }
167 }
168
169 pub fn write(&self, bytes: &[u8]) -> Result<usize, Status> {
176 self.write_opts(bytes, SocketWriteOpts::default())
177 }
178
179 pub unsafe fn write_raw(&self, bytes: *const u8, len: usize) -> Result<usize, Status> {
190 unsafe { self.write_raw_opts(bytes, len, SocketWriteOpts::default()) }
192 }
193
194 pub fn write_opts(&self, bytes: &[u8], opts: SocketWriteOpts) -> Result<usize, Status> {
201 unsafe { self.write_raw_opts(bytes.as_ptr(), bytes.len(), opts) }
203 }
204
205 pub unsafe fn write_raw_opts(
216 &self,
217 bytes: *const u8,
218 len: usize,
219 opts: SocketWriteOpts,
220 ) -> Result<usize, Status> {
221 let mut actual = 0;
222 let status = unsafe {
224 sys::zx_socket_write(self.raw_handle(), opts.bits(), bytes, len, &mut actual)
225 };
226 ok(status).map(|()| actual)
227 }
228
229 pub fn read(&self, bytes: &mut [u8]) -> Result<usize, Status> {
235 self.read_opts(bytes, SocketReadOpts::default())
236 }
237
238 pub fn read_opts(&self, bytes: &mut [u8], opts: SocketReadOpts) -> Result<usize, Status> {
244 unsafe { self.read_raw_opts(bytes.as_mut_ptr(), bytes.len(), opts) }
246 }
247
248 pub unsafe fn read_raw(&self, bytes: *mut u8, len: usize) -> Result<usize, Status> {
259 unsafe { self.read_raw_opts(bytes, len, SocketReadOpts::default()) }
261 }
262
263 pub unsafe fn read_raw_opts(
274 &self,
275 bytes: *mut u8,
276 len: usize,
277 opts: SocketReadOpts,
278 ) -> Result<usize, Status> {
279 let mut actual = 0;
280 let status =
282 unsafe { sys::zx_socket_read(self.raw_handle(), opts.bits(), bytes, len, &mut actual) };
283 ok(status).map(|()| actual)
284 }
285
286 pub fn read_uninit<'a>(
288 &self,
289 bytes: &'a mut [MaybeUninit<u8>],
290 ) -> Result<&'a mut [u8], Status> {
291 self.read_uninit_opts(bytes, SocketReadOpts::default())
292 }
293
294 pub fn read_uninit_opts<'a>(
297 &self,
298 bytes: &'a mut [MaybeUninit<u8>],
299 opts: SocketReadOpts,
300 ) -> Result<&'a mut [u8], Status> {
301 let actual =
304 unsafe { self.read_raw_opts(bytes.as_mut_ptr().cast::<u8>(), bytes.len(), opts)? };
305 let (valid, _uninit) = bytes.split_at_mut(actual);
306
307 Ok(unsafe { std::slice::from_raw_parts_mut(valid.as_mut_ptr().cast::<u8>(), valid.len()) })
310 }
311
312 pub fn half_close(&self) -> Result<(), Status> {
317 self.set_disposition(None, Some(SocketWriteDisposition::Disabled))
318 }
319
320 pub fn set_disposition(
325 &self,
326 disposition: Option<SocketWriteDisposition>,
327 disposition_peer: Option<SocketWriteDisposition>,
328 ) -> Result<(), Status> {
329 let status = unsafe {
330 sys::zx_socket_set_disposition(
331 self.raw_handle(),
332 disposition.map(u32::from).unwrap_or(0),
333 disposition_peer.map(u32::from).unwrap_or(0),
334 )
335 };
336 ok(status)
337 }
338
339 pub fn outstanding_read_bytes(&self) -> Result<usize, Status> {
341 Ok(self.info()?.rx_buf_available)
342 }
343
344 pub fn info(&self) -> Result<SocketInfo, Status> {
348 Ok(SocketInfo::from(self.0.get_info_single::<SocketInfoQuery>()?))
349 }
350}
351
352unsafe_handle_properties!(object: Socket,
353 props: [
354 {query_ty: SOCKET_RX_THRESHOLD, tag: SocketRxThresholdTag, prop_ty: usize, get:get_rx_threshold, set: set_rx_threshold},
355 {query_ty: SOCKET_TX_THRESHOLD, tag: SocketTxThresholdTag, prop_ty: usize, get:get_tx_threshold, set: set_tx_threshold},
356 ]
357);
358
359#[cfg(test)]
362mod tests {
363 use std::mem::MaybeUninit;
364
365 use super::*;
366
367 fn socket_basic_helper(opts: SocketOpts) {
368 let (s1, s2) = match opts {
369 SocketOpts::STREAM => Socket::create_stream(),
370 SocketOpts::DATAGRAM => Socket::create_datagram(),
371 _ => panic!("unsupported socket options"),
372 };
373
374 assert_eq!(s1.write(b"hello").unwrap(), 5);
376 assert_eq!(s1.write(b"world").unwrap(), 5);
377
378 let mut read_vec = vec![0; 11];
379 if opts == SocketOpts::DATAGRAM {
380 assert_eq!(s2.read(&mut read_vec).unwrap(), 5);
381 assert_eq!(&read_vec[0..5], b"hello");
382
383 assert_eq!(s2.read(&mut read_vec).unwrap(), 5);
384 assert_eq!(&read_vec[0..5], b"world");
385 } else {
386 assert_eq!(s2.read(&mut read_vec).unwrap(), 10);
387 assert_eq!(&read_vec[0..10], b"helloworld");
388 }
389
390 assert_eq!(s2.read(&mut read_vec), Err(Status::SHOULD_WAIT));
392
393 assert!(s1.half_close().is_ok());
395 assert_eq!(s2.write(b"fail"), Err(Status::BAD_STATE));
396 assert_eq!(s1.read(&mut read_vec), Err(Status::BAD_STATE));
397
398 assert_eq!(s2.read(&mut read_vec), Err(Status::SHOULD_WAIT));
400 assert_eq!(s1.write(b"back").unwrap(), 4);
401 assert_eq!(s2.read(&mut read_vec).unwrap(), 4);
402 assert_eq!(&read_vec[0..4], b"back");
403 }
404
405 #[test]
406 fn socket_basic() {
407 socket_basic_helper(SocketOpts::STREAM);
408 socket_basic_helper(SocketOpts::DATAGRAM);
409 }
410
411 #[test]
412 fn socket_info() {
413 let (s1, s2) = Socket::create_stream();
414 let s1info = s1.info().unwrap();
415 assert_eq!(s1info.rx_buf_available, 0);
417 assert_eq!(s1info.rx_buf_size, 0);
418 assert_eq!(s1info.tx_buf_size, 0);
419
420 assert_eq!(s1.write(b"hello").unwrap(), 5);
422
423 let s1info = s1.info().unwrap();
425 let s2info = s2.info().unwrap();
426 assert_eq!(s1info.tx_buf_size, 5);
427 assert_eq!(s1info.rx_buf_size, 0);
428 assert_eq!(s2info.rx_buf_size, 5);
429 assert_eq!(s2info.rx_buf_available, 5);
430 assert_eq!(s2info.tx_buf_size, 0);
431 }
432
433 #[test]
434 fn socket_disposition() {
435 const PAYLOAD: &'static [u8] = b"Hello";
436 let (s1, s2) = Socket::create_stream();
437 assert_eq!(
439 s1.set_disposition(
440 Some(SocketWriteDisposition::Disabled),
441 Some(SocketWriteDisposition::Enabled)
442 ),
443 Ok(())
444 );
445 assert_eq!(s2.write(PAYLOAD), Ok(PAYLOAD.len()));
446 assert_eq!(s1.write(PAYLOAD), Err(Status::BAD_STATE));
447 let mut buf = [0u8; PAYLOAD.len() + 1];
448 assert_eq!(s1.read(&mut buf[..]), Ok(PAYLOAD.len()));
449 assert_eq!(&buf[..PAYLOAD.len()], PAYLOAD);
450 assert_eq!(s1.set_disposition(None, None), Ok(()));
452 assert_eq!(s2.write(PAYLOAD), Ok(PAYLOAD.len()));
453 assert_eq!(s1.write(PAYLOAD), Err(Status::BAD_STATE));
454 }
455
456 #[test]
457 fn read_uninit() {
458 let (s1, s2) = Socket::create_stream();
459 let message = b"hello";
460 assert_eq!(s1.write(&message[..]).unwrap(), 5);
461 let mut recv = [MaybeUninit::<u8>::uninit(); 16];
462 let got = s2.read_uninit(&mut recv[..]).unwrap();
463 assert_eq!(got, &message[..]);
464 }
465}