Commit 04c50739 authored by nanamicat's avatar nanamicat

fix

parent 66048b4c
/import/
/target/
\ No newline at end of file
/target/
/.idea/
\ No newline at end of file
......@@ -25,84 +25,6 @@ dependencies = [
"syn",
]
[[package]]
name = "atomic-waker"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
[[package]]
name = "autocfg"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]]
name = "average"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75aacce61912644dbb732271789748142bc4bf7ce6382d67bb26850516b7a391"
dependencies = [
"easy-cast",
"float-ord",
"num-traits",
]
[[package]]
name = "axum"
version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f"
dependencies = [
"async-trait",
"axum-core",
"bytes",
"futures-util",
"http",
"http-body",
"http-body-util",
"hyper",
"hyper-util",
"itoa",
"matchit",
"memchr",
"mime",
"percent-encoding",
"pin-project-lite",
"rustversion",
"serde",
"serde_json",
"serde_path_to_error",
"serde_urlencoded",
"sync_wrapper",
"tokio",
"tower",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "axum-core"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199"
dependencies = [
"async-trait",
"bytes",
"futures-util",
"http",
"http-body",
"http-body-util",
"mime",
"pin-project-lite",
"rustversion",
"sync_wrapper",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "bincode"
version = "2.0.1"
......@@ -153,12 +75,6 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "cfg_aliases"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
name = "config"
version = "0.15.19"
......@@ -217,21 +133,6 @@ dependencies = [
"libc",
]
[[package]]
name = "crossbeam-queue"
version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "crunchy"
version = "0.2.4"
......@@ -248,19 +149,6 @@ dependencies = [
"typenum",
]
[[package]]
name = "dashmap"
version = "5.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
dependencies = [
"cfg-if",
"hashbrown 0.14.5",
"lock_api",
"once_cell",
"parking_lot_core",
]
[[package]]
name = "digest"
version = "0.10.7"
......@@ -280,15 +168,6 @@ dependencies = [
"const-random",
]
[[package]]
name = "easy-cast"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23f40539c229fc2e4674bdecdf24bfcc2cb83631ca911c78a035fa9f2381c32b"
dependencies = [
"libm",
]
[[package]]
name = "encoding_rs"
version = "0.8.35"
......@@ -309,27 +188,12 @@ dependencies = [
"typeid",
]
[[package]]
name = "float-ord"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ce81f49ae8a0482e4c55ea62ebbd7e5a686af544c00b9d090bba3ff9be97b3d"
[[package]]
name = "foldhash"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]]
name = "form_urlencoded"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
dependencies = [
"percent-encoding",
]
[[package]]
name = "futures"
version = "0.3.31"
......@@ -464,94 +328,6 @@ dependencies = [
"hashbrown 0.15.5",
]
[[package]]
name = "http"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a"
dependencies = [
"bytes",
"itoa",
]
[[package]]
name = "http-body"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
dependencies = [
"bytes",
"http",
]
[[package]]
name = "http-body-util"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a"
dependencies = [
"bytes",
"futures-core",
"http",
"http-body",
"pin-project-lite",
]
[[package]]
name = "http-range-header"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9171a2ea8a68358193d15dd5d70c1c10a2afc3e7e4c5bc92bc9f025cebd7359c"
[[package]]
name = "httparse"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
[[package]]
name = "httpdate"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "hyper"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11"
dependencies = [
"atomic-waker",
"bytes",
"futures-channel",
"futures-core",
"http",
"http-body",
"httparse",
"httpdate",
"itoa",
"pin-project-lite",
"pin-utils",
"smallvec",
"tokio",
]
[[package]]
name = "hyper-util"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f"
dependencies = [
"bytes",
"futures-core",
"http",
"http-body",
"hyper",
"pin-project-lite",
"tokio",
"tower-service",
]
[[package]]
name = "itoa"
version = "1.0.15"
......@@ -575,12 +351,6 @@ version = "0.2.178"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
[[package]]
name = "libm"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
[[package]]
name = "lock_api"
version = "0.4.14"
......@@ -590,40 +360,12 @@ dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
[[package]]
name = "matchit"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
[[package]]
name = "memchr"
version = "2.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
[[package]]
name = "mime"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "mime_guess"
version = "2.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e"
dependencies = [
"mime",
"unicase",
]
[[package]]
name = "mio"
version = "1.1.1"
......@@ -635,76 +377,6 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "netlink-packet-core"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3463cbb78394cb0141e2c926b93fc2197e473394b761986eca3b9da2c63ae0f4"
dependencies = [
"paste",
]
[[package]]
name = "netlink-packet-route"
version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ea06a7cec15a9df94c58bddc472b1de04ca53bd32e72da7da2c5dd1c3885edc"
dependencies = [
"bitflags",
"libc",
"log",
"netlink-packet-core",
]
[[package]]
name = "netlink-proto"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b65d130ee111430e47eed7896ea43ca693c387f097dd97376bffafbf25812128"
dependencies = [
"bytes",
"futures",
"log",
"netlink-packet-core",
"netlink-sys",
"thiserror 2.0.17",
]
[[package]]
name = "netlink-sys"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16c903aa70590cb93691bf97a767c8d1d6122d2cc9070433deb3bbf36ce8bd23"
dependencies = [
"bytes",
"futures",
"libc",
"log",
"tokio",
]
[[package]]
name = "nix"
version = "0.30.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
dependencies = [
"bitflags",
"cfg-if",
"cfg_aliases",
"libc",
]
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
"libm",
]
[[package]]
name = "once_cell"
version = "1.21.3"
......@@ -744,24 +416,12 @@ dependencies = [
"windows-link",
]
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "pathdiff"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3"
[[package]]
name = "percent-encoding"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
[[package]]
name = "pest"
version = "2.8.4"
......@@ -836,29 +496,16 @@ dependencies = [
]
[[package]]
name = "railgun-routing-client"
name = "railgun-routing-server"
version = "0.1.0"
dependencies = [
"anyhow",
"average",
"axum",
"bincode",
"bytes",
"config",
"crossbeam-queue",
"dashmap",
"futures",
"http",
"httparse",
"once_cell",
"rtnetlink",
"serde",
"serde_json",
"tokio",
"tokio-stream",
"tokio-util",
"tower-http",
"tracing",
]
[[package]]
......@@ -884,24 +531,6 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "rtnetlink"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ee907fdcec9200d13b9cdb64dfc8179cb4ac16ead6ae0ac76333dc41981fc"
dependencies = [
"futures-channel",
"futures-util",
"log",
"netlink-packet-core",
"netlink-packet-route",
"netlink-proto",
"netlink-sys",
"nix",
"thiserror 1.0.69",
"tokio",
]
[[package]]
name = "rust-ini"
version = "0.21.3"
......@@ -912,12 +541,6 @@ dependencies = [
"ordered-multimap",
]
[[package]]
name = "rustversion"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "ryu"
version = "1.0.20"
......@@ -985,17 +608,6 @@ dependencies = [
"serde_core",
]
[[package]]
name = "serde_path_to_error"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457"
dependencies = [
"itoa",
"serde",
"serde_core",
]
[[package]]
name = "serde_spanned"
version = "1.0.3"
......@@ -1005,18 +617,6 @@ dependencies = [
"serde_core",
]
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
dependencies = [
"form_urlencoded",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "sha2"
version = "0.10.9"
......@@ -1070,52 +670,6 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "sync_wrapper"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
[[package]]
name = "thiserror"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
"thiserror-impl 1.0.69",
]
[[package]]
name = "thiserror"
version = "2.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
dependencies = [
"thiserror-impl 2.0.17",
]
[[package]]
name = "thiserror-impl"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "thiserror-impl"
version = "2.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tiny-keccak"
version = "2.0.2"
......@@ -1153,30 +707,6 @@ dependencies = [
"syn",
]
[[package]]
name = "tokio-stream"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047"
dependencies = [
"futures-core",
"pin-project-lite",
"tokio",
]
[[package]]
name = "tokio-util"
version = "0.7.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"pin-project-lite",
"tokio",
]
[[package]]
name = "toml"
version = "0.9.8"
......@@ -1208,91 +738,6 @@ dependencies = [
"winnow",
]
[[package]]
name = "tower"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
dependencies = [
"futures-core",
"futures-util",
"pin-project-lite",
"sync_wrapper",
"tokio",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tower-http"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5"
dependencies = [
"bitflags",
"bytes",
"futures-util",
"http",
"http-body",
"http-body-util",
"http-range-header",
"httpdate",
"mime",
"mime_guess",
"percent-encoding",
"pin-project-lite",
"tokio",
"tokio-util",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tower-layer"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
[[package]]
name = "tower-service"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
[[package]]
name = "tracing"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647"
dependencies = [
"log",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tracing-core"
version = "0.1.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c"
dependencies = [
"once_cell",
]
[[package]]
name = "typeid"
version = "1.0.3"
......@@ -1311,12 +756,6 @@ version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
[[package]]
name = "unicase"
version = "2.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
[[package]]
name = "unicode-ident"
version = "1.0.22"
......
[package]
name = "railgun-routing-client"
name = "railgun-routing-server"
version = "0.1.0"
edition = "2024"
......@@ -7,25 +7,9 @@ edition = "2024"
[dependencies]
config = "0.15.19"
average = "0.16.0"
serde_json = "1.0.145"
serde = { version = "1.0.228", features = ["derive", "rc"] }
# serde_derive = "1.0" # Included in serde features
tokio = { version = "1.48", features = ["full"] }
rtnetlink = "0.19.0"
anyhow = "1.0.100"
# bincode = { version = "2.0.1", features = ["derive"] } # Removed as we use JSON
axum = "0.7"
tower-http = { version = "0.5", features = ["fs", "cors", "trace"] }
tracing = "0.1"
once_cell = "1.19"
crossbeam-queue = "0.3"
dashmap = "5.5"
bincode = "2.0.1"
tokio-util = { version = "0.7.17", features = ["codec"] }
bytes = "1.11.0"
http = "1.4.0"
tokio-stream = "0.1.17"
futures = "0.3.31"
httparse = "1.10.1" # For concurrent map access
// use crate::protocol::PeerQuality;
// use crate::router::GlobalState;
// use axum::{Router as AxumRouter, extract::State, response::Json, routing::get};
// use serde::Serialize;
// use std::sync::Arc;
//
//
// struct Status {
// tick: u64,
// last_update_ms: u64,
// msg: String,
// }
//
// // Response structs
// #[derive(Serialize)]
// struct RouterStateResponse {
// id: u8,
// peers: std::collections::HashMap<u8, PeerQuality>,
// via: std::collections::HashMap<u8, u8>,
// }
//
// #[derive(Serialize)]
// struct RouterConfigResponse {
// id: u8,
// name: String,
// location: String,
// host: String,
// #[serde(rename = "sshPort")]
// ssh_port: u16,
// user: String,
// }
//
// =
// // serde_json::from_str(&std::fs::read_to_string("../import/connections.json")?)?;
// // let mut routers: BTreeMap<u8, Router>
//
// pub fn app(state: Arc<(&BTreeMap<u8, BTreeMap<u8, ConnectionData>>>)) -> AxumRouter {
// AxumRouter::new()
// .route("/api/state", get(get_state))
// .route("/api/routers", get(get_routers))
// .route("/api/connections", get(get_connections))
// .with_state(state)
// }
//
// async fn get_state(State(state): State<Arc<GlobalState>>) -> Json<Vec<RouterStateResponse>> {
// let mut result = Vec::new();
// // iterate routers
// for router_lock in &state.routers {
// let router = router_lock.read().await;
// result.push(RouterStateResponse {
// id: router.id,
// peers: router.peers.clone(),
// via: router.via.clone(),
// });
// }
// Json(result)
// }
//
// async fn get_routers(State(state): State<Arc<GlobalState>>) -> Json<Vec<RouterConfigResponse>> {
// let mut result = Vec::new();
// for router_lock in &state.routers {
// let router = router_lock.read().await;
// result.push(RouterConfigResponse {
// id: router.config.id,
// name: router.config.name.clone(),
// location: router.config.location.clone(),
// host: router.config.host.clone(),
// ssh_port: router.config.ssh_port,
// user: router.config.user.clone(),
// });
// }
// Json(result)
// }
//
// async fn get_connections(
// State(state): State<Arc<GlobalState>>,
// ) -> Json<std::collections::HashMap<u8, std::collections::HashMap<u8, crate::router::ConnectionData>>>
// {
// Json(state.connections.clone())
// }
use bytes::{Buf, BufMut, BytesMut};
use http::{Response, Version};
use std::io;
use std::net::SocketAddr;
use tokio::net::{TcpListener, TcpStream, ToSocketAddrs};
use tokio_stream::{StreamExt, StreamMap};
use tokio_util::codec::{Decoder, Encoder, Framed};
pub struct HttpMonitor {
listener: TcpListener,
connections: StreamMap<SocketAddr, Framed<TcpStream, SimpleHttpCodec>>,
}
impl HttpMonitor {
pub async fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<Self> {
Ok(Self {
listener: TcpListener::bind(addr).await?,
connections: StreamMap::new(),
})
}
/// 在 select! 中调用的核心方法
pub async fn next_request(&mut self) -> io::Result<(http::Request<()>, Framed<TcpStream, SimpleHttpCodec>)> {
loop {
tokio::select! {
// 1. 接受新连接
Ok((stream, addr)) = self.listener.accept() => {
// 优化:开启 TCP NoDelay,对 HTTP 这种请求-响应模式很重要,减少延迟
let _ = stream.set_nodelay(true);
self.connections.insert(addr, Framed::new(stream, SimpleHttpCodec));
}
// 2. 处理已有连接的数据
// next() 会轮询所有连接,一旦有任何一个解析出完整的 HTTP 包,就返回
res = self.connections.next(), if !self.connections.is_empty() => {
match res {
Some((addr, Ok(req))) => {
// 暂时移除连接,将其所有权移交给 Request 对象
return Ok((req, self.connections.remove(&addr).unwrap()));
}
Some((addr, Err(_))) => {
// 出错或断开,清理
self.connections.remove(&addr);
}
None => {}
}
}
}
}
}
}
// --- 底层 Codec (不需要关心细节) ---
const MAX_HEADER_SIZE: usize = 8192; // 8KB header limit
pub struct SimpleHttpCodec;
impl Decoder for SimpleHttpCodec {
type Item = http::Request<()>;
type Error = io::Error;
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
// 安全检查:防止 Payload 过大导致的 OOM 攻击
if src.len() > MAX_HEADER_SIZE {
return Err(io::Error::new(io::ErrorKind::InvalidData, "Request too large"));
}
// httparse 需要预分配一些 slot 来存放 headers
// 对于简单的监控接口,16 个 header 足够了,甚至不需要分配堆内存
let mut headers = [httparse::EMPTY_HEADER; 16];
let mut req = httparse::Request::new(&mut headers);
// httparse::Request::parse 尝试从字节切片中解析
match req.parse(src) {
// 1. 解析成功 (Complete)
Ok(httparse::Status::Complete(bytes_parsed)) => {
// 获取我们需要的数据
let method = req.method.unwrap_or("GET");
let path = req.path.unwrap_or("/");
let mut builder = http::Request::builder().method(method).uri(path).version(Version::HTTP_11);
for header in req.headers {
builder = builder.header(header.name, header.value);
}
// !!! 关键步骤 !!!
// 告诉 BytesMut 我们消耗了多少字节,把这些字节从缓存中移除
src.advance(bytes_parsed);
Ok(Some(builder.body(()).unwrap()))
}
// 2. 数据还没发完 (Partial)
// 比如只发了 "GET /sta",还没有发 "\r\n"
// 返回 Ok(None) 告诉 Framed:继续读 TCP,读到了再叫我
Ok(httparse::Status::Partial) => Ok(None),
// 3. 解析错误 (比如发了乱码)
Err(e) => Err(io::Error::new(io::ErrorKind::InvalidData, e.to_string())),
}
}
}
impl Encoder<Response<String>> for SimpleHttpCodec {
type Error = io::Error;
fn encode(&mut self, item: Response<String>, dst: &mut BytesMut) -> Result<(), Self::Error> {
// 1. 写入 Status Line (例如: HTTP/1.1 200 OK)
// 注意:http crate 的 Version debug 输出就是 "HTTP/1.1" 这种格式
let version = match item.version() {
Version::HTTP_11 => "HTTP/1.1",
Version::HTTP_10 => "HTTP/1.0",
_ => "HTTP/1.1",
};
// 预估一个容量以减少内存重新分配
let body_bytes = item.body().as_bytes();
dst.reserve(256 + body_bytes.len());
// 使用 writer 避免中间字符串分配
use std::io::Write;
let mut writer = dst.writer();
// 1. 写入 Status Line
// write! 宏可以直接写入 BytesMut,比 format! 更高效
let _ = write!(writer, "{} {}\r\n", version, item.status());
// 2. 写入 Headers
for (key, value) in item.headers() {
let _ = writer.write(key.as_str().as_bytes());
let _ = writer.write(b": ");
let _ = writer.write(value.as_bytes());
let _ = writer.write(b"\r\n");
}
// 3. 自动补充 Headers
if !item.headers().contains_key("content-length") {
let _ = write!(writer, "content-length: {}\r\n", body_bytes.len());
}
if !item.headers().contains_key("connection") {
let _ = writer.write(b"connection: close\r\n");
}
// 4. Header 结束
let _ = writer.write(b"\r\n");
// 5. Body
let _ = writer.write(body_bytes);
Ok(())
}
}
use crate::data::{ConnectionData, RouterData};
use crate::http::HttpMonitor;
use crate::protocol::{Change, Report};
use crate::router::Router;
use crate::settings::{Settings, TIMEOUT};
use ::config::Config;
use ::http::Response;
use anyhow::Result;
use ::config::Config;
use config::{Environment, File};
use futures::SinkExt;
use std::collections::BTreeMap;
use tokio::net::UdpSocket;
use tokio::select;
use tokio::time::{Duration, interval};
use tokio::time::{interval, Duration};
mod api;
mod data;
mod gateway_group;
mod http;
mod protocol;
mod quality;
mod router;
......@@ -68,10 +63,7 @@ async fn main() -> Result<()> {
let socket = UdpSocket::bind(config.udp_bind).await?;
println!("UDP listening on {}", config.udp_bind);
let mut buf = [0u8; 65535]; // Max UDP size
let mut http = HttpMonitor::bind(config.http_bind).await?;
println!("HTTP listening on {}", config.http_bind);
let mut buf = [0u8; u16::MAX as usize]; // Max UDP size
let mut interval = interval(Duration::from_secs(1));
......@@ -85,7 +77,10 @@ async fn main() -> Result<()> {
bincode::decode_from_slice::<Report, _>(&buf[..len], bincode::config::standard())
&& let Some(router) = routers.get_mut(&report.id)
{
router.on_message(report,&socket, addr, &mut updating);
if let Some(change) = router.on_message(report, addr, &mut updating) {
let len = bincode::encode_into_slice(change, &mut buf, bincode::config::standard())?;
let _ = socket.send_to(&buf[..len], addr).await;
}
}
}
......@@ -93,7 +88,8 @@ async fn main() -> Result<()> {
if updating.router_id != 0 {
let router = routers.get_mut(&updating.router_id).expect("updating router_id should exist");
if now.duration_since(router.time) < TIMEOUT {
let _ = router.send(&updating.change, &socket, router.addr.unwrap()); // updating 期间 addr 一定存在
let len = bincode::encode_into_slice(&updating.change, &mut buf, bincode::config::standard())?;
let _ = socket.send_to(&buf[..len], router.addr.unwrap()).await;
} else {
router.offline();
router.finish(&mut updating);
......@@ -105,25 +101,11 @@ async fn main() -> Result<()> {
router.offline();
}
}
if let Some(result) = routers.values().find_map(|r|r.update(&routers, &connections)) {
updating = result;
let router = routers.get_mut(&updating.router_id).expect("updating router_id should exist");
let _ = router.send(&updating.change, &socket, router.addr.unwrap());
}
}
}
result = http.next_request() => {
if let Ok((req, mut connection)) = result {
if req.uri().path() == "/status" {
let json = serde_json::to_string(&connections)?;
let response = Response::builder()
.header("Content-Type", "application/json")
.body(json)?;
tokio::spawn(async move {
connection.send(response).await
});
if let Some((router, change)) = routers.values().find_map(|r|r.update(&routers, &connections).map(|change|(r,change))) {
updating.router_id = router.id;
updating.change = change;
let len = bincode::encode_into_slice(&updating.change, &mut buf, bincode::config::standard())?;
let _ = socket.send_to(&buf[..len], router.addr.unwrap()).await;
}
}
}
......
use std::collections::BTreeMap;
use bincode::{Decode, Encode};
#[derive(Encode, Decode)]
pub struct Hello {
pub time: u16,
}
use std::collections::BTreeMap;
#[derive(Encode, Decode)]
pub struct Report {
......
use crate::protocol::PeerQuality;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default)]
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct Quality {
pub delay: i32,
pub jitter: u32,
......@@ -35,7 +35,7 @@ impl Quality {
}
}
fn default() -> Self {
pub(crate) fn default() -> Self {
Self {
delay: 0,
jitter: 0,
......
......@@ -5,7 +5,6 @@ use crate::settings::THROTTLE;
use crate::UpdatingState;
use std::collections::BTreeMap;
use std::net::SocketAddr;
use tokio::net::UdpSocket;
use tokio::time::Instant;
pub struct Router {
......@@ -68,7 +67,7 @@ impl Router {
self.time = Instant::now();
}
pub fn on_message(&mut self, data: Report, socket: &UdpSocket, addr: SocketAddr, updating: &mut UpdatingState) {
pub fn on_message(&mut self, data: Report, addr: SocketAddr, updating: &mut UpdatingState) -> Option<Change> {
// self.addr None (+不满足上线条件) => 客户端不认为自己新上线,但是服务端不认识,立即发送 rst 当前状态,暂不承认上线
// syn + peer => 新上线的客户端,立即发送 rst 当前状态,暂不承认上线,有 updating 解除 updating, addr=none
// syn + no peer + 正确的 ack 号 => 确认了关于 rst 的指令,上线
......@@ -78,50 +77,41 @@ impl Router {
match (self.addr != None, data.syn, data.peers.len() != 0, data.ack == self.seq.wrapping_add(1)) {
(false, true, false, true) => {
self.online(addr);
None
}
(false, _, _, _) | (_, true, true, _) => {
self.offline();
self.finish(updating);
let change = Change {
Some(Change {
seq: self.seq,
via: self.via.clone(),
plan: self.plan.clone(),
rst: true,
};
self.send(&change, socket, addr);
})
}
(true, false, true, true) => {
self.online(addr);
for (current, new) in self.peers.values_mut().zip(data.peers) {
*current = new
}
None
}
(true, false, false, true) => {
self.online(addr);
self.finish(updating);
None
}
_ => {}
_ => None,
}
}
pub async fn change(&self, message: Change, updating: &mut UpdatingState, socket: &UdpSocket) {
updating.router_id = self.id;
updating.change = message;
self.send(&updating.change, socket, self.addr.unwrap()).await;
}
pub fn finish(&self, updating: &mut UpdatingState) {
if updating.router_id == self.id {
updating.router_id = 0;
}
}
pub async fn send(&self, message: &Change, socket: &UdpSocket, addr: SocketAddr) {
let buf = bincode::encode_to_vec(message, bincode::config::standard()).unwrap();
socket.send_to(&buf, addr).await;
}
pub fn update(&self, routers: &BTreeMap<u8, Router>, connections: &BTreeMap<u8, BTreeMap<u8, ConnectionData>>) -> Option<UpdatingState> {
pub fn update(&self, routers: &BTreeMap<u8, Router>, connections: &BTreeMap<u8, BTreeMap<u8, ConnectionData>>) -> Option<Change> {
if self.addr.is_none() {
return None;
}
......@@ -145,14 +135,11 @@ impl Router {
}
if changed_via.len() > 0 {
Some(UpdatingState {
router_id: self.id,
change: Change {
seq: self.seq,
rst: false,
via: changed_via,
plan: BTreeMap::new(),
},
Some(Change {
seq: self.seq,
rst: false,
via: changed_via,
plan: BTreeMap::new(),
})
} else {
None
......@@ -163,7 +150,7 @@ impl Router {
assert!(self != to);
assert!(self != via);
let mut result = Quality::default();
let mut result: Quality = Quality::default();
let mut route = vec![self, via];
let mut current = self;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment