1use std::net::{Ipv4Addr, SocketAddrV4};
2use std::sync::{Arc, Weak};
3
4use atomic_refcell::AtomicRefCell;
5use linux_api::errno::Errno;
6use linux_api::ioctls::IoctlRequest;
7use linux_api::socket::Shutdown;
8use nix::sys::socket::{MsgFlags, SockaddrIn};
9use shadow_shim_helper_rs::emulated_time::EmulatedTime;
10use shadow_shim_helper_rs::simulation_time::SimulationTime;
11use shadow_shim_helper_rs::syscall_types::ForeignPtr;
12
13use crate::core::work::task::TaskRef;
14use crate::core::worker::Worker;
15use crate::cshadow as c;
16use crate::host::descriptor::listener::{StateEventSource, StateListenHandle, StateListenerFilter};
17use crate::host::descriptor::socket::inet;
18use crate::host::descriptor::socket::{InetSocket, RecvmsgArgs, RecvmsgReturn, SendmsgArgs};
19use crate::host::descriptor::{File, Socket};
20use crate::host::descriptor::{
21 FileMode, FileSignals, FileState, FileStatus, OpenFile, SyscallResult,
22};
23use crate::host::memory_manager::MemoryManager;
24use crate::host::network::interface::FifoPacketPriority;
25use crate::host::network::namespace::{AssociationHandle, NetworkNamespace};
26use crate::host::syscall::io::{IoVec, IoVecReader, IoVecWriter, write_partial};
27use crate::host::syscall::types::SyscallError;
28use crate::network::packet::{PacketRc, PacketStatus};
29use crate::utility::callback_queue::CallbackQueue;
30use crate::utility::sockaddr::SockaddrStorage;
31use crate::utility::{HostTreePointer, ObjectCounter};
32
33pub struct TcpSocket {
34 tcp_state: tcp::TcpState<TcpDeps>,
35 socket_weak: Weak<AtomicRefCell<Self>>,
36 event_source: StateEventSource,
37 status: FileStatus,
38 file_state: FileState,
39 association: Option<AssociationHandle>,
40 connect_result_is_pending: bool,
41 shutdown_status: Option<Shutdown>,
42 has_open_file: bool,
45 _counter: ObjectCounter,
46}
47
48impl TcpSocket {
49 pub fn new(status: FileStatus) -> Arc<AtomicRefCell<Self>> {
50 let rv = Arc::new_cyclic(|weak: &Weak<AtomicRefCell<Self>>| {
51 let tcp_dependencies = TcpDeps {
52 timer_state: Arc::new(AtomicRefCell::new(TcpDepsTimerState {
53 socket: weak.clone(),
54 registered_by: tcp::TimerRegisteredBy::Parent,
55 })),
56 };
57
58 AtomicRefCell::new(Self {
59 tcp_state: tcp::TcpState::new(tcp_dependencies, tcp::TcpConfig::default()),
60 socket_weak: weak.clone(),
61 event_source: StateEventSource::new(),
62 status,
63 file_state: FileState::ACTIVE,
66 association: None,
67 connect_result_is_pending: false,
68 shutdown_status: None,
69 has_open_file: false,
70 _counter: ObjectCounter::new("TcpSocket"),
71 })
72 });
73
74 CallbackQueue::queue_and_run_with_legacy(|cb_queue| {
77 rv.borrow_mut().with_tcp_state(cb_queue, |_state| ())
78 });
79
80 rv
81 }
82
83 pub fn status(&self) -> FileStatus {
84 self.status
85 }
86
87 pub fn set_status(&mut self, status: FileStatus) {
88 self.status = status;
89 }
90
91 pub fn mode(&self) -> FileMode {
92 FileMode::READ | FileMode::WRITE
93 }
94
95 pub fn has_open_file(&self) -> bool {
96 self.has_open_file
97 }
98
99 pub fn supports_sa_restart(&self) -> bool {
100 true
101 }
102
103 pub fn set_has_open_file(&mut self, val: bool) {
104 self.has_open_file = val;
105 }
106
107 fn with_tcp_state<T>(
108 &mut self,
109 cb_queue: &mut CallbackQueue,
110 f: impl FnOnce(&mut tcp::TcpState<TcpDeps>) -> T,
111 ) -> T {
112 self.with_tcp_state_and_signal(cb_queue, |state| (f(state), FileSignals::empty()))
113 }
114
115 fn with_tcp_state_and_signal<T>(
117 &mut self,
118 cb_queue: &mut CallbackQueue,
119 f: impl FnOnce(&mut tcp::TcpState<TcpDeps>) -> (T, FileSignals),
120 ) -> T {
121 let rv = f(&mut self.tcp_state);
122
123 if self.tcp_state.wants_to_send() {
127 let socket = self.socket_weak.upgrade().unwrap();
131
132 let interface_ip = *self
136 .tcp_state
137 .local_remote_addrs()
138 .map(|x| x.0)
139 .or(self.association.as_ref().map(|x| x.local_addr()))
140 .unwrap()
141 .ip();
142
143 cb_queue.add(move |_cb_queue| {
144 Worker::with_active_host(|host| {
145 let socket = InetSocket::Tcp(socket);
146 host.notify_socket_has_packets(interface_ip, &socket);
147 })
148 .unwrap();
149 });
150 }
151
152 let mut read_write_flags = FileState::empty();
157 let poll_state = self.tcp_state.poll();
158
159 if poll_state.intersects(tcp::PollState::READABLE | tcp::PollState::RECV_CLOSED) {
160 read_write_flags.insert(FileState::READABLE);
161 }
162 if poll_state.intersects(tcp::PollState::WRITABLE) {
163 read_write_flags.insert(FileState::WRITABLE);
164 }
165 if poll_state.intersects(tcp::PollState::READY_TO_ACCEPT) {
166 read_write_flags.insert(FileState::READABLE);
167 }
168 if poll_state.intersects(tcp::PollState::ERROR) {
169 read_write_flags.insert(FileState::READABLE | FileState::WRITABLE);
170 }
171
172 if self.file_state.contains(FileState::CLOSED) {
175 read_write_flags = FileState::empty();
176 }
177
178 self.update_state(
180 FileState::READABLE | FileState::WRITABLE,
181 read_write_flags,
182 rv.1,
183 cb_queue,
184 );
185
186 if poll_state.contains(tcp::PollState::CLOSED) {
188 self.association = None;
190 }
193
194 rv.0
195 }
196
197 pub fn push_in_packet(
198 &mut self,
199 packet: PacketRc,
200 cb_queue: &mut CallbackQueue,
201 _recv_time: EmulatedTime,
202 ) {
203 packet.add_status(PacketStatus::RcvSocketProcessed);
204
205 let header = packet
211 .ipv4_tcp_header()
212 .expect("TCP socket received a non-tcp packet");
213
214 let payload = tcp::Payload(packet.payload());
218 assert_eq!(payload.len() as usize, packet.payload_len());
219
220 self.with_tcp_state_and_signal(cb_queue, |s| {
221 let pushed_len = s.push_packet(&header, payload).unwrap();
222 let signals = if pushed_len > 0 {
223 FileSignals::READ_BUFFER_GREW
224 } else {
225 FileSignals::empty()
226 };
227 ((), signals)
228 });
229
230 packet.add_status(PacketStatus::RcvSocketBuffered);
231 }
232
233 pub fn pull_out_packet(&mut self, cb_queue: &mut CallbackQueue) -> Option<PacketRc> {
234 #[cfg(debug_assertions)]
235 let wants_to_send = self.tcp_state.wants_to_send();
236
237 #[cfg(debug_assertions)]
239 debug_assert_eq!(self.has_data_to_send(), wants_to_send);
240
241 let rv = self.with_tcp_state(cb_queue, |s| s.pop_packet());
243
244 let (header, payload) = match rv {
245 Ok(x) => x,
246 Err(tcp::PopPacketError::NoPacket) => {
247 #[cfg(debug_assertions)]
248 debug_assert!(!wants_to_send);
249 return None;
250 }
251 Err(tcp::PopPacketError::InvalidState) => {
252 #[cfg(debug_assertions)]
253 debug_assert!(!wants_to_send);
254 return None;
255 }
256 };
257
258 #[cfg(debug_assertions)]
259 debug_assert!(wants_to_send);
260
261 let packet = PacketRc::new_ipv4_tcp(header, payload, 0);
265 packet.add_status(PacketStatus::SndCreated);
266
267 Some(packet)
268 }
269
270 pub fn peek_next_packet_priority(&self) -> Option<FifoPacketPriority> {
271 self.has_data_to_send().then_some(0)
273 }
274
275 pub fn has_data_to_send(&self) -> bool {
276 self.tcp_state.wants_to_send()
277 }
278
279 pub fn getsockname(&self) -> Result<Option<SockaddrIn>, Errno> {
280 Ok(Some(
284 self.association
285 .as_ref()
286 .map(|x| x.local_addr().into())
287 .unwrap_or(SockaddrIn::new(0, 0, 0, 0, 0)),
288 ))
289 }
290
291 pub fn getpeername(&self) -> Result<Option<SockaddrIn>, Errno> {
292 Ok(Some(
296 self.tcp_state
297 .local_remote_addrs()
298 .map(|x| x.1.into())
299 .ok_or(Errno::ENOTCONN)?,
300 ))
301
302 }
309
310 pub fn address_family(&self) -> linux_api::socket::AddressFamily {
311 linux_api::socket::AddressFamily::AF_INET
312 }
313
314 pub fn close(&mut self, cb_queue: &mut CallbackQueue) -> Result<(), SyscallError> {
315 self.with_tcp_state(cb_queue, |state| state.close())
317 .unwrap();
318
319 self.update_state(
321 FileState::all(),
322 FileState::CLOSED,
323 FileSignals::empty(),
324 cb_queue,
325 );
326
327 Ok(())
328 }
329
330 pub fn bind(
331 socket: &Arc<AtomicRefCell<Self>>,
332 addr: Option<&SockaddrStorage>,
333 net_ns: &NetworkNamespace,
334 rng: impl rand::Rng,
335 ) -> Result<(), SyscallError> {
336 let Some(addr) = addr else {
338 return Err(Errno::EFAULT.into());
339 };
340
341 let Some(addr) = addr.as_inet() else {
343 return Err(Errno::EINVAL.into());
344 };
345
346 let addr: SocketAddrV4 = (*addr).into();
347
348 let mut socket_ref = socket.borrow_mut();
349
350 if socket_ref.association.is_some() {
352 return Err(Errno::EINVAL.into());
353 }
354
355 let peer_addr = SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0);
357
358 let (_addr, handle) = inet::associate_socket(
360 InetSocket::Tcp(Arc::clone(socket)),
361 addr,
362 peer_addr,
363 true,
364 net_ns,
365 rng,
366 )?;
367
368 socket_ref.association = Some(handle);
369
370 Ok(())
371 }
372
373 pub fn readv(
374 &mut self,
375 _iovs: &[IoVec],
376 _offset: Option<libc::off_t>,
377 _flags: libc::c_int,
378 _mem: &mut MemoryManager,
379 _cb_queue: &mut CallbackQueue,
380 ) -> Result<libc::ssize_t, SyscallError> {
381 panic!("Called TcpSocket::readv() on a TCP socket");
385 }
386
387 pub fn writev(
388 &mut self,
389 _iovs: &[IoVec],
390 _offset: Option<libc::off_t>,
391 _flags: libc::c_int,
392 _mem: &mut MemoryManager,
393 _cb_queue: &mut CallbackQueue,
394 ) -> Result<libc::ssize_t, SyscallError> {
395 panic!("Called TcpSocket::writev() on a TCP socket");
399 }
400
401 pub fn sendmsg(
402 socket: &Arc<AtomicRefCell<Self>>,
403 args: SendmsgArgs,
404 mem: &mut MemoryManager,
405 _net_ns: &NetworkNamespace,
406 _rng: impl rand::Rng,
407 cb_queue: &mut CallbackQueue,
408 ) -> Result<libc::ssize_t, SyscallError> {
409 let mut socket_ref = socket.borrow_mut();
410
411 let Some(mut flags) = MsgFlags::from_bits(args.flags) else {
412 log::debug!("Unrecognized send flags: {:#b}", args.flags);
413 return Err(Errno::EINVAL.into());
414 };
415
416 if socket_ref.status().contains(FileStatus::NONBLOCK) {
417 flags.insert(MsgFlags::MSG_DONTWAIT);
418 }
419
420 let len: libc::size_t = args.iovs.iter().map(|x| x.len).sum();
421
422 let result = (|| {
424 let reader = IoVecReader::new(args.iovs, mem);
425
426 let rv = socket_ref.with_tcp_state(cb_queue, |state| state.send(reader, len));
427
428 let num_sent = match rv {
429 Ok(x) => x,
430 Err(tcp::SendError::Full) => return Err(Errno::EWOULDBLOCK),
431 Err(tcp::SendError::NotConnected) => return Err(Errno::EPIPE),
432 Err(tcp::SendError::StreamClosed) => return Err(Errno::EPIPE),
433 Err(tcp::SendError::Io(e)) => return Err(Errno::try_from(e).unwrap()),
434 Err(tcp::SendError::InvalidState) => return Err(Errno::EINVAL),
435 };
436
437 Ok(num_sent)
438 })();
439
440 if result == Err(Errno::EWOULDBLOCK) && !flags.contains(MsgFlags::MSG_DONTWAIT) {
442 return Err(SyscallError::new_blocked_on_file(
443 File::Socket(Socket::Inet(InetSocket::Tcp(socket.clone()))),
444 FileState::WRITABLE | FileState::CLOSED,
445 socket_ref.supports_sa_restart(),
446 ));
447 }
448
449 Ok(result?.try_into().unwrap())
450 }
451
452 pub fn recvmsg(
453 socket: &Arc<AtomicRefCell<Self>>,
454 args: RecvmsgArgs,
455 mem: &mut MemoryManager,
456 cb_queue: &mut CallbackQueue,
457 ) -> Result<RecvmsgReturn, SyscallError> {
458 let socket_ref = &mut *socket.borrow_mut();
459
460 if let Some(error) = socket_ref.with_tcp_state(cb_queue, |state| state.clear_error()) {
462 socket_ref.connect_result_is_pending = false;
465
466 return Err(tcp_error_to_errno(error).into());
467 }
468
469 let Some(mut flags) = MsgFlags::from_bits(args.flags) else {
470 log::debug!("Unrecognized recv flags: {:#b}", args.flags);
471 return Err(Errno::EINVAL.into());
472 };
473
474 if socket_ref.status().contains(FileStatus::NONBLOCK) {
475 flags.insert(MsgFlags::MSG_DONTWAIT);
476 }
477
478 let len: libc::size_t = args.iovs.iter().map(|x| x.len).sum();
479
480 let result = (|| {
482 let writer = IoVecWriter::new(args.iovs, mem);
483
484 let rv = socket_ref.with_tcp_state(cb_queue, |state| state.recv(writer, len));
485
486 let num_recv = match rv {
487 Ok(x) => x,
488 Err(tcp::RecvError::Empty) => {
489 if [Shutdown::SHUT_RD, Shutdown::SHUT_RDWR]
490 .map(Some)
491 .contains(&socket_ref.shutdown_status)
492 {
493 0
494 } else {
495 return Err(Errno::EWOULDBLOCK);
496 }
497 }
498 Err(tcp::RecvError::NotConnected) => return Err(Errno::ENOTCONN),
499 Err(tcp::RecvError::StreamClosed) => 0,
500 Err(tcp::RecvError::Io(e)) => return Err(Errno::try_from(e).unwrap()),
501 Err(tcp::RecvError::InvalidState) => return Err(Errno::EINVAL),
502 };
503
504 Ok(RecvmsgReturn {
505 return_val: num_recv.try_into().unwrap(),
506 addr: None,
507 msg_flags: MsgFlags::empty().bits(),
508 control_len: 0,
509 })
510 })();
511
512 if result.as_ref().err() == Some(&Errno::EWOULDBLOCK)
514 && !flags.contains(MsgFlags::MSG_DONTWAIT)
515 {
516 return Err(SyscallError::new_blocked_on_file(
517 File::Socket(Socket::Inet(InetSocket::Tcp(socket.clone()))),
518 FileState::READABLE | FileState::CLOSED,
519 socket_ref.supports_sa_restart(),
520 ));
521 }
522
523 Ok(result?)
524 }
525
526 pub fn ioctl(
527 &mut self,
528 _request: IoctlRequest,
529 _arg_ptr: ForeignPtr<()>,
530 _mem: &mut MemoryManager,
531 ) -> SyscallResult {
532 todo!();
533 }
534
535 pub fn stat(&self) -> Result<linux_api::stat::stat, SyscallError> {
536 warn_once_then_debug!("We do not yet handle stat calls on tcp sockets");
537 Err(Errno::EINVAL.into())
538 }
539
540 pub fn lseek(
541 &mut self,
542 _off: linux_api::posix_types::kernel_off_t,
543 _whence: linux_api::unistd::LSeekWhence,
544 ) -> Result<linux_api::posix_types::kernel_off_t, SyscallError> {
545 warn_once_then_debug!("We do not yet handle lseek calls on tcp sockets");
546 Err(Errno::EBADF.into())
547 }
548
549 pub fn listen(
550 socket: &Arc<AtomicRefCell<Self>>,
551 backlog: i32,
552 net_ns: &NetworkNamespace,
553 rng: impl rand::Rng,
554 cb_queue: &mut CallbackQueue,
555 ) -> Result<(), Errno> {
556 let socket_ref = &mut *socket.borrow_mut();
557
558 let backlog = backlog as u32;
561
562 let is_associated = socket_ref.association.is_some();
563
564 let rv = if is_associated {
565 let associate_fn = || Ok(None);
567 socket_ref.with_tcp_state(cb_queue, |state| state.listen(backlog, associate_fn))
568 } else {
569 let associate_fn = || {
571 let local_addr = SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0);
573
574 let peer_addr = SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0);
576 let socket = Arc::clone(socket);
577
578 let (_addr, handle) = inet::associate_socket(
580 InetSocket::Tcp(Arc::clone(&socket)),
581 local_addr,
582 peer_addr,
583 true,
584 net_ns,
585 rng,
586 )?;
587
588 Ok::<_, Errno>(Some(handle))
589 };
590 socket_ref.with_tcp_state(cb_queue, |state| state.listen(backlog, associate_fn))
591 };
592
593 let handle = match rv {
594 Ok(x) => x,
595 Err(tcp::ListenError::InvalidState) => return Err(Errno::EINVAL),
596 Err(tcp::ListenError::FailedAssociation(e)) => return Err(e),
597 };
598
599 if let Some(handle) = handle {
601 assert!(socket_ref.association.is_none());
602 socket_ref.association = Some(handle);
603 }
604
605 Ok(())
606 }
607
608 pub fn connect(
609 socket: &Arc<AtomicRefCell<Self>>,
610 peer_addr: &SockaddrStorage,
611 net_ns: &NetworkNamespace,
612 rng: impl rand::Rng,
613 cb_queue: &mut CallbackQueue,
614 ) -> Result<(), SyscallError> {
615 let socket_ref = &mut *socket.borrow_mut();
616
617 if let Some(error) = socket_ref.with_tcp_state(cb_queue, |state| state.clear_error()) {
619 socket_ref.connect_result_is_pending = false;
622
623 return Err(tcp_error_to_errno(error).into());
624 }
625
626 if socket_ref.connect_result_is_pending {
629 if socket_ref
633 .tcp_state
634 .poll()
635 .contains(tcp::PollState::CONNECTING)
636 {
637 return Err(Errno::EALREADY.into());
638 }
639
640 socket_ref.connect_result_is_pending = false;
642 return Ok(());
643 }
644
645 let Some(peer_addr) = peer_addr.as_inet() else {
647 return Err(Errno::EINVAL.into());
648 };
649
650 let mut peer_addr: std::net::SocketAddrV4 = (*peer_addr).into();
651
652 if peer_addr.ip().is_unspecified() {
655 peer_addr.set_ip(std::net::Ipv4Addr::LOCALHOST);
656 }
657
658 let local_addr = socket_ref.association.as_ref().map(|x| x.local_addr());
659
660 let rv = if let Some(mut local_addr) = local_addr {
661 if local_addr.ip().is_unspecified() {
664 if peer_addr.ip() == &std::net::Ipv4Addr::LOCALHOST {
665 local_addr.set_ip(Ipv4Addr::LOCALHOST)
666 } else {
667 local_addr.set_ip(net_ns.default_ip)
668 };
669 }
670
671 let associate_fn = || Ok((local_addr, None));
673 socket_ref.with_tcp_state(cb_queue, |state| state.connect(peer_addr, associate_fn))
674 } else {
675 let associate_fn = || {
677 let local_addr = if peer_addr.ip() == &std::net::Ipv4Addr::LOCALHOST {
680 Ipv4Addr::LOCALHOST
681 } else {
682 net_ns.default_ip
683 };
684
685 let local_addr = SocketAddrV4::new(local_addr, 0);
687
688 let (local_addr, handle) = inet::associate_socket(
689 InetSocket::Tcp(Arc::clone(socket)),
690 local_addr,
691 peer_addr,
692 true,
693 net_ns,
694 rng,
695 )?;
696
697 Ok((local_addr, Some(handle)))
699 };
700 socket_ref.with_tcp_state(cb_queue, |state| state.connect(peer_addr, associate_fn))
701 };
702
703 let handle = match rv {
704 Ok(x) => x,
705 Err(tcp::ConnectError::InProgress) => return Err(Errno::EALREADY.into()),
706 Err(tcp::ConnectError::AlreadyConnected) => return Err(Errno::EISCONN.into()),
707 Err(tcp::ConnectError::IsListening) => return Err(Errno::EISCONN.into()),
708 Err(tcp::ConnectError::InvalidState) => return Err(Errno::EINVAL.into()),
709 Err(tcp::ConnectError::FailedAssociation(e)) => return Err(e),
710 };
711
712 if let Some(handle) = handle {
714 assert!(socket_ref.association.is_none());
715 socket_ref.association = Some(handle);
716 }
717
718 socket_ref.connect_result_is_pending = true;
721
722 if socket_ref.status.contains(FileStatus::NONBLOCK) {
723 Err(Errno::EINPROGRESS.into())
724 } else {
725 let err = SyscallError::new_blocked_on_file(
726 File::Socket(Socket::Inet(InetSocket::Tcp(Arc::clone(socket)))),
727 FileState::READABLE | FileState::WRITABLE | FileState::CLOSED,
744 socket_ref.supports_sa_restart(),
745 );
746
747 Err(err)
749 }
750 }
751
752 pub fn accept(
753 &mut self,
754 net_ns: &NetworkNamespace,
755 rng: impl rand::Rng,
756 cb_queue: &mut CallbackQueue,
757 ) -> Result<OpenFile, SyscallError> {
758 let rv = self.with_tcp_state(cb_queue, |state| state.accept());
759
760 let accepted_state = match rv {
761 Ok(x) => x,
762 Err(tcp::AcceptError::InvalidState) => return Err(Errno::EINVAL.into()),
763 Err(tcp::AcceptError::NothingToAccept) => return Err(Errno::EAGAIN.into()),
764 };
765
766 let local_addr = accepted_state.local_addr();
767 let remote_addr = accepted_state.remote_addr();
768
769 let new_socket = Arc::new_cyclic(|weak: &Weak<AtomicRefCell<Self>>| {
771 let accepted_state = accepted_state.finalize(|deps| {
772 let timer_state = &mut *deps.timer_state.borrow_mut();
775 timer_state.socket = weak.clone();
776 timer_state.registered_by = tcp::TimerRegisteredBy::Parent;
777 });
778
779 AtomicRefCell::new(Self {
780 tcp_state: accepted_state,
781 socket_weak: weak.clone(),
782 event_source: StateEventSource::new(),
783 status: FileStatus::empty(),
784 file_state: FileState::ACTIVE,
787 association: None,
788 connect_result_is_pending: false,
789 shutdown_status: None,
790 has_open_file: false,
791 _counter: ObjectCounter::new("TcpSocket"),
792 })
793 });
794
795 new_socket
798 .borrow_mut()
799 .with_tcp_state(cb_queue, |_state| ());
800
801 let (_addr, handle) = inet::associate_socket(
805 InetSocket::Tcp(Arc::clone(&new_socket)),
806 local_addr,
807 remote_addr,
808 false,
809 net_ns,
810 rng,
811 )?;
812
813 new_socket.borrow_mut().association = Some(handle);
814
815 Ok(OpenFile::new(File::Socket(Socket::Inet(InetSocket::Tcp(
816 new_socket,
817 )))))
818 }
819
820 pub fn shutdown(
821 &mut self,
822 how: Shutdown,
823 cb_queue: &mut CallbackQueue,
824 ) -> Result<(), SyscallError> {
825 let how = match (how, self.shutdown_status) {
829 (_, Some(Shutdown::SHUT_RDWR)) => Shutdown::SHUT_RDWR,
831 (Shutdown::SHUT_RDWR, _) => Shutdown::SHUT_RDWR,
833 (Shutdown::SHUT_RD, None | Some(Shutdown::SHUT_RD)) => Shutdown::SHUT_RD,
834 (Shutdown::SHUT_RD, Some(Shutdown::SHUT_WR)) => Shutdown::SHUT_RDWR,
835 (Shutdown::SHUT_WR, None | Some(Shutdown::SHUT_WR)) => Shutdown::SHUT_WR,
836 (Shutdown::SHUT_WR, Some(Shutdown::SHUT_RD)) => Shutdown::SHUT_RDWR,
837 };
838
839 let tcp_how = match how {
844 Shutdown::SHUT_RD => None,
845 Shutdown::SHUT_WR => Some(tcp::Shutdown::Write),
846 Shutdown::SHUT_RDWR => Some(tcp::Shutdown::Both),
847 };
848
849 if let Some(tcp_how) = tcp_how {
850 if let Err(e) = self.with_tcp_state(cb_queue, |state| state.shutdown(tcp_how)) {
851 match e {
852 tcp::ShutdownError::NotConnected => return Err(Errno::ENOTCONN.into()),
853 tcp::ShutdownError::InvalidState => return Err(Errno::EINVAL.into()),
854 }
855 }
856 } else {
857 let not_connected = !self
861 .tcp_state
862 .poll()
863 .intersects(tcp::PollState::CONNECTING | tcp::PollState::CONNECTED);
864
865 if not_connected {
866 return Err(Errno::ENOTCONN.into());
867 }
868 }
869
870 self.shutdown_status = Some(how);
872
873 Ok(())
874 }
875
876 pub fn getsockopt(
877 &mut self,
878 level: libc::c_int,
879 optname: libc::c_int,
880 optval_ptr: ForeignPtr<()>,
881 optlen: libc::socklen_t,
882 mem: &mut MemoryManager,
883 cb_queue: &mut CallbackQueue,
884 ) -> Result<libc::socklen_t, SyscallError> {
885 match (level, optname) {
886 (libc::SOL_SOCKET, libc::SO_ERROR) => {
887 let error = self.with_tcp_state(cb_queue, |state| state.clear_error());
890 let error = error.map(tcp_error_to_errno).map(Into::into).unwrap_or(0);
891
892 let optval_ptr = optval_ptr.cast::<libc::c_int>();
893 let bytes_written = write_partial(mem, &error, optval_ptr, optlen as usize)?;
894
895 Ok(bytes_written as libc::socklen_t)
896 }
897 (libc::SOL_SOCKET, libc::SO_DOMAIN) => {
898 let domain = libc::AF_INET;
899
900 let optval_ptr = optval_ptr.cast::<libc::c_int>();
901 let bytes_written = write_partial(mem, &domain, optval_ptr, optlen as usize)?;
902
903 Ok(bytes_written as libc::socklen_t)
904 }
905 (libc::SOL_SOCKET, libc::SO_TYPE) => {
906 let sock_type = libc::SOCK_STREAM;
907
908 let optval_ptr = optval_ptr.cast::<libc::c_int>();
909 let bytes_written = write_partial(mem, &sock_type, optval_ptr, optlen as usize)?;
910
911 Ok(bytes_written as libc::socklen_t)
912 }
913 (libc::SOL_SOCKET, libc::SO_PROTOCOL) => {
914 let protocol = libc::IPPROTO_TCP;
915
916 let optval_ptr = optval_ptr.cast::<libc::c_int>();
917 let bytes_written = write_partial(mem, &protocol, optval_ptr, optlen as usize)?;
918
919 Ok(bytes_written as libc::socklen_t)
920 }
921 (libc::SOL_SOCKET, libc::SO_ACCEPTCONN) => {
922 let is_listener = self.tcp_state.poll().contains(tcp::PollState::LISTENING);
923 let is_listener = is_listener as libc::c_int;
924
925 let optval_ptr = optval_ptr.cast::<libc::c_int>();
926 let bytes_written = write_partial(mem, &is_listener, optval_ptr, optlen as usize)?;
927
928 Ok(bytes_written as libc::socklen_t)
929 }
930 (libc::SOL_SOCKET, libc::SO_BROADCAST) => {
931 let optval_ptr = optval_ptr.cast::<libc::c_int>();
932 let bytes_written = write_partial(mem, &0, optval_ptr, optlen as usize)?;
934
935 Ok(bytes_written as libc::socklen_t)
936 }
937 _ => {
938 log_once_per_value_at_level!(
939 (level, optname),
940 (i32, i32),
941 log::Level::Warn,
942 log::Level::Debug,
943 "getsockopt called with unsupported level {level} and opt {optname}"
944 );
945 Err(Errno::ENOPROTOOPT.into())
946 }
947 }
948 }
949
950 pub fn setsockopt(
951 &mut self,
952 level: libc::c_int,
953 optname: libc::c_int,
954 optval_ptr: ForeignPtr<()>,
955 optlen: libc::socklen_t,
956 mem: &MemoryManager,
957 ) -> Result<(), SyscallError> {
958 match (level, optname) {
959 (libc::SOL_SOCKET, libc::SO_REUSEADDR) => {
960 log::trace!("setsockopt SO_REUSEADDR not yet implemented");
962 }
963 (libc::SOL_SOCKET, libc::SO_REUSEPORT) => {
964 log::trace!("setsockopt SO_REUSEPORT not yet implemented");
966 }
967 (libc::SOL_SOCKET, libc::SO_KEEPALIVE) => {
968 log::trace!("setsockopt SO_KEEPALIVE not yet implemented");
970 }
971 (libc::SOL_SOCKET, libc::SO_BROADCAST) => {
972 type OptType = libc::c_int;
973
974 if usize::try_from(optlen).unwrap() < std::mem::size_of::<OptType>() {
975 return Err(Errno::EINVAL.into());
976 }
977
978 let optval_ptr = optval_ptr.cast::<OptType>();
979 let val = mem.read(optval_ptr)?;
980
981 if val == 0 {
982 } else {
984 warn_once_then_debug!(
986 "setsockopt SO_BROADCAST not yet implemented for tcp; ignoring and returning 0"
987 );
988 }
989 }
990 _ => {
991 log_once_per_value_at_level!(
992 (level, optname),
993 (i32, i32),
994 log::Level::Warn,
995 log::Level::Debug,
996 "setsockopt called with unsupported level {level} and opt {optname}"
997 );
998 return Err(Errno::ENOPROTOOPT.into());
999 }
1000 }
1001
1002 Ok(())
1003 }
1004
1005 pub fn add_listener(
1006 &mut self,
1007 monitoring_state: FileState,
1008 monitoring_signals: FileSignals,
1009 filter: StateListenerFilter,
1010 notify_fn: impl Fn(FileState, FileState, FileSignals, &mut CallbackQueue)
1011 + Send
1012 + Sync
1013 + 'static,
1014 ) -> StateListenHandle {
1015 self.event_source
1016 .add_listener(monitoring_state, monitoring_signals, filter, notify_fn)
1017 }
1018
1019 pub fn add_legacy_listener(&mut self, ptr: HostTreePointer<c::StatusListener>) {
1020 self.event_source.add_legacy_listener(ptr);
1021 }
1022
1023 pub fn remove_legacy_listener(&mut self, ptr: *mut c::StatusListener) {
1024 self.event_source.remove_legacy_listener(ptr);
1025 }
1026
1027 pub fn state(&self) -> FileState {
1028 self.file_state
1029 }
1030
1031 fn update_state(
1032 &mut self,
1033 mask: FileState,
1034 state: FileState,
1035 signals: FileSignals,
1036 cb_queue: &mut CallbackQueue,
1037 ) {
1038 let old_state = self.file_state;
1039
1040 self.file_state.remove(mask);
1042 self.file_state.insert(state & mask);
1043
1044 self.handle_state_change(old_state, signals, cb_queue);
1045 }
1046
1047 fn handle_state_change(
1048 &mut self,
1049 old_state: FileState,
1050 signals: FileSignals,
1051 cb_queue: &mut CallbackQueue,
1052 ) {
1053 let states_changed = self.file_state ^ old_state;
1054
1055 if states_changed.is_empty() && signals.is_empty() {
1057 return;
1058 }
1059
1060 self.event_source
1061 .notify_listeners(self.file_state, states_changed, signals, cb_queue);
1062 }
1063}
1064
1065fn tcp_error_to_errno(error: tcp::TcpError) -> Errno {
1066 match error {
1067 tcp::TcpError::ResetSent => Errno::ECONNRESET,
1068 tcp::TcpError::ResetReceived => Errno::ECONNREFUSED,
1070 tcp::TcpError::ClosedWhileConnecting => Errno::ECONNRESET,
1071 tcp::TcpError::TimedOut => Errno::ETIMEDOUT,
1072 }
1073}
1074
1075#[derive(Debug)]
1078struct TcpDepsTimerState {
1079 socket: Weak<AtomicRefCell<TcpSocket>>,
1081 registered_by: tcp::TimerRegisteredBy,
1084}
1085
1086#[derive(Debug)]
1089struct TcpDeps {
1090 timer_state: Arc<AtomicRefCell<TcpDepsTimerState>>,
1094}
1095
1096impl tcp::Dependencies for TcpDeps {
1097 type Instant = EmulatedTime;
1098 type Duration = SimulationTime;
1099
1100 fn register_timer(
1101 &self,
1102 time: Self::Instant,
1103 f: impl FnOnce(&mut tcp::TcpState<Self>, tcp::TimerRegisteredBy) + Send + Sync + 'static,
1104 ) {
1105 let timer_state = self.timer_state.borrow();
1110 let socket = timer_state.socket.upgrade().unwrap();
1111 let registered_by = timer_state.registered_by;
1112
1113 let f = Arc::new(AtomicRefCell::new(Some(f)));
1117
1118 Worker::with_active_host(|host| {
1120 let task = TaskRef::new(move |_host| {
1121 let f = f.borrow_mut().take().unwrap();
1123
1124 CallbackQueue::queue_and_run_with_legacy(|cb_queue| {
1126 socket.borrow_mut().with_tcp_state(cb_queue, |state| {
1127 f(state, registered_by);
1128 })
1129 });
1130 });
1131
1132 host.schedule_task_at_emulated_time(task, time);
1133 })
1134 .unwrap();
1135 }
1136
1137 fn current_time(&self) -> Self::Instant {
1138 Worker::current_time().unwrap()
1139 }
1140
1141 fn fork(&self) -> Self {
1142 let timer_state = self.timer_state.borrow();
1143
1144 assert_eq!(timer_state.registered_by, tcp::TimerRegisteredBy::Parent);
1146
1147 Self {
1148 timer_state: Arc::new(AtomicRefCell::new(TcpDepsTimerState {
1149 socket: timer_state.socket.clone(),
1150 registered_by: tcp::TimerRegisteredBy::Child,
1151 })),
1152 }
1153 }
1154}