feat: 握手写完了
This commit is contained in:
165
src/lib.rs
165
src/lib.rs
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user