1use std::{
2 future::Future,
3 io,
4 mem::{ManuallyDrop, MaybeUninit},
5 ops::Deref,
6 pin::Pin,
7 task::{Context, Poll},
8};
9
10use compio_buf::{
11 BufResult, IntoInner, IoBuf, IoBufMut, IoVectoredBuf, IoVectoredBufMut, SetLenExt, buf_try,
12};
13#[cfg(windows)]
14use compio_driver::op::Disconnect;
15#[cfg(unix)]
16use compio_driver::op::{Bind, CreateSocket, Listen, ShutdownSocket};
17use compio_driver::{
18 AsFd, AsRawFd, BorrowedFd, BufferRef, OpCode, RawFd, ResultTakeBuffer, SharedFd, TakeBuffer,
19 ToSharedFd,
20 op::{
21 Accept, BufResultExt, CloseSocket, Connect, Recv, RecvFlags, RecvFrom, RecvFromManaged,
22 RecvFromMulti, RecvFromMultiResult, RecvFromVectored, RecvManaged, RecvMsg, RecvMsgManaged,
23 RecvMsgMulti, RecvMsgMultiResult, RecvMulti, RecvResultExt, RecvVectored, ReturnFlags,
24 Send, SendFlags, SendMsg, SendMsgZc, SendTo, SendToVectored, SendToVectoredZc, SendToZc,
25 SendVectored, SendVectoredZc, SendZc, VecBufResultExt,
26 },
27 syscall,
28};
29use compio_runtime::{Attacher, Runtime, SubmitMulti, SubmitMultiStream, fd::PollFd};
30use futures_util::{Stream, StreamExt};
31use pin_project_lite::pin_project;
32use socket2::{Domain, Protocol, SockAddr, Socket as Socket2, Type};
33use sys::SocketState;
34
35use crate::Incoming;
36
37cfg_select! {
38 any(
39 target_os = "linux",
40 target_os = "android",
41 target_os = "hurd",
42 target_os = "dragonfly",
43 target_os = "freebsd",
44 target_os = "openbsd",
45 target_os = "netbsd",
46 target_os = "solaris",
47 target_os = "illumos",
48 target_os = "haiku",
49 target_os = "nto",
50 target_os = "cygwin"
51 ) => {
52 pub(crate) const MSG_NOSIGNAL: SendFlags =
53 SendFlags::from_bits_retain(libc::MSG_NOSIGNAL as _);
54 }
55 _ => {
56 pub(crate) const MSG_NOSIGNAL: SendFlags = SendFlags::empty();
57 }
58}
59
60cfg_select! {
61 windows => {
62 #[path = "windows.rs"]
63 mod sys;
64 }
65 target_os = "linux" => {
66 #[path = "linux.rs"]
67 mod sys;
68 }
69 _ => {
70 #[path = "stub.rs"]
71 mod sys;
72 }
73}
74
75#[derive(Debug)]
77pub struct SocketWithState {
78 inner: Socket2,
79 #[allow(dead_code)]
80 state: SocketState,
81}
82
83impl SocketWithState {
84 fn new(inner: Socket2) -> Self {
85 Self {
86 inner,
87 state: SocketState::new(),
88 }
89 }
90
91 fn into_inner(self) -> Socket2 {
92 self.inner
93 }
94}
95
96impl Deref for SocketWithState {
97 type Target = Socket2;
98
99 fn deref(&self) -> &Self::Target {
100 &self.inner
101 }
102}
103
104impl AsRawFd for SocketWithState {
105 fn as_raw_fd(&self) -> RawFd {
106 self.inner.as_raw_fd()
107 }
108}
109
110impl AsFd for SocketWithState {
111 fn as_fd(&self) -> BorrowedFd<'_> {
112 self.inner.as_fd()
113 }
114}
115
116#[derive(Debug, Clone)]
117pub struct Socket {
118 pub(crate) socket: Attacher<SocketWithState>,
119}
120
121impl Socket {
122 pub fn from_socket2(socket: Socket2) -> io::Result<Self> {
123 Ok(Self {
124 socket: Attacher::new(SocketWithState::new(socket))?,
125 })
126 }
127
128 pub fn peer_addr(&self) -> io::Result<SockAddr> {
129 self.socket.peer_addr()
130 }
131
132 pub fn local_addr(&self) -> io::Result<SockAddr> {
133 self.socket.local_addr()
134 }
135
136 pub fn to_poll_fd(&self) -> io::Result<PollFd<SocketWithState>> {
137 PollFd::from_shared_fd(self.to_shared_fd())
138 }
139
140 pub fn into_poll_fd(self) -> io::Result<PollFd<SocketWithState>> {
141 PollFd::from_shared_fd(self.socket.into_inner())
142 }
143
144 #[cfg(windows)]
145 pub async fn new(domain: Domain, ty: Type, protocol: Option<Protocol>) -> io::Result<Self> {
146 Self::from_socket2(Socket2::new(domain, ty, protocol)?)
147 }
148
149 #[cfg(unix)]
150 pub async fn new(domain: Domain, ty: Type, protocol: Option<Protocol>) -> io::Result<Self> {
151 let op = CreateSocket::new(
152 domain.into(),
153 ty.into(),
154 protocol.map(|p| p.into()).unwrap_or_default(),
155 );
156 let (_, op) = buf_try!(@try compio_runtime::submit(op).await);
157
158 Self::from_socket2(op.into_inner())
159 }
160
161 pub async fn bind(&self, addr: &SockAddr) -> io::Result<()> {
162 #[cfg(not(unix))]
163 self.socket.bind(addr)?;
164 #[cfg(unix)]
165 {
166 let op = Bind::new(self.to_shared_fd(), addr.clone());
167 compio_runtime::submit(op).await.0?;
168 }
169 Ok(())
170 }
171
172 pub async fn listen(&self, backlog: i32) -> io::Result<()> {
173 #[cfg(not(unix))]
174 {
175 self.socket.listen(backlog)
176 }
177 #[cfg(unix)]
178 {
179 let op = Listen::new(self.to_shared_fd(), backlog);
180 compio_runtime::submit(op).await.0?;
181 Ok(())
182 }
183 }
184
185 pub fn connect(&self, addr: &SockAddr) -> io::Result<()> {
186 self.socket.connect(addr)
187 }
188
189 pub async fn connect_async(&self, addr: &SockAddr) -> io::Result<()> {
190 let op = Connect::new(self.to_shared_fd(), addr.clone());
191 let (_, _op) = buf_try!(@try compio_runtime::submit(op).await);
192 #[cfg(windows)]
193 _op.update_context()?;
194 Ok(())
195 }
196
197 #[cfg(windows)]
198 pub async fn disconnect(&self) -> io::Result<()> {
199 let op = Disconnect::new(self.to_shared_fd());
200 compio_runtime::submit(op).await.0.map(|_| ())
201 }
202
203 #[cfg(unix)]
204 pub async fn accept(&self) -> io::Result<(Self, SockAddr)> {
205 let op = Accept::new(self.to_shared_fd());
206 let (BufResult(res, op), extra) = compio_runtime::submit(op).with_extra().await;
207 res?;
208 extra.update_socket_state(&*self.socket);
209 let (accept_sock, addr) = op.into_inner();
210 let accept_sock = Self::from_socket2(accept_sock)?;
211 Ok((accept_sock, addr))
212 }
213
214 #[cfg(windows)]
215 pub async fn accept(&self) -> io::Result<(Self, SockAddr)> {
216 let domain = self.local_addr()?.domain();
217 let ty = self.socket.r#type()?;
218 let protocol = self.socket.protocol()?;
219 let accept_sock = Socket2::new(domain, ty, protocol)?;
220 self.accept_with(Self::from_socket2(accept_sock)?).await
221 }
222
223 #[cfg(windows)]
224 pub async fn accept_with(&self, accept_sock: Self) -> io::Result<(Self, SockAddr)> {
225 let op = Accept::new(self.to_shared_fd(), accept_sock);
226 let (_, op) = buf_try!(@try compio_runtime::submit(op).await);
227 op.update_context()?;
228 let (accept_sock, addr) = op.into_addr()?;
229 Ok((accept_sock, addr))
230 }
231
232 pub fn incoming(&self) -> Incoming<'_> {
233 Incoming::new(self)
234 }
235
236 pub fn close(self) -> impl Future<Output = io::Result<()>> {
237 let this = ManuallyDrop::new(self);
241 async move {
242 let fd = ManuallyDrop::into_inner(this)
243 .socket
244 .into_inner()
245 .take()
246 .await;
247 if let Some(fd) = fd {
248 let op = CloseSocket::new(fd.into_inner().into());
249 compio_runtime::submit(op).await.0?;
250 }
251 Ok(())
252 }
253 }
254
255 #[cfg(unix)]
256 async fn shutdown_impl(&self) -> io::Result<()> {
257 let op = ShutdownSocket::new(self.to_shared_fd(), std::net::Shutdown::Write);
258 compio_runtime::submit(op).await.0.map(|_| ())
259 }
260
261 #[cfg(windows)]
262 async fn shutdown_impl(&self) -> io::Result<()> {
263 self.socket.shutdown(std::net::Shutdown::Write)?;
264 Ok(())
265 }
266
267 pub async fn shutdown(&self) -> io::Result<()> {
268 match self.shutdown_impl().await {
269 Err(e) if e.kind() == io::ErrorKind::NotConnected => Ok(()),
271 res => res,
272 }
273 }
274
275 pub async fn recv<B: IoBufMut>(&self, buffer: B, flags: RecvFlags) -> BufResult<usize, B> {
276 let fd = self.to_shared_fd();
277 let op = Recv::new(fd, buffer, flags);
278 let (res, extra) = compio_runtime::submit(op).with_extra().await;
279 extra.update_socket_state(&*self.socket);
280 let res = res.into_inner();
281 unsafe { res.map_advanced() }
282 }
283
284 pub async fn recv_vectored<V: IoVectoredBufMut>(
285 &self,
286 buffer: V,
287 flags: RecvFlags,
288 ) -> BufResult<usize, V> {
289 let fd = self.to_shared_fd();
290 let op = RecvVectored::new(fd, buffer, flags);
291 let (res, extra) = compio_runtime::submit(op).with_extra().await;
292 extra.update_socket_state(&*self.socket);
293 let res = res.into_inner();
294 unsafe { res.map_vec_advanced() }
295 }
296
297 pub async fn recv_managed(
298 &self,
299 len: usize,
300 flags: RecvFlags,
301 ) -> io::Result<Option<BufferRef>> {
302 let fd = self.to_shared_fd();
303 let (res, extra) = Runtime::with_current(|rt| {
304 let buffer_pool = rt.buffer_pool()?;
305 let op = RecvManaged::new(fd, &buffer_pool, len, flags)?;
306 io::Result::Ok(rt.submit(op).with_extra())
307 })?
308 .await;
309
310 extra.update_socket_state(&*self.socket);
311
312 unsafe { res.take_buffer() }
313 }
314
315 pub fn recv_multi(
316 &self,
317 len: usize,
318 flags: RecvFlags,
319 ) -> impl Stream<Item = io::Result<BufferRef>> {
320 let fd = self.to_shared_fd();
321 let rt = Runtime::current();
322 SubmitMultiStream::new(move || {
323 let buffer_pool = rt.buffer_pool()?;
324 let op = RecvMulti::new(fd.clone(), &buffer_pool, len, flags)?;
325 Ok(rt.submit_multi(op).into_managed(buffer_pool))
326 })
327 }
328
329 pub async fn send<T: IoBuf>(&self, buffer: T, flags: SendFlags) -> BufResult<usize, T> {
330 let fd = self.to_shared_fd();
331 let op = Send::new(fd, buffer, flags);
332 compio_runtime::submit(op).await.into_inner()
333 }
334
335 pub async fn send_vectored<T: IoVectoredBuf>(
336 &self,
337 buffer: T,
338 flags: SendFlags,
339 ) -> BufResult<usize, T> {
340 let fd = self.to_shared_fd();
341 let op = SendVectored::new(fd, buffer, flags);
342 compio_runtime::submit(op).await.into_inner()
343 }
344
345 pub async fn send_zerocopy<T: IoBuf>(
346 &self,
347 buf: T,
348 flags: SendFlags,
349 ) -> BufResult<usize, Zerocopy<SendZc<T, SharedFd<SocketWithState>>>> {
350 submit_zerocopy(SendZc::new(self.to_shared_fd(), buf, flags)).await
351 }
352
353 pub async fn send_zerocopy_vectored<T: IoVectoredBuf>(
354 &self,
355 buf: T,
356 flags: SendFlags,
357 ) -> BufResult<usize, Zerocopy<SendVectoredZc<T, SharedFd<SocketWithState>>>> {
358 submit_zerocopy(SendVectoredZc::new(self.to_shared_fd(), buf, flags)).await
359 }
360
361 pub async fn recv_from<T: IoBufMut>(
362 &self,
363 buffer: T,
364 flags: RecvFlags,
365 ) -> BufResult<(usize, Option<SockAddr>), T> {
366 let fd = self.to_shared_fd();
367 let op = RecvFrom::new(fd, buffer, flags);
368 let (res, extra) = compio_runtime::submit(op).with_extra().await;
369 extra.update_socket_state(&*self.socket);
370 let res = res.into_inner().map_addr();
371 unsafe { res.map_advanced() }
372 }
373
374 pub async fn recv_from_vectored<T: IoVectoredBufMut>(
375 &self,
376 buffer: T,
377 flags: RecvFlags,
378 ) -> BufResult<(usize, Option<SockAddr>), T> {
379 let fd = self.to_shared_fd();
380 let op = RecvFromVectored::new(fd, buffer, flags);
381 let (res, extra) = compio_runtime::submit(op).with_extra().await;
382 extra.update_socket_state(&*self.socket);
383 let res = res.into_inner().map_addr();
384 unsafe { res.map_vec_advanced() }
385 }
386
387 pub async fn recv_from_managed(
388 &self,
389 len: usize,
390 flags: RecvFlags,
391 ) -> io::Result<Option<(BufferRef, Option<SockAddr>)>> {
392 let fd = self.to_shared_fd();
393 let (inner, extra) = Runtime::with_current(|rt| {
394 let buffer_pool = rt.buffer_pool()?;
395 let op = RecvFromManaged::new(fd, &buffer_pool, len, flags)?;
396 io::Result::Ok(rt.submit(op).with_extra())
397 })?
398 .await;
399 extra.update_socket_state(&*self.socket);
400 let (len, op) = buf_try!(@try inner);
401 if len == 0 {
404 return Ok(None);
405 }
406 let Some((mut buf, addr)) = op.take_buffer() else {
407 return Err(io::Error::new(
408 io::ErrorKind::UnexpectedEof,
409 format!("Read {len} bytes, but no buffer was selected by kernel"),
410 ));
411 };
412 unsafe { buf.advance_to(len) };
413 Ok(Some((buf, addr)))
414 }
415
416 pub fn recv_from_multi(
417 &self,
418 flags: RecvFlags,
419 ) -> impl Stream<Item = io::Result<RecvFromMultiResult>> {
420 let fd = self.to_shared_fd();
421 let rt = Runtime::current();
422 SubmitMultiStream::new(move || {
423 let buffer_pool = rt.buffer_pool()?;
424 let op = RecvFromMulti::new(fd.clone(), &buffer_pool, flags)?;
425 Ok(rt.submit_multi(op).into_managed(buffer_pool))
426 })
427 }
428
429 pub async fn recv_msg<T: IoBufMut, C: IoBufMut>(
430 &self,
431 buffer: T,
432 control: C,
433 flags: RecvFlags,
434 ) -> BufResult<(usize, usize, Option<SockAddr>, ReturnFlags), (T, C)> {
435 self.recv_msg_vectored([buffer], control, flags)
436 .await
437 .map_buffer(|([buffer], control)| (buffer, control))
438 }
439
440 pub async fn recv_msg_vectored<T: IoVectoredBufMut, C: IoBufMut>(
441 &self,
442 buffer: T,
443 control: C,
444 flags: RecvFlags,
445 ) -> BufResult<(usize, usize, Option<SockAddr>, ReturnFlags), (T, C)> {
446 let fd = self.to_shared_fd();
447 let op = RecvMsg::new(fd, buffer, control, flags);
448 let (res, extra) = compio_runtime::submit(op).with_extra().await;
449 extra.update_socket_state(&*self.socket);
450 let res = res.into_inner().map_addr();
451 unsafe { res.map_vec_advanced() }
452 }
453
454 pub async fn recv_msg_managed<C: IoBufMut>(
455 &self,
456 len: usize,
457 control: C,
458 flags: RecvFlags,
459 ) -> io::Result<Option<(BufferRef, C, Option<SockAddr>, ReturnFlags)>> {
460 let fd = self.to_shared_fd();
461 let (inner, extra) = Runtime::with_current(|rt| {
462 let buffer_pool = rt.buffer_pool()?;
463 let op = RecvMsgManaged::new(fd, &buffer_pool, len, control, flags)?;
464 io::Result::Ok(rt.submit(op).with_extra())
465 })?
466 .await;
467 extra.update_socket_state(&*self.socket);
468 let (len, op) = buf_try!(@try inner);
469 if len == 0 {
472 return Ok(None);
473 }
474 let Some(((mut buf, mut control), addr, control_len, flags)) = op.take_buffer() else {
475 return Err(io::Error::new(
476 io::ErrorKind::UnexpectedEof,
477 format!("Read {len} bytes, but no buffer was selected by kernel"),
478 ));
479 };
480 unsafe { buf.advance_to(len) };
481 unsafe { control.advance_to(control_len) };
482 Ok(Some((buf, control, addr, flags)))
483 }
484
485 pub fn recv_msg_multi(
486 &self,
487 control_len: usize,
488 flags: RecvFlags,
489 ) -> impl Stream<Item = io::Result<RecvMsgMultiResult>> {
490 let fd = self.to_shared_fd();
491 let rt = Runtime::current();
492 SubmitMultiStream::new(move || {
493 let buffer_pool = rt.buffer_pool()?;
494 let op = RecvMsgMulti::new(fd.clone(), &buffer_pool, control_len, flags)?;
495 io::Result::Ok(
496 rt.submit_multi(op)
497 .into_managed_with(buffer_pool, control_len),
498 )
499 })
500 }
501
502 pub async fn send_to<T: IoBuf>(
503 &self,
504 buffer: T,
505 addr: &SockAddr,
506 flags: SendFlags,
507 ) -> BufResult<usize, T> {
508 let fd = self.to_shared_fd();
509 let op = SendTo::new(fd, buffer, addr.clone(), flags);
510 compio_runtime::submit(op).await.into_inner()
511 }
512
513 pub async fn send_to_vectored<T: IoVectoredBuf>(
514 &self,
515 buffer: T,
516 addr: &SockAddr,
517 flags: SendFlags,
518 ) -> BufResult<usize, T> {
519 let fd = self.to_shared_fd();
520 let op = SendToVectored::new(fd, buffer, addr.clone(), flags);
521 compio_runtime::submit(op).await.into_inner()
522 }
523
524 pub async fn send_to_zerocopy<T: IoBuf>(
525 &self,
526 buffer: T,
527 addr: &SockAddr,
528 flags: SendFlags,
529 ) -> BufResult<usize, Zerocopy<SendToZc<T, SharedFd<SocketWithState>>>> {
530 let op = SendToZc::new(self.to_shared_fd(), buffer, addr.clone(), flags);
531 submit_zerocopy(op).await
532 }
533
534 pub async fn send_to_zerocopy_vectored<T: IoVectoredBuf>(
535 &self,
536 buffer: T,
537 addr: &SockAddr,
538 flags: SendFlags,
539 ) -> BufResult<usize, Zerocopy<SendToVectoredZc<T, SharedFd<SocketWithState>>>> {
540 let op = SendToVectoredZc::new(self.to_shared_fd(), buffer, addr.clone(), flags);
541 submit_zerocopy(op).await
542 }
543
544 pub async fn send_msg<T: IoBuf, C: IoBuf>(
545 &self,
546 buffer: T,
547 control: C,
548 addr: Option<&SockAddr>,
549 flags: SendFlags,
550 ) -> BufResult<usize, (T, C)> {
551 self.send_msg_vectored([buffer], control, addr, flags)
552 .await
553 .map_buffer(|([buffer], control)| (buffer, control))
554 }
555
556 pub async fn send_msg_vectored<T: IoVectoredBuf, C: IoBuf>(
557 &self,
558 buffer: T,
559 control: C,
560 addr: Option<&SockAddr>,
561 flags: SendFlags,
562 ) -> BufResult<usize, (T, C)> {
563 let fd = self.to_shared_fd();
564 let op = SendMsg::new(fd, buffer, control, addr.cloned(), flags);
565 compio_runtime::submit(op).await.into_inner()
566 }
567
568 pub async fn send_msg_zerocopy<T: IoBuf, C: IoBuf>(
569 &self,
570 buffer: T,
571 control: C,
572 addr: Option<&SockAddr>,
573 flags: SendFlags,
574 ) -> BufResult<usize, Extract<Zerocopy<SendMsgZc<[T; 1], C, SharedFd<SocketWithState>>>, T, C>>
575 {
576 let BufResult(res, fut) = self
577 .send_msg_zerocopy_vectored([buffer], control, addr, flags)
578 .await;
579
580 BufResult(res, Extract::new(fut))
581 }
582
583 pub async fn send_msg_zerocopy_vectored<T: IoVectoredBuf, C: IoBuf>(
584 &self,
585 buffer: T,
586 control: C,
587 addr: Option<&SockAddr>,
588 flags: SendFlags,
589 ) -> BufResult<usize, Zerocopy<SendMsgZc<T, C, SharedFd<SocketWithState>>>> {
590 let fd = self.to_shared_fd();
591 let op = SendMsgZc::new(fd, buffer, control, addr.cloned(), flags);
592 submit_zerocopy(op).await
593 }
594
595 #[cfg(unix)]
596 pub unsafe fn get_socket_option<T: Copy>(&self, level: i32, name: i32) -> io::Result<T> {
597 let mut value: MaybeUninit<T> = MaybeUninit::uninit();
598 let mut len = size_of::<T>() as libc::socklen_t;
599 syscall!(libc::getsockopt(
600 self.socket.as_raw_fd(),
601 level,
602 name,
603 value.as_mut_ptr() as _,
604 &mut len
605 ))
606 .map(|_| {
607 debug_assert_eq!(len as usize, size_of::<T>());
608 unsafe { value.assume_init() }
610 })
611 }
612
613 #[cfg(windows)]
614 pub unsafe fn get_socket_option<T: Copy>(&self, level: i32, name: i32) -> io::Result<T> {
615 let mut value: MaybeUninit<T> = MaybeUninit::uninit();
616 let mut len = size_of::<T>() as i32;
617 syscall!(
618 SOCKET,
619 windows_sys::Win32::Networking::WinSock::getsockopt(
620 self.socket.as_raw_fd() as _,
621 level,
622 name,
623 value.as_mut_ptr() as _,
624 &mut len
625 )
626 )
627 .map(|_| {
628 debug_assert_eq!(len as usize, size_of::<T>());
629 unsafe { value.assume_init() }
631 })
632 }
633
634 #[cfg(unix)]
635 pub unsafe fn set_socket_option<T: Copy>(
636 &self,
637 level: i32,
638 name: i32,
639 value: &T,
640 ) -> io::Result<()> {
641 syscall!(libc::setsockopt(
642 self.socket.as_raw_fd(),
643 level,
644 name,
645 value as *const _ as _,
646 std::mem::size_of::<T>() as _
647 ))
648 .map(|_| ())
649 }
650
651 #[cfg(windows)]
652 pub unsafe fn set_socket_option<T: Copy>(
653 &self,
654 level: i32,
655 name: i32,
656 value: &T,
657 ) -> io::Result<()> {
658 syscall!(
659 SOCKET,
660 windows_sys::Win32::Networking::WinSock::setsockopt(
661 self.socket.as_raw_fd() as _,
662 level,
663 name,
664 value as *const _ as _,
665 std::mem::size_of::<T>() as _
666 )
667 )
668 .map(|_| ())
669 }
670}
671
672impl AsRawFd for Socket {
673 fn as_raw_fd(&self) -> RawFd {
674 self.socket.as_raw_fd()
675 }
676}
677
678impl AsFd for Socket {
679 fn as_fd(&self) -> BorrowedFd<'_> {
680 self.socket.as_fd()
681 }
682}
683
684#[cfg(unix)]
685impl std::os::fd::FromRawFd for SocketWithState {
686 unsafe fn from_raw_fd(fd: RawFd) -> Self {
687 Self::new(unsafe { std::os::fd::FromRawFd::from_raw_fd(fd) })
688 }
689}
690
691#[cfg(windows)]
692impl std::os::windows::io::FromRawSocket for SocketWithState {
693 unsafe fn from_raw_socket(sock: std::os::windows::io::RawSocket) -> Self {
694 Self::new(unsafe { std::os::windows::io::FromRawSocket::from_raw_socket(sock) })
695 }
696}
697
698#[cfg(unix)]
699impl std::os::fd::FromRawFd for Socket {
700 unsafe fn from_raw_fd(fd: RawFd) -> Self {
701 Self {
702 socket: unsafe { std::os::fd::FromRawFd::from_raw_fd(fd) },
703 }
704 }
705}
706
707impl compio_driver::ToSharedFd<SocketWithState> for Socket {
708 fn to_shared_fd(&self) -> compio_driver::SharedFd<SocketWithState> {
709 self.socket.to_shared_fd()
710 }
711}
712
713#[cfg(windows)]
714impl std::os::windows::io::FromRawSocket for Socket {
715 unsafe fn from_raw_socket(sock: std::os::windows::io::RawSocket) -> Self {
716 Self {
717 socket: unsafe { std::os::windows::io::FromRawSocket::from_raw_socket(sock) },
718 }
719 }
720}
721
722#[cfg(windows)]
723impl std::os::windows::io::AsSocket for Socket {
724 fn as_socket(&self) -> std::os::windows::io::BorrowedSocket<'_> {
725 self.socket.as_socket()
726 }
727}
728
729#[cfg(windows)]
730impl std::os::windows::io::AsRawSocket for Socket {
731 fn as_raw_socket(&self) -> std::os::windows::io::RawSocket {
732 self.socket.as_raw_socket()
733 }
734}
735
736pub struct Zerocopy<T: OpCode> {
737 stream: Option<SubmitMulti<T>>,
738}
739
740impl<T: OpCode + IntoInner + 'static> Zerocopy<T> {
741 pub(crate) fn new(stream: SubmitMulti<T>) -> Self {
742 Self {
743 stream: Some(stream),
744 }
745 }
746}
747
748impl<T: OpCode + IntoInner + 'static> Future for Zerocopy<T> {
749 type Output = T::Inner;
750
751 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
752 let this = self.get_mut();
753
754 let stream = this.stream.as_mut().expect("stream should be Some");
755
756 let _ = futures_util::ready!(stream.poll_next_unpin(cx));
757
758 let stream = this.stream.take().expect("stream should be Some");
759
760 Poll::Ready(
761 stream
762 .try_take()
763 .map_err(|_| ())
764 .expect("Cannot retrieve buffer")
765 .into_inner(),
766 )
767 }
768}
769
770pin_project! {
771 pub struct Extract<F, T, C>
772 where
773 F: Future<Output = ([T; 1], C)>,
774 T: IoBuf,
775 C: IoBuf,
776 {
777 #[pin]
778 future: F,
779 }
780}
781
782impl<F, T, C> Extract<F, T, C>
783where
784 F: Future<Output = ([T; 1], C)>,
785 T: IoBuf,
786 C: IoBuf,
787{
788 pub(crate) fn new(future: F) -> Self {
789 Self { future }
790 }
791}
792
793impl<F, T, C> Future for Extract<F, T, C>
794where
795 F: Future<Output = ([T; 1], C)>,
796 T: IoBuf,
797 C: IoBuf,
798{
799 type Output = (T, C);
800
801 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
802 let this = self.project();
803
804 match this.future.poll(cx) {
805 Poll::Pending => Poll::Pending,
806 Poll::Ready(([buf], control)) => Poll::Ready((buf, control)),
807 }
808 }
809}
810
811async fn submit_zerocopy<T: OpCode + IntoInner + 'static>(op: T) -> BufResult<usize, Zerocopy<T>> {
812 let mut stream = compio_runtime::submit_multi(op);
813 let res = stream
814 .next()
815 .await
816 .expect("SubmitMulti should yield at least one item")
817 .0;
818
819 let fut = Zerocopy::new(stream);
820
821 BufResult(res, fut)
822}