1use alloc::{sync::Arc, vec::Vec};
2use lazy_static::lazy_static;
3use lose_net_stack::packets::tcp::TCPPacket;
4
5use crate::fs::File;
6use crate::sync::UPIntrFreeCell;
7use crate::task::TaskControlBlock;
8
9use super::tcp::TCP;
10
11pub struct Port {
12 pub port: u16,
13 pub receivable: bool,
14 pub schedule: Option<Arc<TaskControlBlock>>,
15}
16
17lazy_static! {
18 static ref LISTEN_TABLE: UPIntrFreeCell<Vec<Option<Port>>> =
19 unsafe { UPIntrFreeCell::new(Vec::new()) };
20}
21
22pub fn listen(port: u16) -> Option<usize> {
23 let mut listen_table = LISTEN_TABLE.exclusive_access();
24 let mut index = usize::MAX;
25 for i in 0..listen_table.len() {
26 if listen_table[i].is_none() {
27 index = i;
28 break;
29 }
30 }
31
32 let listen_port = Port {
33 port,
34 receivable: false,
35 schedule: None,
36 };
37
38 if index == usize::MAX {
39 listen_table.push(Some(listen_port));
40 Some(listen_table.len() - 1)
41 } else {
42 listen_table[index] = Some(listen_port);
43 Some(index)
44 }
45}
46
47pub fn accept(listen_index: usize, task: Arc<TaskControlBlock>) {
49 let mut listen_table = LISTEN_TABLE.exclusive_access();
50 assert!(listen_index < listen_table.len());
51 let listen_port = listen_table[listen_index].as_mut();
52 assert!(listen_port.is_some());
53 let listen_port = listen_port.unwrap();
54 listen_port.receivable = true;
55 listen_port.schedule = Some(task);
56}
57
58pub fn port_acceptable(listen_index: usize) -> bool {
59 let mut listen_table = LISTEN_TABLE.exclusive_access();
60 assert!(listen_index < listen_table.len());
61
62 let listen_port = listen_table[listen_index].as_mut();
63 listen_port.map_or(false, |x| x.receivable)
64}
65
66pub fn check_accept(port: u16, tcp_packet: &TCPPacket) -> Option<()> {
68 LISTEN_TABLE.exclusive_session(|listen_table| {
69 let mut listen_ports: Vec<&mut Option<Port>> = listen_table
70 .iter_mut()
71 .filter(|x| match x {
72 Some(t) => t.port == port && t.receivable == true,
73 None => false,
74 })
75 .collect();
76 if listen_ports.len() == 0 {
77 None
78 } else {
79 let listen_port = listen_ports[0].as_mut().unwrap();
80 let task = listen_port.schedule.clone().unwrap();
81 listen_port.schedule = None;
83 listen_port.receivable = false;
84
85 accept_connection(port, tcp_packet, task);
86 Some(())
87 }
88 })
89}
90
91pub fn accept_connection(_port: u16, tcp_packet: &TCPPacket, task: Arc<TaskControlBlock>) {
92 let process = task.process.upgrade().unwrap();
93 let mut inner = process.inner_exclusive_access();
94 let fd = inner.alloc_fd();
95
96 let tcp_socket = TCP::new(
97 tcp_packet.source_ip,
98 tcp_packet.dest_port,
99 tcp_packet.source_port,
100 tcp_packet.seq,
101 tcp_packet.ack,
102 );
103
104 inner.fd_table[fd] = Some(Arc::new(tcp_socket));
105
106 let cx = task.inner_exclusive_access().get_trap_cx();
107 cx.x[10] = fd;
108}
109
110pub struct PortFd(usize);
112
113impl PortFd {
114 pub fn new(port_index: usize) -> Self {
115 PortFd(port_index)
116 }
117}
118
119impl Drop for PortFd {
120 fn drop(&mut self) {
121 LISTEN_TABLE.exclusive_access()[self.0] = None
122 }
123}
124
125impl File for PortFd {
126 fn readable(&self) -> bool {
127 false
128 }
129
130 fn writable(&self) -> bool {
131 false
132 }
133
134 fn read(&self, _buf: crate::mm::UserBuffer) -> usize {
135 0
136 }
137
138 fn write(&self, _buf: crate::mm::UserBuffer) -> usize {
139 0
140 }
141}