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