1use crate::task::{
6 CurrentTask, EventHandler, SignalHandler, SignalHandlerInner, WaitCanceler, Waiter,
7};
8use crate::vfs::buffers::{AncillaryData, InputBuffer, MessageReadInfo, OutputBuffer};
9use crate::vfs::socket::{
10 SockOptValue, Socket, SocketAddress, SocketHandle, SocketMessageFlags, SocketOps, SocketPeer,
11 SocketShutdownFlags, SocketType,
12};
13use anyhow::Context;
14use fidl::endpoints::{SynchronousProxy, create_sync_proxy};
15use fidl_fuchsia_hardware_qualcomm_router as fqrtr;
16use starnix_logging::{log_warn, track_stub};
17use starnix_sync::{LockDepGuard, LockDepMutex, MappedLockDepGuard, QipcrtrSocketInnerLock};
18use starnix_uapi::errors::{Errno, from_status_like_fdio};
19use starnix_uapi::vfs::FdEvents;
20use starnix_uapi::{
21 AF_QIPCRTR, SO_RCVBUF, SO_SNDBUF, SOL_SOCKET, errno, error, sockaddr_qrtr, socklen_t, ucred,
22};
23use zerocopy::{FromBytes, IntoBytes};
24
25const QRTR_CLIENT_SERVICE_DIRECTORY: &str = "/svc/fuchsia.hardware.qualcomm.router.ClientService";
26fn connect_to_connector() -> Result<fqrtr::QrtrConnectorSynchronousProxy, anyhow::Error> {
27 let mut dir = std::fs::read_dir(QRTR_CLIENT_SERVICE_DIRECTORY)
28 .context("Failed to read ClientService directory")?;
29 let entry = dir
30 .next()
31 .ok_or_else(|| anyhow::format_err!("Missing ClientService instance"))?
32 .context("Unable to read ClientService instance")?;
33 let path = entry
34 .path()
35 .join("qrtr_connector")
36 .into_os_string()
37 .into_string()
38 .map_err(|_| anyhow::format_err!("Failed to get qrtr_connector path"))?;
39
40 let (client_end, server_end) = zx::Channel::create();
41 fdio::service_connect(&path, server_end)?;
42 Ok(fqrtr::QrtrConnectorSynchronousProxy::from_channel(client_end))
43}
44
45pub const SEND_BUF_MIN_SIZE: usize = 2048;
47pub const SEND_BUF_MAX_SIZE: usize = 1 << 31;
48pub const SEND_BUF_DEFAULT_SIZE: usize = 2048;
49
50pub const RECV_BUF_MIN_SIZE: usize = 256;
52pub const RECV_BUF_MAX_SIZE: usize = 1 << 31;
53pub const RECV_BUF_DEFAULT_SIZE: usize = 256;
54
55pub struct QipcrtrSocket {
56 inner: LockDepMutex<Option<QipcrtrSocketInner>, QipcrtrSocketInnerLock>,
57}
58
59struct QipcrtrSocketInner {
60 proxy: fqrtr::QrtrClientConnectionSynchronousProxy,
62
63 events: zx::EventPair,
65
66 peer: Option<sockaddr_qrtr>,
69
70 send_buf_size: usize,
76
77 recv_buf_size: usize,
83}
84
85impl QipcrtrSocket {
86 pub fn new(_socket_type: SocketType) -> Self {
87 Self { inner: Default::default() }
88 }
89
90 fn connecting_lock(&self) -> Result<MappedLockDepGuard<'_, QipcrtrSocketInner>, Errno> {
93 let mut inner = self.inner.lock();
94 if inner.is_none() {
95 *inner = Some(QipcrtrSocketInner::new(fqrtr::ConnectionOptions {
96 blocking: Some(false),
97 ..Default::default()
98 })?);
99 }
100 Ok(LockDepGuard::map(inner, |inner| inner.as_mut().unwrap()))
101 }
102
103 fn close(&self) {
104 *self.inner.lock() = None;
105 }
106}
107
108impl QipcrtrSocketInner {
109 fn new(options: fqrtr::ConnectionOptions) -> Result<Self, Errno> {
110 let connector = connect_to_connector().map_err(|e| errno!(ENETUNREACH, e))?;
111
112 let (client_end, server_end) = create_sync_proxy::<fqrtr::QrtrClientConnectionMarker>();
113 connector
114 .get_connection(&options, server_end, zx::MonotonicInstant::INFINITE)
115 .map_err(|e| errno!(ENETUNREACH, e))?
116 .map_err(qrtr_error_to_errno)?;
117
118 let proxy = fqrtr::QrtrClientConnectionSynchronousProxy::new(client_end.into_channel());
119 let events = proxy
120 .get_signals(zx::MonotonicInstant::INFINITE)
121 .map_err(|e| errno!(ENETUNREACH, e))?;
122
123 Ok(Self {
124 proxy,
125 events,
126 peer: None,
127 send_buf_size: SEND_BUF_DEFAULT_SIZE,
128 recv_buf_size: RECV_BUF_DEFAULT_SIZE,
129 })
130 }
131
132 fn bound_addr(&self) -> Result<sockaddr_qrtr, Errno> {
134 let addr = sockaddr_qrtr {
135 sq_family: AF_QIPCRTR,
136 sq_node: self
137 .proxy
138 .get_node_id(zx::MonotonicInstant::INFINITE)
139 .map_err(|e| errno!(EINVAL, e))?,
140 sq_port: self
141 .proxy
142 .get_port_id(zx::MonotonicInstant::INFINITE)
143 .map_err(|e| errno!(EINVAL, e))?,
144 ..Default::default()
145 };
146 Ok(addr)
147 }
148}
149
150impl Drop for QipcrtrSocketInner {
151 fn drop(&mut self) {
152 if let Err(e) = self.proxy.close_connection(zx::MonotonicInstant::INFINITE) {
153 log_warn!("Failed to close QRTR connection: {e:?}");
154 }
155 }
156}
157
158impl SocketOps for QipcrtrSocket {
159 fn connect(
160 &self,
161 _socket: &SocketHandle,
162 _current_task: &CurrentTask,
163 peer: SocketPeer,
164 ) -> Result<(), Errno> {
165 let peer = match peer {
166 SocketPeer::Address(addr) => extract_qrtr_sockaddr(&addr)?,
167 _ => {
168 return error!(EINVAL);
169 }
170 };
171
172 let mut inner = self.inner.lock();
173 if inner.is_some() {
174 return error!(EISCONN);
175 }
176
177 let mut new_inner = QipcrtrSocketInner::new(fqrtr::ConnectionOptions {
180 blocking: Some(false),
181 ..Default::default()
182 })?;
183 new_inner.peer = Some(peer);
184
185 *inner = Some(new_inner);
186 Ok(())
187 }
188
189 fn listen(&self, _socket: &Socket, _backlog: i32, _credentials: ucred) -> Result<(), Errno> {
190 error!(ENOTSUP)
191 }
192
193 fn accept(&self, _socket: &Socket, _current_task: &CurrentTask) -> Result<SocketHandle, Errno> {
194 error!(ENOTSUP)
195 }
196
197 fn bind(
198 &self,
199 _socket: &Socket,
200 _current_task: &CurrentTask,
201 socket_address: SocketAddress,
202 ) -> Result<(), Errno> {
203 let addr = extract_qrtr_sockaddr(&socket_address)?;
204
205 let mut inner = self.inner.lock();
206 if inner.is_some() {
207 return error!(EINVAL);
208 }
209
210 *inner = Some(QipcrtrSocketInner::new(fqrtr::ConnectionOptions {
212 blocking: Some(false),
213 port: Some(addr.sq_port),
214 ..Default::default()
215 })?);
216
217 Ok(())
218 }
219
220 fn read(
221 &self,
222 _socket: &Socket,
223 _current_task: &CurrentTask,
224 data: &mut dyn OutputBuffer,
225 flags: SocketMessageFlags,
226 ) -> Result<MessageReadInfo, Errno> {
227 if flags.contains(SocketMessageFlags::PEEK) {
228 track_stub!(
229 TODO("https://fxbug.dev/388082019"),
230 "SocketMessageFlags::PEEK is unsupported"
231 );
232 return error!(EINVAL);
233 }
234
235 let inner = self.connecting_lock()?;
236
237 if flags.contains(SocketMessageFlags::DONTWAIT) {
238 match inner.events.wait_one(
239 zx::Signals::from_bits_truncate(fqrtr::SIGNAL_READABLE)
240 | zx::Signals::EVENTPAIR_PEER_CLOSED,
241 zx::MonotonicInstant::INFINITE_PAST,
242 ) {
243 zx::WaitResult::Ok(_) => {}
244 zx::WaitResult::TimedOut(_) | zx::WaitResult::Canceled(_) => return error!(EAGAIN),
245 zx::WaitResult::Err(status) => return Err(from_status_like_fdio!(status)),
246 }
247 }
248
249 let (src_node, src_port, src_data) = inner
250 .proxy
251 .read(zx::MonotonicInstant::INFINITE)
252 .map_err(|e| errno!(ECONNRESET, e))?
253 .map_err(qrtr_error_to_errno)?;
254
255 let bytes_read = data.write(src_data.as_bytes())?;
256 Ok(MessageReadInfo {
257 bytes_read,
258 message_length: src_data.len(),
259 address: Some(pack_qrtr_sockaddr(src_node, src_port)),
260 ..Default::default()
261 })
262 }
263
264 fn write(
265 &self,
266 _socket: &Socket,
267 _current_task: &CurrentTask,
268 data: &mut dyn InputBuffer,
269 dest_address: &mut Option<SocketAddress>,
270 _ancillary_data: &mut Vec<AncillaryData>,
271 ) -> Result<usize, Errno> {
272 let inner = self.connecting_lock()?;
273
274 let dest = match dest_address {
277 Some(addr) => extract_qrtr_sockaddr(addr)?,
278 None => inner.peer.ok_or_else(|| errno!(EDESTADDRREQ))?,
279 };
280
281 match inner.events.wait_one(
282 zx::Signals::from_bits_truncate(fqrtr::SIGNAL_WRITABLE)
283 | zx::Signals::EVENTPAIR_PEER_CLOSED,
284 zx::MonotonicInstant::INFINITE_PAST,
285 ) {
286 zx::WaitResult::Ok(_) => {}
287 zx::WaitResult::TimedOut(_) | zx::WaitResult::Canceled(_) => return error!(EAGAIN),
288 zx::WaitResult::Err(status) => return Err(from_status_like_fdio!(status)),
289 }
290
291 let data_written = data.read_all()?;
292 let _ = inner
293 .proxy
294 .write(
295 dest.sq_node,
296 dest.sq_port,
297 data_written.as_ref(),
298 zx::MonotonicInstant::INFINITE,
299 )
300 .map_err(|e| errno!(ECONNRESET, e))?
301 .map_err(qrtr_error_to_errno)?;
302 Ok(data_written.len())
303 }
304
305 fn wait_async(
306 &self,
307 _socket: &Socket,
308 _current_task: &CurrentTask,
309 waiter: &Waiter,
310 events: FdEvents,
311 handler: EventHandler,
312 ) -> WaitCanceler {
313 let Ok(inner) = self.connecting_lock() else {
314 return WaitCanceler::new_noop();
315 };
316 let signal_handler = SignalHandler {
317 inner: SignalHandlerInner::ZxHandle(qrtr_signals_to_fd_events),
318 event_handler: handler,
319 err_code: None,
320 };
321 let canceler = waiter
322 .wake_on_zircon_signals(
323 &inner.events,
324 fd_events_to_qrtr_signals(events),
325 signal_handler,
326 )
327 .unwrap();
328 WaitCanceler::new_port(canceler)
329 }
330
331 fn query_events(
332 &self,
333 _socket: &Socket,
334 _current_task: &CurrentTask,
335 ) -> Result<FdEvents, Errno> {
336 let inner = self.connecting_lock()?;
337 let signals = inner
338 .events
339 .as_handle_ref()
340 .wait_one(zx::Signals::all(), zx::MonotonicInstant::INFINITE_PAST)
341 .map_err(|e| from_status_like_fdio!(e))?;
342 Ok(qrtr_signals_to_fd_events(signals))
343 }
344
345 fn shutdown(&self, _socket: &Socket, _how: SocketShutdownFlags) -> Result<(), Errno> {
346 self.close();
347 Ok(())
348 }
349
350 fn close(&self, _current_task: &CurrentTask, _socket: &Socket) {
351 self.close();
352 }
353
354 fn getsockname(&self, _socket: &Socket) -> Result<SocketAddress, Errno> {
355 let name = self.connecting_lock()?.bound_addr()?;
356 Ok(SocketAddress::Qipcrtr(name.as_bytes().to_vec()))
357 }
358
359 fn getpeername(&self, _socket: &Socket) -> Result<SocketAddress, Errno> {
360 let peer = self.connecting_lock()?.peer.ok_or_else(|| errno!(ENOTCONN))?;
361 Ok(SocketAddress::Qipcrtr(peer.as_bytes().to_vec()))
362 }
363
364 fn setsockopt(
365 &self,
366 _socket: &Socket,
367 current_task: &CurrentTask,
368 level: u32,
369 optname: u32,
370 optval: SockOptValue,
371 ) -> Result<(), Errno> {
372 let mut inner = self.connecting_lock()?;
373 match level {
374 SOL_SOCKET => match optname {
375 SO_SNDBUF => {
376 let requested_capacity: socklen_t = optval.read(current_task)?;
377 let capacity = usize::try_from(requested_capacity * 2).unwrap_or(usize::MAX);
380 let capacity = capacity.clamp(SEND_BUF_MIN_SIZE, SEND_BUF_MAX_SIZE);
382 inner.send_buf_size = capacity;
383 }
384 SO_RCVBUF => {
385 let requested_capacity: socklen_t = optval.read(current_task)?;
386 let capacity = usize::try_from(requested_capacity * 2).unwrap_or(usize::MAX);
389 let capacity = capacity.clamp(RECV_BUF_MIN_SIZE, RECV_BUF_MAX_SIZE);
391 inner.recv_buf_size = capacity;
392 }
393 _ => return error!(ENOSYS),
394 },
395 _ => return error!(ENOSYS),
396 }
397
398 Ok(())
399 }
400
401 fn getsockopt(
402 &self,
403 _socket: &Socket,
404 _current_task: &CurrentTask,
405 level: u32,
406 optname: u32,
407 _optlen: u32,
408 ) -> Result<Vec<u8>, Errno> {
409 let inner = self.connecting_lock()?;
410 Ok(match level {
411 SOL_SOCKET => match optname {
412 SO_SNDBUF => (inner.send_buf_size as socklen_t).to_ne_bytes().to_vec(),
413 SO_RCVBUF => (inner.recv_buf_size as socklen_t).to_ne_bytes().to_vec(),
414 _ => return error!(ENOSYS),
415 },
416 _ => vec![],
417 })
418 }
419}
420
421fn extract_qrtr_sockaddr(addr: &SocketAddress) -> Result<sockaddr_qrtr, Errno> {
424 match addr {
425 SocketAddress::Qipcrtr(bytes) => sockaddr_qrtr::read_from_prefix(bytes.as_bytes())
426 .map(|(addr, _)| addr)
427 .map_err(|e| errno!(EINVAL, e)),
428 _ => error!(EINVAL),
429 }
430}
431
432fn pack_qrtr_sockaddr(node: u32, port: u32) -> SocketAddress {
434 let addr =
435 sockaddr_qrtr { sq_family: AF_QIPCRTR, sq_node: node, sq_port: port, ..Default::default() };
436 SocketAddress::Qipcrtr(addr.as_bytes().into())
437}
438
439fn qrtr_error_to_errno(e: fqrtr::Error) -> Errno {
441 match e {
442 fqrtr::Error::InternalError => errno!(EINVAL),
443 fqrtr::Error::AlreadyPending => errno!(EBUSY),
444 fqrtr::Error::RemoteNodeUnavailable => errno!(ECONNRESET),
445 fqrtr::Error::AlreadyBound => errno!(EADDRINUSE),
446 fqrtr::Error::NotSupported => errno!(ENOTSUP),
447 fqrtr::Error::WouldBlock => errno!(EAGAIN),
448 fqrtr::Error::NoResources => errno!(ENOMEM),
449 fqrtr::Error::InvalidArgs => errno!(EINVAL),
450 _ => errno!(EINVAL),
451 }
452}
453
454fn fd_events_to_qrtr_signals(events: FdEvents) -> zx::Signals {
456 let mut signals = zx::Signals::empty();
457 if events.contains(FdEvents::POLLIN) {
458 signals |= zx::Signals::from_bits_truncate(fqrtr::SIGNAL_READABLE);
459 }
460 if events.contains(FdEvents::POLLOUT) {
461 signals |= zx::Signals::from_bits_truncate(fqrtr::SIGNAL_WRITABLE);
462 }
463
464 signals |= zx::Signals::EVENTPAIR_PEER_CLOSED;
466 signals
467}
468
469fn qrtr_signals_to_fd_events(signals: zx::Signals) -> FdEvents {
471 let mut events = FdEvents::empty();
472 if signals.contains(zx::Signals::from_bits_truncate(fqrtr::SIGNAL_READABLE)) {
473 events |= FdEvents::POLLIN;
474 }
475 if signals.contains(zx::Signals::from_bits_truncate(fqrtr::SIGNAL_WRITABLE)) {
476 events |= FdEvents::POLLOUT;
477 }
478 if signals.contains(zx::Signals::EVENTPAIR_PEER_CLOSED) {
479 events |= FdEvents::POLLHUP;
480 }
481 events
482}
483
484#[cfg(test)]
485mod tests {
486 use super::*;
487 use crate::testing::spawn_kernel_and_run;
488 use crate::vfs::buffers::{VecInputBuffer, VecOutputBuffer};
489 use crate::vfs::socket::{SocketDomain, SocketProtocol, SocketType};
490 use fidl::endpoints::create_sync_proxy;
491 use futures::StreamExt;
492
493 fn mock_qipcrtr_socket()
498 -> (QipcrtrSocket, fidl::endpoints::ServerEnd<fqrtr::QrtrClientConnectionMarker>) {
499 let (proxy, server_end) = create_sync_proxy::<fqrtr::QrtrClientConnectionMarker>();
500
501 let (events, _) = zx::EventPair::create();
503
504 let inner = QipcrtrSocketInner {
505 proxy,
506 events,
507 peer: None,
508 send_buf_size: SEND_BUF_DEFAULT_SIZE,
509 recv_buf_size: RECV_BUF_DEFAULT_SIZE,
510 };
511
512 (QipcrtrSocket { inner: Some(inner).into() }, server_end)
513 }
514
515 #[::fuchsia::test]
516 async fn test_qipcrtr_socket_new() {
517 spawn_kernel_and_run(async |current_task| {
518 let _kernel = current_task.kernel();
519 let _socket = Socket::new(
526 ¤t_task,
527 SocketDomain::Qipcrtr,
528 SocketType::Datagram,
529 SocketProtocol::default(),
530 false,
531 )
532 .expect("Failed to create socket.");
533 })
534 .await;
535 }
536
537 #[::fuchsia::test]
538 async fn test_qipcrtr_sockopt() {
539 spawn_kernel_and_run(async |current_task| {
540 let socket = mock_qipcrtr_socket();
541 let socket_obj = Socket::new_with_ops_and_info(
542 Box::new(socket.0),
543 SocketDomain::Qipcrtr,
544 SocketType::Datagram,
545 SocketProtocol::default(),
546 );
547 let _server_end = socket.1;
548
549 let sndbuf = socket_obj.getsockopt(¤t_task, SOL_SOCKET, SO_SNDBUF, 4).unwrap();
551 let sndbuf_val = u32::from_ne_bytes(sndbuf.as_slice().try_into().unwrap());
552 assert_eq!(sndbuf_val, SEND_BUF_DEFAULT_SIZE as u32);
553
554 let new_sndbuf: u32 = 4096;
555 socket_obj
556 .setsockopt(
557 ¤t_task,
558 SOL_SOCKET,
559 SO_SNDBUF,
560 SockOptValue::from(new_sndbuf.as_bytes().to_vec()),
561 )
562 .unwrap();
563
564 let sndbuf = socket_obj.getsockopt(¤t_task, SOL_SOCKET, SO_SNDBUF, 4).unwrap();
565 let sndbuf_val = u32::from_ne_bytes(sndbuf.as_slice().try_into().unwrap());
566 assert_eq!(sndbuf_val, new_sndbuf * 2);
568
569 let rcvbuf = socket_obj.getsockopt(¤t_task, SOL_SOCKET, SO_RCVBUF, 4).unwrap();
571 let rcvbuf_val = u32::from_ne_bytes(rcvbuf.as_slice().try_into().unwrap());
572 assert_eq!(rcvbuf_val, RECV_BUF_DEFAULT_SIZE as u32);
573
574 let new_rcvbuf: u32 = 1024;
575 socket_obj
576 .setsockopt(
577 ¤t_task,
578 SOL_SOCKET,
579 SO_RCVBUF,
580 SockOptValue::from(new_rcvbuf.as_bytes().to_vec()),
581 )
582 .unwrap();
583
584 let rcvbuf = socket_obj.getsockopt(¤t_task, SOL_SOCKET, SO_RCVBUF, 4).unwrap();
585 let rcvbuf_val = u32::from_ne_bytes(rcvbuf.as_slice().try_into().unwrap());
586 assert_eq!(rcvbuf_val, new_rcvbuf * 2);
588 })
589 .await;
590 }
591
592 #[::fuchsia::test]
593 async fn test_qipcrtr_sockname() {
594 let (socket_inner, server_end) = mock_qipcrtr_socket();
595 std::thread::spawn(move || {
597 let mut executor = fuchsia_async::LocalExecutor::default();
598 executor.run_singlethreaded(async move {
599 let mut stream = server_end.into_stream();
600 while let Some(Ok(request)) = stream.next().await {
601 match request {
602 fqrtr::QrtrClientConnectionRequest::GetNodeId { responder, .. } => {
603 let _ = responder.send(123).unwrap();
604 }
605 fqrtr::QrtrClientConnectionRequest::GetPortId { responder, .. } => {
606 let _ = responder.send(456).unwrap();
607 }
608 fqrtr::QrtrClientConnectionRequest::CloseConnection {
609 responder, ..
610 } => {
611 let _ = responder.send();
612 }
613 _ => panic!("Unexpected request: {:?}", request),
614 }
615 }
616 });
617 });
618
619 spawn_kernel_and_run(async |_current_task| {
620 let socket_obj = Socket::new_with_ops_and_info(
621 Box::new(socket_inner),
622 SocketDomain::Qipcrtr,
623 SocketType::Datagram,
624 SocketProtocol::default(),
625 );
626
627 let addr = socket_obj.getsockname().unwrap();
628 let qrtr_addr = extract_qrtr_sockaddr(&addr).unwrap();
629 assert_eq!(qrtr_addr.sq_node, 123);
630 assert_eq!(qrtr_addr.sq_port, 456);
631
632 let peer_addr = sockaddr_qrtr {
634 sq_family: AF_QIPCRTR,
635 sq_node: 10,
636 sq_port: 20,
637 ..Default::default()
638 };
639 socket_obj
640 .downcast_socket::<QipcrtrSocket>()
641 .unwrap()
642 .inner
643 .lock()
644 .as_mut()
645 .unwrap()
646 .peer = Some(peer_addr);
647
648 let peer = socket_obj.getpeername().unwrap();
649 let peer_qrtr = extract_qrtr_sockaddr(&peer).unwrap();
650 assert_eq!(peer_qrtr.sq_node, 10);
651 assert_eq!(peer_qrtr.sq_port, 20);
652 })
653 .await;
654 }
655
656 #[::fuchsia::test]
657 async fn test_qipcrtr_read_write() {
658 let (socket_inner, server_end) = mock_qipcrtr_socket();
659 std::thread::spawn(move || {
660 let mut executor = fuchsia_async::LocalExecutor::default();
661 executor.run_singlethreaded(async move {
662 let mut stream = server_end.into_stream();
663 while let Some(Ok(request)) = stream.next().await {
664 match request {
665 fqrtr::QrtrClientConnectionRequest::Write {
666 dst_node_id,
667 dst_port,
668 data,
669 responder,
670 ..
671 } => {
672 assert_eq!(dst_node_id, 10);
673 assert_eq!(dst_port, 20);
674 assert_eq!(data, b"hello");
675 let _ = responder.send(Ok(())).unwrap();
676 }
677 fqrtr::QrtrClientConnectionRequest::Read { responder, .. } => {
678 let _ = responder.send(Ok((5, 15, b"world"))).unwrap();
679 }
680 fqrtr::QrtrClientConnectionRequest::CloseConnection {
681 responder, ..
682 } => {
683 let _ = responder.send();
684 }
685 _ => panic!("Unexpected request: {:?}", request),
686 }
687 }
688 });
689 });
690
691 spawn_kernel_and_run(async |current_task| {
692 let socket_obj = Socket::new_with_ops_and_info(
693 Box::new(socket_inner),
694 SocketDomain::Qipcrtr,
695 SocketType::Datagram,
696 SocketProtocol::default(),
697 );
698 let peer_addr = sockaddr_qrtr {
700 sq_family: AF_QIPCRTR,
701 sq_node: 10,
702 sq_port: 20,
703 ..Default::default()
704 };
705 socket_obj
706 .downcast_socket::<QipcrtrSocket>()
707 .unwrap()
708 .inner
709 .lock()
710 .as_mut()
711 .unwrap()
712 .peer = Some(peer_addr);
713
714 let mut input = VecInputBuffer::new(b"hello");
716 let written =
717 socket_obj.write(¤t_task, &mut input, &mut None, &mut vec![]).unwrap();
718 assert_eq!(written, 5);
719
720 let mut output = VecOutputBuffer::new(100);
722 let info =
723 socket_obj.read(¤t_task, &mut output, SocketMessageFlags::empty()).unwrap();
724 assert_eq!(info.bytes_read, 5);
725 assert_eq!(output.data(), b"world");
726
727 let addr = extract_qrtr_sockaddr(&info.address.unwrap()).unwrap();
728 assert_eq!(addr.sq_node, 5);
729 assert_eq!(addr.sq_port, 15);
730 })
731 .await;
732 }
733}