feat: 握手写完了

This commit is contained in:
2025-02-16 22:38:06 +08:00
parent 1f5be02810
commit c5efd76773
10 changed files with 962 additions and 9 deletions

View File

@@ -1,14 +1,161 @@
pub fn add(left: u64, right: u64) -> u64 {
left + right
use std::{io, net::Ipv4Addr};
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub struct Quad {
pub src: (Ipv4Addr, u16),
pub dst: (Ipv4Addr, u16),
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Debug)]
pub enum State {
//Listen,
SynRcvd,
Estab,
FinWait1,
FinWait2,
TimeWait,
}
/// 对于一个连接,我们需要保存其中的状态上下文
/// 主要是滑动窗口部分的状态
pub struct RecvStateContext {
/// 下一个接受的seq值
pub nxt: u32,
/// 窗口大小
pub wnd: u16,
/// 由对方设置的初始接受序列号
pub irs: u32,
}
/// 一个连接既可以是接受方,也可以是发送方
/// 所以还需要一个结构保存发送时的状态信息
pub struct SendStateContext {
/// 滑动窗口的左边界指针
pub una: u32,
/// 存放下一个发送的seq值
pub nxt: u32,
/// 发送方窗口大小
pub wnd: u16,
/// 由自己设置的初始发送序列号
pub iss: u32,
}
#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
pub struct Connection {
state: State,
send: SendStateContext,
recv: RecvStateContext,
iph: etherparse::Ipv4Header
}
impl Connection {
pub fn on_packet<'a>(
&mut self,
iph: etherparse::Ipv4HeaderSlice<'a>,
tcph: etherparse::TcpHeaderSlice<'a>,
data: &'a [u8],
) {
// 需要检查是否接受
// SND.UNA < SEG.ACK <= SND.NXT
let ack = tcph.acknowledgment_number();
if !is_cyclic_order(self.send.una, ack, self.send.nxt.wrapping_add(1)){
eprintln!("不在可接受的范围!");
return;
}
match self.state {
State::SynRcvd => {
eprintln!("接收到第三次握手包!");
self.state = State::Estab;
},
State::Estab => {
// 握手结束
// TODO: 3:31:04 开始编写结束连接
},
State::FinWait1 => todo!(),
State::FinWait2 => todo!(),
State::TimeWait => todo!(),
}
}
pub fn accept<'a>(
nic: &'a mut tun_tap::Iface,
iph: etherparse::Ipv4HeaderSlice<'a>,
tcph: etherparse::TcpHeaderSlice<'a>,
) -> io::Result<Option<Self>> {
let mut buf = [0u8; 1500];
// 回应握手包
if !tcph.syn() {
// 只响应syn数据包
return Ok(None);
}
let iss = 0;
let wnd = 1024;
let mut c = Connection {
state: State::SynRcvd,
send: SendStateContext{
iss,
una: iss,
nxt: iss,
wnd,
},
recv: RecvStateContext{
irs: tcph.sequence_number(),
nxt: tcph.sequence_number() + 1,
wnd: tcph.window_size(),
},
iph: etherparse::Ipv4Header::new(
0,
64,
etherparse::IpNumber::TCP,
iph.destination(),
iph.source(),
).expect("create ip header fail!")
};
// 准备回复SYN+ACK 握手包
let mut syn_ack = etherparse::TcpHeader::new(
tcph.destination_port(),
tcph.source_port(),
c.send.iss,
10,
);
// acknowledgment_number 期望接收的下一个字节的序号
syn_ack.acknowledgment_number = tcph.sequence_number() + 1;
syn_ack.ack = true;
syn_ack.syn = true;
c.iph.set_payload_len(syn_ack.header_len());
let unwritten = {
let mut unwritten = &mut buf[..];
c.iph.write(&mut unwritten);
syn_ack.write(&mut unwritten);
unwritten.len()
};
nic.send(&buf[..unwritten])?;
Ok(Some(c))
}
}
/// 判断三个无符号整数是否按顺时针方向形成环形递增顺序
///
/// # 参数
/// - `start`:起始点
/// - `middle`:中间点(预期在 `start` 顺时针方向)
/// - `end`:终点(预期在 `middle` 顺时针方向)
///
/// # 返回值
/// 如果满足 `start → middle → end` 的顺时针递增顺序(允许溢出环绕),返回 `true`
fn is_cyclic_order(start: u32, middle: u32, end: u32) -> bool {
// 计算环形空间的最大半值(超过此值代表逆时针方向更短)
let half_max_value = u32::MAX / 2 + 1;
// 计算各点间的顺时针距离(考虑溢出)
let start_to_middle_distance = middle.wrapping_sub(start);
let middle_to_end_distance = end.wrapping_sub(middle);
let start_to_end_distance = end.wrapping_sub(start);
// 验证条件:
// 1. start到middle的顺时针距离不超过半环
// 2. middle到end的顺时针距离不超过半环
// 3. start到end的总距离等于前两段距离之和确保连续性
start_to_middle_distance <= half_max_value &&
middle_to_end_distance <= half_max_value &&
start_to_end_distance == start_to_middle_distance + middle_to_end_distance
}