Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
R
railgun-routing-server
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Railgun
railgun-routing-server
Commits
04c50739
Commit
04c50739
authored
Dec 16, 2025
by
nanamicat
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix
parent
66048b4c
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
35 additions
and
878 deletions
+35
-878
server/.gitignore
server/.gitignore
+2
-1
server/Cargo.lock
server/Cargo.lock
+1
-562
server/Cargo.toml
server/Cargo.toml
+1
-17
server/src/api.rs
server/src/api.rs
+0
-80
server/src/http.rs
server/src/http.rs
+0
-151
server/src/main.rs
server/src/main.rs
+14
-32
server/src/protocol.rs
server/src/protocol.rs
+1
-6
server/src/quality.rs
server/src/quality.rs
+2
-2
server/src/router.rs
server/src/router.rs
+14
-27
No files found.
server/.gitignore
View file @
04c50739
/import/
/target/
\ No newline at end of file
/target/
/.idea/
\ No newline at end of file
server/Cargo.lock
View file @
04c50739
...
...
@@ -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"
...
...
server/Cargo.toml
View file @
04c50739
[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
server/src/api.rs
deleted
100644 → 0
View file @
66048b4c
// 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())
// }
server/src/http.rs
deleted
100644 → 0
View file @
66048b4c
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
(())
}
}
server/src/main.rs
View file @
04c50739
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
;
}
}
}
...
...
server/src/protocol.rs
View file @
04c50739
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
{
...
...
server/src/quality.rs
View file @
04c50739
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
,
...
...
server/src/router.rs
View file @
04c50739
...
...
@@ -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
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment