1use alloc::string::String;
2use alloc::vec::Vec;
3
4pub fn tcp_socket_lines() -> Vec<String> {
5 let mut lines = Vec::new();
6 unsafe {
7 for i in 0..super::TCP_SOCKET_TABLE_SIZE {
8 let s = &super::TCP_SOCKETS[i];
9 if !s.valid {
10 continue;
11 }
12 lines.push(alloc::format!(
13 "lport={} -> {}:{} state={} snd_nxt={} rcv_nxt={} rx_buf={}",
14 s.local_port,
15 super::format_ipv4(s.remote_ip),
16 s.remote_port,
17 tcp_state_name(s.state),
18 s.snd_nxt,
19 s.rcv_nxt,
20 s.rx_buffer.len()
21 ));
22 }
23 }
24 lines
25}
26
27pub fn tcp_connect_real(remote_ip: [u8; 4], remote_port: u16) -> Result<u16, &'static str> {
28 let _p = crate::os_lib::web_engine::perf::start();
29 let r = tcp_connect_real_measured(remote_ip, remote_port);
30 crate::os_lib::web_engine::perf::add(
31 crate::os_lib::web_engine::perf::Slot::TcpConnect,
32 _p,
33 );
34 r
35}
36
37fn tcp_connect_real_measured(remote_ip: [u8; 4], remote_port: u16) -> Result<u16, &'static str> {
38 if remote_port == 0 {
39 return Err("invalid remote port");
40 }
41
42 let local_port = {
43 let _lock = super::NET_LOCK.lock();
44 unsafe {
45 let picked = super::tcp_state::next_ephemeral_port(
49 super::TCP_EPHEMERAL_PORT,
50 |port| {
51 (0..super::TCP_SOCKET_TABLE_SIZE)
52 .any(|i| super::TCP_SOCKETS[i].valid && super::TCP_SOCKETS[i].local_port == port)
53 },
54 );
55 let p = picked.unwrap_or(super::TCP_EPHEMERAL_PORT);
61 super::TCP_EPHEMERAL_PORT = p.wrapping_add(1);
62 if super::TCP_EPHEMERAL_PORT < 40000 {
63 super::TCP_EPHEMERAL_PORT = 40000;
64 }
65 p
66 }
67 };
68
69 let idx = {
70 let _lock = super::NET_LOCK.lock();
71 tcp_alloc_socket(local_port, remote_ip, remote_port)?
72 };
73
74 let mut syn_pkt = [0u8; 128];
75 let syn_len = {
76 let _lock = super::NET_LOCK.lock();
77 unsafe {
78 super::TCP_SOCKETS[idx].state = super::TcpState::SynSent;
79 super::TCP_SOCKETS[idx].snd_nxt = 1000;
80 }
81 build_tcp_ipv4(
82 super::status().ip,
83 local_port,
84 remote_ip,
85 remote_port,
86 1000,
87 0,
88 0x02, &[],
90 &mut syn_pkt,
91 )?
92 };
93 let my_ip = super::status().ip;
94 crate::info!(
95 "TCP CONNECT: {}.{}.{}.{} -> {}.{}.{}.{}:{} (SYN, src_ip valid={})",
96 my_ip[0],
97 my_ip[1],
98 my_ip[2],
99 my_ip[3],
100 remote_ip[0],
101 remote_ip[1],
102 remote_ip[2],
103 remote_ip[3],
104 remote_port,
105 my_ip != [0, 0, 0, 0]
106 );
107 if let Err(e) = super::arp::transmit_nic_ipv4_packet(&syn_pkt[..syn_len]) {
113 crate::warn!("[NET] TCP CONNECT: SYN transmit failed: {}", e);
114 let _lock = super::NET_LOCK.lock();
115 unsafe {
116 super::TCP_SOCKETS[idx] = super::TcpSocket::empty();
117 REASSEMBLERS[idx].clear();
120 }
121 return Err(e);
122 }
123
124 let start_time = crate::kernel::timer::get_system_time_ms();
131 let mut last_retx = start_time;
132 while crate::kernel::timer::get_system_time_ms() - start_time < 6000 {
133 let state = {
134 let _lock = super::NET_LOCK.lock();
135 unsafe { super::TCP_SOCKETS[idx].state }
136 };
137 if state == super::TcpState::Established {
138 crate::info!("[NET] TCP CONNECT: established on local_port={}", local_port);
139 return Ok(local_port);
140 }
141 if state == super::TcpState::Closed {
142 let _lock = super::NET_LOCK.lock();
150 unsafe {
151 super::TCP_SOCKETS[idx] = super::TcpSocket::empty();
152 REASSEMBLERS[idx].clear();
155 }
156 return Err("tcp connection refused (RST received)");
157 }
158 let now = crate::kernel::timer::get_system_time_ms();
159 if now - last_retx >= 500 {
160 if let Err(e) = super::arp::transmit_nic_ipv4_packet(&syn_pkt[..syn_len]) {
164 crate::warn!("[NET] TCP CONNECT: SYN retransmit failed: {}", e);
165 }
166 last_retx = now;
167 }
168 crate::kernel::scheduler::sleep(1);
171 }
172
173 {
174 let _lock = super::NET_LOCK.lock();
175 unsafe {
176 super::TCP_SOCKETS[idx] = super::TcpSocket::empty();
177 REASSEMBLERS[idx].clear();
180 }
181 }
182 crate::warn!(
186 "[NET][SYNDIAG] connect timeout dst={}.{}.{}.{}:{} local_port={}",
187 remote_ip[0], remote_ip[1], remote_ip[2], remote_ip[3],
188 remote_port,
189 local_port
190 );
191 Err("tcp connect timeout")
192}
193
194pub fn tcp_send_real(local_port: u16, data: &[u8]) -> Result<(), &'static str> {
195 let _lock = super::NET_LOCK.lock();
196 let idx = tcp_find_socket_by_local(local_port).ok_or("socket not found")?;
197 let (remote_ip, remote_port, seq, ack) = unsafe {
198 let s = &super::TCP_SOCKETS[idx];
199 if s.state != super::TcpState::Established {
200 return Err("socket not established");
201 }
202 (s.remote_ip, s.remote_port, s.snd_nxt, s.rcv_nxt)
203 };
204
205 let mut pkt = alloc::vec![0u8; 128 + data.len()];
206 let pkt_len = build_tcp_ipv4(
207 super::status().ip,
208 local_port,
209 remote_ip,
210 remote_port,
211 seq,
212 ack,
213 0x18,
214 data,
215 &mut pkt,
216 )?;
217 if let Err(e) = super::arp::transmit_nic_ipv4_packet(&pkt[..pkt_len]) {
223 crate::warn!(
224 "[NET] TCP SEND failed on local_port={} len={}: {}",
225 local_port,
226 data.len(),
227 e
228 );
229 return Err(e);
230 }
231 unsafe {
232 super::TCP_SOCKETS[idx].snd_nxt = super::TCP_SOCKETS[idx]
233 .snd_nxt
234 .wrapping_add(data.len() as u32);
235 }
236 Ok(())
237}
238
239pub fn tcp_retransmit_real(local_port: u16, data: &[u8], seq: u32) -> Result<(), &'static str> {
247 let _lock = super::NET_LOCK.lock();
248 let idx = tcp_find_socket_by_local(local_port).ok_or("socket not found")?;
249 let (remote_ip, remote_port, ack) = unsafe {
250 let s = &super::TCP_SOCKETS[idx];
251 if s.state != super::TcpState::Established {
252 return Err("socket not established");
253 }
254 (s.remote_ip, s.remote_port, s.rcv_nxt)
255 };
256
257 let mut pkt = alloc::vec![0u8; 128 + data.len()];
258 let pkt_len = build_tcp_ipv4(
259 super::status().ip,
260 local_port,
261 remote_ip,
262 remote_port,
263 seq,
264 ack,
265 0x18,
266 data,
267 &mut pkt,
268 )?;
269 if let Err(e) = super::arp::transmit_nic_ipv4_packet(&pkt[..pkt_len]) {
271 crate::warn!(
272 "[NET] TCP RETRANSMIT failed on local_port={} seq={}: {}",
273 local_port,
274 seq,
275 e
276 );
277 return Err(e);
278 }
279 Ok(())
280}
281
282pub fn tcp_current_snd_seq(local_port: u16) -> Option<u32> {
286 let _lock = super::NET_LOCK.lock();
287 unsafe {
288 tcp_find_socket_by_local(local_port).map(|idx| super::TCP_SOCKETS[idx].snd_nxt)
289 }
290}
291
292pub fn tcp_recv_real(
293 local_port: u16,
294 timeout_iters: usize,
295) -> Result<alloc::vec::Vec<u8>, &'static str> {
296 let idx = tcp_find_socket_by_local(local_port).ok_or("socket not found")?;
297
298 let max_timeout_ms = if timeout_iters <= 1 {
299 0
300 } else {
301 (timeout_iters as u32 * 5).min(5000)
302 };
303
304 let start_time = crate::kernel::timer::get_system_time_ms();
305 loop {
306 RECV_POLLS.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
310 crate::kernel::usb::poll_ethernet_data_plane_only();
311
312 let buf_opt = {
313 let _lock = super::NET_LOCK.lock();
314 unsafe {
315 if !super::TCP_SOCKETS[idx].rx_buffer.is_empty()
316 || super::TCP_SOCKETS[idx].state == super::TcpState::CloseWait
317 || super::TCP_SOCKETS[idx].fin_received
318 {
319 Some(core::mem::take(&mut super::TCP_SOCKETS[idx].rx_buffer))
340 } else {
341 None
342 }
343 }
344 };
345
346 if let Some(buf) = buf_opt {
347 return Ok(buf);
348 }
349
350 if max_timeout_ms == 0
351 || crate::kernel::timer::get_system_time_ms() - start_time >= max_timeout_ms as u64
352 {
353 break;
354 }
355 crate::kernel::scheduler::sleep(1);
358 }
359
360 Ok(alloc::vec::Vec::new())
361}
362
363pub fn wait_for_first_byte(local_port: u16, max_ticks: usize) {
381 let _p = crate::os_lib::web_engine::perf::start();
382 wait_for_first_byte_inner(local_port, max_ticks);
383 crate::os_lib::web_engine::perf::add(
384 crate::os_lib::web_engine::perf::Slot::FirstByte,
385 _p,
386 );
387}
388
389fn wait_for_first_byte_inner(local_port: u16, max_ticks: usize) {
390 let start = crate::kernel::timer::get_ticks();
391 while crate::kernel::timer::get_ticks().wrapping_sub(start) < max_ticks {
392 crate::kernel::usb::poll_ethernet_data_plane_only();
393 if tcp_recv_peek_nonempty(local_port) || tcp_is_socket_closed(local_port) {
394 return;
395 }
396 crate::kernel::scheduler::sleep(1);
397 }
398}
399
400pub fn tcp_recv_peek_nonempty(local_port: u16) -> bool {
401 let _lock = super::NET_LOCK.lock();
402 unsafe {
403 if let Some(idx) = tcp_find_socket_by_local(local_port) {
404 !super::TCP_SOCKETS[idx].rx_buffer.is_empty()
405 } else {
406 false
407 }
408 }
409}
410
411pub fn tcp_is_socket_closed(local_port: u16) -> bool {
412 let _lock = super::NET_LOCK.lock();
413 unsafe {
414 if let Some(idx) = tcp_find_socket_by_local(local_port) {
415 let s = &super::TCP_SOCKETS[idx];
416 s.state == super::TcpState::CloseWait
417 || s.state == super::TcpState::Closed
418 || s.state == super::TcpState::TimeWait
419 || s.fin_received
420 } else {
421 true
422 }
423 }
424}
425
426static mut REASSEMBLERS: [super::reassembly::Reassembler; super::TCP_SOCKET_TABLE_SIZE] =
429 [const { super::reassembly::Reassembler::new_const() }; super::TCP_SOCKET_TABLE_SIZE];
430
431pub static SEG_ACCEPTED: core::sync::atomic::AtomicU32 = core::sync::atomic::AtomicU32::new(0);
433pub static SEG_DROPPED: core::sync::atomic::AtomicU32 = core::sync::atomic::AtomicU32::new(0);
434
435pub static RECV_POLLS: core::sync::atomic::AtomicU32 = core::sync::atomic::AtomicU32::new(0);
440
441pub fn tcp_close_real(local_port: u16) -> Result<(), &'static str> {
458 let idx = {
459 let _lock = super::NET_LOCK.lock();
460 tcp_find_socket_by_local(local_port).ok_or("socket not found")?
461 };
462
463 let (remote_ip, remote_port, seq, ack) = {
464 let _lock = super::NET_LOCK.lock();
465 unsafe {
466 let s = &super::TCP_SOCKETS[idx];
467 if s.state != super::TcpState::Established && s.state != super::TcpState::CloseWait {
468 super::TCP_SOCKETS[idx] = super::TcpSocket::empty();
480 REASSEMBLERS[idx].clear();
483 return Ok(());
484 }
485 (s.remote_ip, s.remote_port, s.snd_nxt, s.rcv_nxt)
486 }
487 };
488
489 {
490 let _lock = super::NET_LOCK.lock();
491 unsafe {
492 super::TCP_SOCKETS[idx].state = super::TcpState::FinWait1;
493 super::TCP_SOCKETS[idx].snd_nxt = super::TCP_SOCKETS[idx].snd_nxt.wrapping_add(1);
494 }
495 }
496
497 let mut fin_pkt = [0u8; 128];
498 let len = build_tcp_ipv4(
499 super::status().ip,
500 local_port,
501 remote_ip,
502 remote_port,
503 seq,
504 ack,
505 0x11, &[],
507 &mut fin_pkt,
508 )?;
509 if let Err(e) = super::arp::transmit_nic_ipv4_packet(&fin_pkt[..len]) {
513 crate::warn!(
514 "[NET] TCP CLOSE: FIN transmit failed on local_port={}: {}",
515 local_port,
516 e
517 );
518 }
519
520 {
521 let _lock = super::NET_LOCK.lock();
522 unsafe {
523 super::NET_STATE.tx_packets = super::NET_STATE.tx_packets.saturating_add(1);
524 }
525 }
526
527 let start_time = crate::kernel::timer::get_system_time_ms();
528 while crate::kernel::timer::get_system_time_ms() - start_time < 3000 {
529 crate::kernel::usb::poll_ethernet_data_plane_only();
530
531 let state = {
532 let _lock = super::NET_LOCK.lock();
533 unsafe { super::TCP_SOCKETS[idx].state }
534 };
535
536 if state == super::TcpState::TimeWait || state == super::TcpState::Closed {
537 break;
538 }
539 crate::kernel::scheduler::yield_now();
542 }
543
544 {
545 let _lock = super::NET_LOCK.lock();
546 unsafe {
547 super::TCP_SOCKETS[idx] = super::TcpSocket::empty();
548 REASSEMBLERS[idx].clear();
551 }
552 }
553
554 Ok(())
555}
556
557pub(crate) fn parse_tcp_ipv4_packet(packet: &[u8]) -> Result<(), &'static str> {
558 if packet.len() < 20 {
563 return Err("tcp packet too short");
564 }
565 let ihl = ((packet[0] & 0x0F) as usize) * 4;
566 if ihl < 20 || packet.len() < ihl + 20 {
567 return Err("tcp packet too short");
568 }
569
570 let total_len = (((packet[2] as u16) << 8) | packet[3] as u16) as usize;
571 if total_len < ihl + 20 || total_len > packet.len() {
572 return Err("invalid ipv4 total length");
573 }
574
575 let tcp = &packet[ihl..total_len];
576 let src_port = ((tcp[0] as u16) << 8) | tcp[1] as u16;
577 let dst_port = ((tcp[2] as u16) << 8) | tcp[3] as u16;
578 let seq =
579 ((tcp[4] as u32) << 24) | ((tcp[5] as u32) << 16) | ((tcp[6] as u32) << 8) | tcp[7] as u32;
580 let ack = ((tcp[8] as u32) << 24)
581 | ((tcp[9] as u32) << 16)
582 | ((tcp[10] as u32) << 8)
583 | tcp[11] as u32;
584 let data_offset = ((tcp[12] >> 4) as usize) * 4;
585 if data_offset < 20 || data_offset > tcp.len() {
586 return Err("invalid tcp data offset");
587 }
588
589 let flags = tcp[13];
590 let payload_len = tcp.len() - data_offset;
591 let src_ip = [packet[12], packet[13], packet[14], packet[15]];
592
593 if dst_port > 1024 {
594 crate::debug!(
595 "TCP RX: src_port={} dst_port={} flags=0x{:02x} payload_len={}",
596 src_port,
597 dst_port,
598 flags,
599 payload_len
600 );
601 }
602
603 let mut ack_pkt = [0u8; 128];
608 let mut ack_len = 0usize;
609
610 {
611 let _lock = super::NET_LOCK.lock();
612 let idx = tcp_find_socket(dst_port, src_ip, src_port).ok_or("tcp socket not found")?;
613
614 unsafe {
615 let s = &mut super::TCP_SOCKETS[idx];
631
632 let mut rs = super::tcp_state::RecvState {
636 state: s.state,
637 snd_nxt: s.snd_nxt,
638 rcv_nxt: s.rcv_nxt,
639 fin_received: s.fin_received,
640 };
641 let seg = super::tcp_state::Segment {
642 seq,
643 ack,
644 flags,
645 payload_len: payload_len as u32,
646 };
647 let prev_fin = rs.fin_received;
648 let outcome = super::tcp_state::on_segment(&mut rs, &seg);
649 if payload_len > 0 {
652 if outcome.accept_payload {
653 SEG_ACCEPTED.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
654 } else {
655 SEG_DROPPED.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
656 }
657 }
658
659 if outcome.accept_payload {
660 s.rx_buffer.extend_from_slice(&tcp[data_offset..]);
661 let reasm = &mut REASSEMBLERS[idx];
664 reasm.drop_before(rs.rcv_nxt);
665 let (new_nxt, more) = reasm.pop_contiguous(rs.rcv_nxt);
666 if !more.is_empty() {
667 s.rx_buffer.extend_from_slice(&more);
668 rs.rcv_nxt = new_nxt;
669 }
670 } else if payload_len > 0
671 && (flags & super::tcp_state::FLAG_SYN) == 0
672 && rs.state == super::TcpState::Established
673 {
674 let _ = REASSEMBLERS[idx].insert(seq, &tcp[data_offset..]);
678 }
679 if (flags & super::tcp_state::FLAG_FIN) != 0 && !prev_fin {
680 crate::warn!(
681 "[NET][DIAG] FIN seg on local_port={} state={} accepted={} rx_buffer_len={}",
682 s.local_port,
683 tcp_state_name(s.state),
684 rs.fin_received,
685 s.rx_buffer.len()
686 );
687 }
688
689 s.state = rs.state;
690 s.snd_nxt = rs.snd_nxt;
691 s.rcv_nxt = rs.rcv_nxt;
692 s.fin_received = rs.fin_received;
693
694 if outcome.send_ack {
695 if let Ok(n) = build_tcp_ack_packet(idx, &mut ack_pkt) {
696 ack_len = n;
697 }
698 }
699
700 super::NET_STATE.rx_packets = super::NET_STATE.rx_packets.saturating_add(1);
701 }
702 } if ack_len > 0 {
705 if let Err(e) = super::arp::transmit_nic_ipv4_packet(&ack_pkt[..ack_len]) {
709 crate::warn!("[NET] TCP: ACK transmit failed: {}", e);
710 }
711 }
712
713 Ok(())
714}
715
716fn build_tcp_ack_packet(idx: usize, out: &mut [u8]) -> Result<usize, &'static str> {
732 unsafe {
733 let s = &super::TCP_SOCKETS[idx];
742 build_tcp_ipv4(
743 super::status().ip,
744 s.local_port,
745 s.remote_ip,
746 s.remote_port,
747 s.snd_nxt,
748 s.rcv_nxt,
749 0x10, &[],
751 out,
752 )
753 }
754}
755
756fn tcp_alloc_socket(
757 local_port: u16,
758 remote_ip: [u8; 4],
759 remote_port: u16,
760) -> Result<usize, &'static str> {
761 unsafe {
762 let idx = super::tcp_state::find_free_slot(super::TCP_SOCKET_TABLE_SIZE, |i| {
765 super::TCP_SOCKETS[i].valid
766 })?;
767 REASSEMBLERS[idx].clear();
769 super::TCP_SOCKETS[idx] = super::TcpSocket {
770 valid: true,
771 local_port,
772 remote_ip,
773 remote_port,
774 state: super::TcpState::Closed,
775 snd_nxt: 0,
776 rcv_nxt: 0,
777 rx_buffer: alloc::vec::Vec::new(),
778 fin_received: false,
779 };
780 Ok(idx)
781 }
782}
783
784#[cfg(test)]
794pub fn tcp_fill_socket_table_for_test() -> usize {
795 let _lock = super::NET_LOCK.lock();
796 let mut occupied = 0usize;
797 unsafe {
798 for i in 0..super::TCP_SOCKET_TABLE_SIZE {
799 if super::TCP_SOCKETS[i].valid {
800 continue;
801 }
802 super::TCP_SOCKETS[i] = super::TcpSocket {
803 valid: true,
804 local_port: 40000 + i as u16,
806 remote_ip: [203, 0, 113, 1],
807 remote_port: 9,
808 state: super::TcpState::Closed,
809 snd_nxt: 0,
810 rcv_nxt: 0,
811 rx_buffer: alloc::vec::Vec::new(),
812 fin_received: false,
813 };
814 occupied += 1;
815 }
816 }
817 occupied
818}
819
820#[cfg(test)]
825pub fn tcp_clear_socket_table_for_test() {
826 let _lock = super::NET_LOCK.lock();
827 unsafe {
828 for i in 0..super::TCP_SOCKET_TABLE_SIZE {
829 super::TCP_SOCKETS[i] = super::TcpSocket::empty();
830 }
831 }
832}
833
834fn tcp_find_socket(local_port: u16, remote_ip: [u8; 4], remote_port: u16) -> Option<usize> {
835 unsafe {
836 for i in 0..super::TCP_SOCKET_TABLE_SIZE {
837 let s = &super::TCP_SOCKETS[i];
838 if !s.valid {
839 continue;
840 }
841 if s.local_port == local_port
842 && s.remote_port == remote_port
843 && s.remote_ip == remote_ip
844 {
845 return Some(i);
846 }
847 }
848 }
849 None
850}
851
852pub(crate) fn tcp_find_socket_by_local(local_port: u16) -> Option<usize> {
853 unsafe {
854 for i in 0..super::TCP_SOCKET_TABLE_SIZE {
855 if super::TCP_SOCKETS[i].valid && super::TCP_SOCKETS[i].local_port == local_port {
856 return Some(i);
857 }
858 }
859 }
860 None
861}
862
863fn build_tcp_ipv4(
864 src_ip: [u8; 4],
865 src_port: u16,
866 dst_ip: [u8; 4],
867 dst_port: u16,
868 seq: u32,
869 ack: u32,
870 flags: u8,
871 payload: &[u8],
872 out: &mut [u8],
873) -> Result<usize, &'static str> {
874 let mut opt_len = 0;
875 if (flags & 0x02) != 0 {
876 opt_len = 4;
877 }
878 let tcp_hdr_len = 20usize + opt_len;
879 let tcp_len = tcp_hdr_len + payload.len();
880 let total_len = 20usize + tcp_len;
881 if total_len > out.len() {
882 return Err("buffer too small");
883 }
884
885 out[0] = 0x45;
886 out[1] = 0;
887 out[2] = ((total_len >> 8) & 0xFF) as u8;
888 out[3] = (total_len & 0xFF) as u8;
889 out[4] = 0x61;
890 out[5] = 0x22;
891 out[6] = 0;
892 out[7] = 0;
893 out[8] = 64;
894 out[9] = 6;
895 out[10] = 0;
896 out[11] = 0;
897 out[12..16].copy_from_slice(&src_ip);
898 out[16..20].copy_from_slice(&dst_ip);
899
900 let ip_checksum = super::ipv4_header_checksum(&out[0..20]);
901 out[10] = (ip_checksum >> 8) as u8;
902 out[11] = ip_checksum as u8;
903
904 out[20] = (src_port >> 8) as u8;
905 out[21] = src_port as u8;
906 out[22] = (dst_port >> 8) as u8;
907 out[23] = dst_port as u8;
908 out[24] = (seq >> 24) as u8;
909 out[25] = (seq >> 16) as u8;
910 out[26] = (seq >> 8) as u8;
911 out[27] = seq as u8;
912 out[28] = (ack >> 24) as u8;
913 out[29] = (ack >> 16) as u8;
914 out[30] = (ack >> 8) as u8;
915 out[31] = ack as u8;
916 out[32] = ((tcp_hdr_len / 4) << 4) as u8;
917 out[33] = flags;
918 out[34] = 0x20;
948 out[35] = 0x00;
949 out[36] = 0x00;
950 out[37] = 0x00;
951 out[38] = 0x00;
952 out[39] = 0x00;
953
954 let mut payload_start = 40;
955 if opt_len > 0 {
956 out[40] = 2;
957 out[41] = 4;
958 out[42] = 0x05;
959 out[43] = 0xB4;
960 payload_start += 4;
961 }
962 let payload_end = payload_start + payload.len();
963 out[payload_start..payload_end].copy_from_slice(payload);
964
965 let mut tcp_csum_buf = alloc::vec![0u8; 12 + tcp_len];
966 tcp_csum_buf[0..4].copy_from_slice(&src_ip);
967 tcp_csum_buf[4..8].copy_from_slice(&dst_ip);
968 tcp_csum_buf[8] = 0;
969 tcp_csum_buf[9] = 6;
970 tcp_csum_buf[10] = ((tcp_len >> 8) & 0xFF) as u8;
971 tcp_csum_buf[11] = (tcp_len & 0xFF) as u8;
972 tcp_csum_buf[12..12 + tcp_len].copy_from_slice(&out[20..total_len]);
973
974 let csum = super::ipv4_header_checksum(&tcp_csum_buf);
975 out[36] = (csum >> 8) as u8;
976 out[37] = csum as u8;
977
978 let sent = super::arp::transmit_nic_ipv4_packet(&out[..total_len])?;
979 Ok(sent)
980}
981
982fn tcp_state_name(state: super::TcpState) -> &'static str {
983 super::tcp_state::tcp_state_name(state)
984}