feat: 握手写完了

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

1
.gitignore vendored
View File

@ -1 +1,2 @@
/target
/joh_git

627
Cargo.lock generated
View File

@ -2,6 +2,633 @@
# It is not intended for manual editing.
version = 4
[[package]]
name = "arrayvec"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
name = "autocfg"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c"
dependencies = [
"byteorder",
"iovec",
]
[[package]]
name = "cc"
version = "1.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c3d1b2e905a3a7b00a6141adb0e4c0bb941d11caf55349d863942a1cc44e3c9"
dependencies = [
"shlex",
]
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
dependencies = [
"bitflags",
]
[[package]]
name = "crossbeam-deque"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c20ff29ded3204c5106278a81a38f4b482636ed4fa1e6cfbeef193291beb29ed"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
"maybe-uninit",
]
[[package]]
name = "crossbeam-epoch"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"lazy_static",
"maybe-uninit",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-queue"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570"
dependencies = [
"cfg-if",
"crossbeam-utils",
"maybe-uninit",
]
[[package]]
name = "crossbeam-utils"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
dependencies = [
"autocfg",
"cfg-if",
"lazy_static",
]
[[package]]
name = "etherparse"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b14e4ac78394e3ea04edbbc412099cf54f2f52ded51efb79c466a282729399d2"
dependencies = [
"arrayvec",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
dependencies = [
"bitflags",
"fuchsia-zircon-sys",
]
[[package]]
name = "fuchsia-zircon-sys"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
[[package]]
name = "futures"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678"
[[package]]
name = "hermit-abi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "iovec"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
dependencies = [
"libc",
]
[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
dependencies = [
"winapi 0.2.8",
"winapi-build",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.2.169"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]]
name = "lock_api"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75"
dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f"
[[package]]
name = "maybe-uninit"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
[[package]]
name = "memoffset"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa"
dependencies = [
"autocfg",
]
[[package]]
name = "mio"
version = "0.6.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4"
dependencies = [
"cfg-if",
"fuchsia-zircon",
"fuchsia-zircon-sys",
"iovec",
"kernel32-sys",
"libc",
"log",
"miow",
"net2",
"slab",
"winapi 0.2.8",
]
[[package]]
name = "mio-uds"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0"
dependencies = [
"iovec",
"libc",
"mio",
]
[[package]]
name = "miow"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d"
dependencies = [
"kernel32-sys",
"net2",
"winapi 0.2.8",
"ws2_32-sys",
]
[[package]]
name = "net2"
version = "0.2.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac"
dependencies = [
"cfg-if",
"libc",
"winapi 0.3.9",
]
[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "parking_lot"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252"
dependencies = [
"lock_api",
"parking_lot_core",
"rustc_version",
]
[[package]]
name = "parking_lot_core"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda66b810a62be75176a80873726630147a5ca780cd33921e0b5709033e66b0a"
dependencies = [
"cfg-if",
"cloudabi",
"libc",
"redox_syscall",
"rustc_version",
"smallvec",
"winapi 0.3.9",
]
[[package]]
name = "redox_syscall"
version = "0.1.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
[[package]]
name = "rs-tcp"
version = "0.1.0"
dependencies = [
"etherparse",
"tun-tap",
]
[[package]]
name = "rustc_version"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
dependencies = [
"semver",
]
[[package]]
name = "scoped-tls"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28"
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "semver"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
dependencies = [
"semver-parser",
]
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]]
name = "smallvec"
version = "0.6.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0"
dependencies = [
"maybe-uninit",
]
[[package]]
name = "tokio"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6"
dependencies = [
"bytes",
"futures",
"mio",
"num_cpus",
"tokio-codec",
"tokio-current-thread",
"tokio-executor",
"tokio-fs",
"tokio-io",
"tokio-reactor",
"tokio-sync",
"tokio-tcp",
"tokio-threadpool",
"tokio-timer",
"tokio-udp",
"tokio-uds",
]
[[package]]
name = "tokio-codec"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b"
dependencies = [
"bytes",
"futures",
"tokio-io",
]
[[package]]
name = "tokio-core"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87b1395334443abca552f63d4f61d0486f12377c2ba8b368e523f89e828cffd4"
dependencies = [
"bytes",
"futures",
"iovec",
"log",
"mio",
"scoped-tls",
"tokio",
"tokio-executor",
"tokio-io",
"tokio-reactor",
"tokio-timer",
]
[[package]]
name = "tokio-current-thread"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e"
dependencies = [
"futures",
"tokio-executor",
]
[[package]]
name = "tokio-executor"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671"
dependencies = [
"crossbeam-utils",
"futures",
]
[[package]]
name = "tokio-fs"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4"
dependencies = [
"futures",
"tokio-io",
"tokio-threadpool",
]
[[package]]
name = "tokio-io"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674"
dependencies = [
"bytes",
"futures",
"log",
]
[[package]]
name = "tokio-reactor"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351"
dependencies = [
"crossbeam-utils",
"futures",
"lazy_static",
"log",
"mio",
"num_cpus",
"parking_lot",
"slab",
"tokio-executor",
"tokio-io",
"tokio-sync",
]
[[package]]
name = "tokio-sync"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee"
dependencies = [
"fnv",
"futures",
]
[[package]]
name = "tokio-tcp"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72"
dependencies = [
"bytes",
"futures",
"iovec",
"mio",
"tokio-io",
"tokio-reactor",
]
[[package]]
name = "tokio-threadpool"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89"
dependencies = [
"crossbeam-deque",
"crossbeam-queue",
"crossbeam-utils",
"futures",
"lazy_static",
"log",
"num_cpus",
"slab",
"tokio-executor",
]
[[package]]
name = "tokio-timer"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296"
dependencies = [
"crossbeam-utils",
"futures",
"slab",
"tokio-executor",
]
[[package]]
name = "tokio-udp"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82"
dependencies = [
"bytes",
"futures",
"log",
"mio",
"tokio-codec",
"tokio-io",
"tokio-reactor",
]
[[package]]
name = "tokio-uds"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab57a4ac4111c8c9dbcf70779f6fc8bc35ae4b2454809febac840ad19bd7e4e0"
dependencies = [
"bytes",
"futures",
"iovec",
"libc",
"log",
"mio",
"mio-uds",
"tokio-codec",
"tokio-io",
"tokio-reactor",
]
[[package]]
name = "tun-tap"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a477a4e9367c72ac875d23cd07ac99ffa932497d8428767fed0cfa27bbabe50"
dependencies = [
"cc",
"futures",
"libc",
"mio",
"tokio-core",
]
[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "ws2_32-sys"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
dependencies = [
"winapi 0.2.8",
"winapi-build",
]

View File

@ -4,3 +4,5 @@ version = "0.1.0"
edition = "2021"
[dependencies]
etherparse = "0.17.0"
tun-tap = "0.1.4"

69
examples/bin.rs Normal file
View File

@ -0,0 +1,69 @@
use rs_tcp::*;
use std::{
collections::{hash_map::Entry, HashMap},
io,
};
fn main() -> io::Result<()> {
let mut nic = tun_tap::Iface::without_packet_info("mytun0", tun_tap::Mode::Tun)?;
let mut buffer = vec![0; 1500];
// 保存所有连接对应的状态
let mut connections: HashMap<Quad, Connection> = HashMap::new();
loop {
let nbytes = nic.recv(&mut buffer).unwrap();
// 忽略非TCP数据包
match etherparse::Ipv4HeaderSlice::from_slice(&buffer) {
Ok(iph) => {
let src = iph.source_addr();
let dst = iph.destination_addr();
let proto = iph.protocol();
if proto != etherparse::IpNumber(0x06) {
continue;
}
match etherparse::TcpHeaderSlice::from_slice(&buffer[iph.slice().len()..nbytes]) {
Ok(tcph) => {
let payload_offset = iph.slice().len() + tcph.slice().len();
let mut payload = &buffer[payload_offset..nbytes];
let recv_quad = Quad {
src: (src, tcph.source_port()),
dst: (dst, tcph.destination_port()),
};
// 这里我们需要处理接收到的Tcp数据包
match connections.entry(recv_quad) {
Entry::Occupied(mut occupied_entry) => {
// 已经存在的连接
occupied_entry.get_mut().on_packet(iph, tcph, &payload);
},
Entry::Vacant(vacant_entry) => {
eprintln!(
"{}:{} -> {}:{} first handpacket syn: {}, seq: {}",
src,
tcph.source_port(),
dst,
tcph.destination_port(),
tcph.syn(),
tcph.sequence_number()
);
// 第一次接受的包
if let Some(c) = Connection::accept(&mut nic, iph, tcph)?{
vacant_entry.insert(c);
}
},
}
}
Err(e) => {
// 这不是一个TCP包 但是协议是TCP
eprintln!("ignoring weird packet: {:?}", e)
}
}
}
Err(_) => {
// 非IP标准包 忽略
continue;
}
};
}
Ok(())
}

7
readme.md Normal file
View File

@ -0,0 +1,7 @@
# rs-tcp
使用`rust`从底层网络链路实现`TCP`协议。
```bash
git remote add origin ssh://git@81.70.52.148:17022/asahi/rs-tcp.git
```

13
run.sh Executable file
View File

@ -0,0 +1,13 @@
#!/bin/bash
cargo build --example bin -r
ext=$?
if [[ $ext -ne 0 ]]; then
exit $ext
fi
sudo setcap cap_net_admin=eip ./target/release/examples/bin
./target/release/examples/bin &
pid=$!
sudo ip addr add 192.168.0.1/24 dev mytun0
sudo ip link set up dev mytun0
trap "kill $pid" INT TERM
wait $pid

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
}

3
tests/test.rs Normal file
View File

@ -0,0 +1,3 @@
#[cfg(test)]
mod tests {
}

0
work.dio Normal file
View File

84
work.md Normal file
View File

@ -0,0 +1,84 @@
# 开始
## 架构相关
### 依赖
- `tun_tap`: 创建低级网络设备的`crate`。
- `tshark`: `wireshark`的终端版本,安装`wireshark`自己会带。
- `etherparse`:用来解析`Tcp`和`IP`部分,并且提供了简便访问成员的封装。
### 传输链路
```mermaid
graph LR
A[TUN 接口] --> B(接收 IP 数据包);
B --> C{解析 IP 数据包};
C --> D[解析 TCP 头部];
D --> E[解析 TCP 数据体];
E --> F{你的逻辑处理};
F --> G[构造 IP 数据包];
G --> H[包装 TCP 结构];
H --> I(通过 TUN 发送);
I --> A;
style A fill:#f9f,stroke:#333,stroke-width:2px
style I fill:#3e89,stroke:#333,stroke-width:2px
style F fill:#05aa20,stroke:#333,stroke-width:2px
classDef process fill:#fffff,stroke:#ffff,stroke-width:1px
class C,D,E,G,H process
```
使用`TUN`模式进行低级网络传输。我们从`NIC`中获取到的是一个`IP`数据包。
具体流程,我们需要先解析这个`IP`数据包,然后解析其中的数据,将它作为`TCP`进行解析,最终我们将我们的数据包装为`IP`数据包,然后传输到`TUN`中,实现通信。
### 项目测试
我们在`example/bin.rs`中编写我们的启动测试主程序。`tests`目录主要是用来编写单元测试。
```bash
#!/bin/bash
cargo build --example bin -r
ext=$?
if [[ $ext -ne 0 ]]; then
exit $ext
fi
sudo setcap cap_net_admin=eip ./target/release/examples/bin # 赋予程序网络控制权限因为要创建tun接口
./target/release/examples/bin &
pid=$!
echo $pid
sudo ip addr add 192.168.0.1/24 dev mytun0 # 为我们的虚拟网卡绑定IP和掩码
sudo ip link set up dev mytun0 # 激活设备
trap "kill $pid" INT TERM
wait $pid
```
#### 抓包
```bash
sudo tshark -i mytun0 # 使用tshark监听mytun0设备
```
![image-20250216153930334](http://qiniu.asahichyan33.top/images/202502161539384.png)
## 开始编写
### 滑动窗口
**接受方滑动窗口**
![image-20250216204749732](http://qiniu.asahichyan33.top/images/202502162047809.png)
**发送方滑动窗口**
![image-20250216205251736](http://qiniu.asahichyan33.top/images/202502162052832.png)
---
当发送方接收到`ACK`后,会将`SND.UNA`向右移动。
而接收方接收到数据包后,会连续的将`RCV.NXT`向右移动,当遇到丢包,就会触发重传。
需要注意,发送方和接收方都存在窗口大小,当发送方发送消息时,同时收到`接收方滑动窗口大小`和`自身窗口大小`的限制。