mirror of https://github.com/ospab/ostp.git
feat: migrate TUN tunnel to native in-process smoltcp and refactor Android JNI layer
This commit is contained in:
parent
5722aaf2bc
commit
8ab49b84e9
|
|
@ -181,6 +181,12 @@ version = "0.22.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.11.1"
|
version = "2.11.1"
|
||||||
|
|
@ -211,12 +217,38 @@ version = "3.20.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
|
checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.11.1"
|
version = "1.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
|
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "c2rust-bitfields"
|
||||||
|
version = "0.18.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b43c3f07ab0ef604fa6f595aa46ec2f8a22172c975e186f6f5bf9829a3b72c41"
|
||||||
|
dependencies = [
|
||||||
|
"c2rust-bitfields-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "c2rust-bitfields-derive"
|
||||||
|
version = "0.18.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d3cbc102e2597c9744c8bd8c15915d554300601c91a079430d309816b0912545"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.62"
|
version = "1.2.62"
|
||||||
|
|
@ -324,7 +356,7 @@ dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -407,7 +439,48 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "defmt"
|
||||||
|
version = "0.3.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0963443817029b2024136fc4dd07a5107eb8f977eaf18fcd1fdeb11306b64ad"
|
||||||
|
dependencies = [
|
||||||
|
"defmt 1.1.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "defmt"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a6e524506490a1953d237cb87b1cfc1e46f88c18f10a22dfe0f507dc6bfc7f7f"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"defmt-macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "defmt-macros"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0a27770e9c8f719a79d8b638281f4d828f77d8fd61e0bd94451b9b85e576a0b"
|
||||||
|
dependencies = [
|
||||||
|
"defmt-parser",
|
||||||
|
"proc-macro-error2",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.117",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "defmt-parser"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror 2.0.18",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -438,7 +511,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -507,9 +580,15 @@ checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-sink"
|
||||||
|
version = "0.3.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-task"
|
name = "futures-task"
|
||||||
version = "0.3.32"
|
version = "0.3.32"
|
||||||
|
|
@ -589,6 +668,15 @@ dependencies = [
|
||||||
"polyval",
|
"polyval",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hash32"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.15.5"
|
version = "0.15.5"
|
||||||
|
|
@ -604,6 +692,16 @@ version = "0.17.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
|
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heapless"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
|
||||||
|
dependencies = [
|
||||||
|
"hash32",
|
||||||
|
"stable_deref_trait",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
|
|
@ -736,7 +834,7 @@ dependencies = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"log",
|
"log",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"windows-core",
|
"windows-core 0.62.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -878,6 +976,12 @@ dependencies = [
|
||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ioctl-sys"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8bd11f3a29434026f5ff98c730b668ba74b1033637b8817940b54d040696133c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipnet"
|
name = "ipnet"
|
||||||
version = "2.12.0"
|
version = "2.12.0"
|
||||||
|
|
@ -937,7 +1041,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264"
|
checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -976,6 +1080,16 @@ version = "0.2.185"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f"
|
checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libloading"
|
||||||
|
version = "0.8.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "litemap"
|
name = "litemap"
|
||||||
version = "0.8.2"
|
version = "0.8.2"
|
||||||
|
|
@ -994,6 +1108,12 @@ version = "0.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
|
checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "managed"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matchers"
|
name = "matchers"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
|
@ -1123,11 +1243,14 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha2",
|
"sha2",
|
||||||
|
"smoltcp",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
"tun",
|
||||||
"webpki-roots 0.26.11",
|
"webpki-roots 0.26.11",
|
||||||
|
"wintun 0.4.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1287,7 +1410,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
|
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-error-attr2"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-error2"
|
||||||
|
version = "2.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-error-attr2",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1536,7 +1681,7 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"rust-embed-utils",
|
"rust-embed-utils",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -1655,7 +1800,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1742,6 +1887,20 @@ version = "1.15.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smoltcp"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a1a996951e50b5971a2c8c0fa05a381480d70a933064245c4a223ddc87ccc97"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"byteorder",
|
||||||
|
"cfg-if",
|
||||||
|
"defmt 0.3.100",
|
||||||
|
"heapless",
|
||||||
|
"managed",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "snow"
|
name = "snow"
|
||||||
version = "0.9.6"
|
version = "0.9.6"
|
||||||
|
|
@ -1786,6 +1945,17 @@ version = "2.6.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.109"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.117"
|
version = "2.0.117"
|
||||||
|
|
@ -1814,7 +1984,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1843,7 +2013,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1854,7 +2024,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1934,7 +2104,7 @@ checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1947,6 +2117,19 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-util"
|
||||||
|
version = "0.7.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml"
|
name = "toml"
|
||||||
version = "0.5.11"
|
version = "0.5.11"
|
||||||
|
|
@ -1978,7 +2161,7 @@ version = "0.6.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68d6fdd9f81c2819c9a8b0e0cd91660e7746a8e6ea2ba7c6b2b057985f6bcb51"
|
checksum = "68d6fdd9f81c2819c9a8b0e0cd91660e7746a8e6ea2ba7c6b2b057985f6bcb51"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.11.1",
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http",
|
"http",
|
||||||
|
|
@ -2022,7 +2205,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2070,6 +2253,24 @@ version = "0.2.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tun"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0adb9992bbd5ca76f3847ed579ad4ee8defb2ec2eea918cceef17ccc66fa4fd4"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"bytes",
|
||||||
|
"futures-core",
|
||||||
|
"ioctl-sys",
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"thiserror 1.0.69",
|
||||||
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
|
"wintun 0.3.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.19.0"
|
version = "1.19.0"
|
||||||
|
|
@ -2243,7 +2444,7 @@ dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -2284,7 +2485,7 @@ version = "0.244.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
|
checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.11.1",
|
||||||
"hashbrown 0.15.5",
|
"hashbrown 0.15.5",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"semver",
|
"semver",
|
||||||
|
|
@ -2337,6 +2538,44 @@ dependencies = [
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows"
|
||||||
|
version = "0.51.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9"
|
||||||
|
dependencies = [
|
||||||
|
"windows-core 0.51.1",
|
||||||
|
"windows-targets 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
|
||||||
|
dependencies = [
|
||||||
|
"windows-core 0.52.0",
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-core"
|
||||||
|
version = "0.51.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-core"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-core"
|
name = "windows-core"
|
||||||
version = "0.62.2"
|
version = "0.62.2"
|
||||||
|
|
@ -2358,7 +2597,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2369,7 +2608,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2438,6 +2677,21 @@ dependencies = [
|
||||||
"windows_x86_64_msvc 0.42.2",
|
"windows_x86_64_msvc 0.42.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.48.5",
|
||||||
|
"windows_aarch64_msvc 0.48.5",
|
||||||
|
"windows_i686_gnu 0.48.5",
|
||||||
|
"windows_i686_msvc 0.48.5",
|
||||||
|
"windows_x86_64_gnu 0.48.5",
|
||||||
|
"windows_x86_64_gnullvm 0.48.5",
|
||||||
|
"windows_x86_64_msvc 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-targets"
|
name = "windows-targets"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
|
|
@ -2460,6 +2714,12 @@ version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
|
|
@ -2472,6 +2732,12 @@ version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
|
|
@ -2484,6 +2750,12 @@ version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
|
|
@ -2502,6 +2774,12 @@ version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
|
|
@ -2514,6 +2792,12 @@ version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
|
|
@ -2526,6 +2810,12 @@ version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
|
|
@ -2538,6 +2828,12 @@ version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
|
|
@ -2553,6 +2849,32 @@ dependencies = [
|
||||||
"toml",
|
"toml",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wintun"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29b83b0eca06dd125dbcd48a45327c708a6da8aada3d95a3f06db0ce4b17e0d4"
|
||||||
|
dependencies = [
|
||||||
|
"c2rust-bitfields",
|
||||||
|
"libloading",
|
||||||
|
"log",
|
||||||
|
"thiserror 1.0.69",
|
||||||
|
"windows 0.51.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wintun"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b3c8c8876c686f8a2d6376999ac1c9a24c74d2968551c9394f7e89127783685"
|
||||||
|
dependencies = [
|
||||||
|
"c2rust-bitfields",
|
||||||
|
"libloading",
|
||||||
|
"log",
|
||||||
|
"thiserror 1.0.69",
|
||||||
|
"windows 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wit-bindgen"
|
name = "wit-bindgen"
|
||||||
version = "0.51.0"
|
version = "0.51.0"
|
||||||
|
|
@ -2589,7 +2911,7 @@ dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"prettyplease",
|
"prettyplease",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
"wasm-metadata",
|
"wasm-metadata",
|
||||||
"wit-bindgen-core",
|
"wit-bindgen-core",
|
||||||
"wit-component",
|
"wit-component",
|
||||||
|
|
@ -2605,7 +2927,7 @@ dependencies = [
|
||||||
"prettyplease",
|
"prettyplease",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
"wit-bindgen-core",
|
"wit-bindgen-core",
|
||||||
"wit-bindgen-rust",
|
"wit-bindgen-rust",
|
||||||
]
|
]
|
||||||
|
|
@ -2617,7 +2939,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
|
checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bitflags",
|
"bitflags 2.11.1",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
|
|
@ -2681,7 +3003,7 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
"synstructure",
|
"synstructure",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -2702,7 +3024,7 @@ checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2722,7 +3044,7 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
"synstructure",
|
"synstructure",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -2762,7 +3084,7 @@ checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
||||||
|
|
@ -25,3 +25,11 @@ sha2 = "0.10.8"
|
||||||
base64 = "0.22.1"
|
base64 = "0.22.1"
|
||||||
webpki-roots = "0.26"
|
webpki-roots = "0.26"
|
||||||
rustls-pki-types = "1.7"
|
rustls-pki-types = "1.7"
|
||||||
|
smoltcp = { version = "0.11", default-features = false, features = ["std", "medium-ip", "proto-ipv4", "socket-tcp", "socket-udp"] }
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
|
wintun = "0.4"
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
|
tun = { version = "0.6", features = ["async"] }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,6 @@ pub async fn run_client_core(
|
||||||
let (ui_tx, mut ui_rx) = mpsc::channel(512);
|
let (ui_tx, mut ui_rx) = mpsc::channel(512);
|
||||||
let (cmd_tx, cmd_rx) = mpsc::channel(128);
|
let (cmd_tx, cmd_rx) = mpsc::channel(128);
|
||||||
let (shutdown_tx, shutdown_rx) = watch::channel(false);
|
let (shutdown_tx, shutdown_rx) = watch::channel(false);
|
||||||
let proxy_shutdown_rx = shutdown_tx.subscribe();
|
|
||||||
|
|
||||||
|
|
||||||
// Auto-connect on startup
|
// Auto-connect on startup
|
||||||
|
|
@ -248,26 +247,29 @@ pub async fn run_client_core(
|
||||||
});
|
});
|
||||||
|
|
||||||
let config_clone = config.clone();
|
let config_clone = config.clone();
|
||||||
let mut proxy_task = tokio::spawn(async move {
|
let (mut proxy_task, mut wintun_task) = if config.mode == "proxy" {
|
||||||
tunnel::run_local_proxy(
|
let proxy_shutdown_rx = shutdown_tx.subscribe();
|
||||||
config.local_proxy,
|
let t = tokio::spawn(async move {
|
||||||
config.ostp,
|
tunnel::run_local_proxy(
|
||||||
config.exclusions,
|
config.local_proxy,
|
||||||
config.debug,
|
config.ostp,
|
||||||
proxy_shutdown_rx,
|
config.exclusions,
|
||||||
proxy_events_tx,
|
config.debug,
|
||||||
client_msgs_rx,
|
proxy_shutdown_rx,
|
||||||
)
|
proxy_events_tx,
|
||||||
.await
|
client_msgs_rx,
|
||||||
});
|
)
|
||||||
|
.await
|
||||||
let wintun_shutdown_rx = shutdown_tx.subscribe();
|
});
|
||||||
let mut wintun_task = if config_clone.mode == "tun" {
|
(Some(t), None)
|
||||||
Some(tokio::spawn(async move {
|
} else if config.mode == "tun" {
|
||||||
tunnel::run_tun_tunnel(config_clone, wintun_shutdown_rx).await
|
let wintun_shutdown_rx = shutdown_tx.subscribe();
|
||||||
}))
|
let t = tokio::spawn(async move {
|
||||||
|
tunnel::run_tun_tunnel(config_clone, proxy_events_tx, client_msgs_rx, wintun_shutdown_rx).await
|
||||||
|
});
|
||||||
|
(None, Some(t))
|
||||||
} else {
|
} else {
|
||||||
None
|
(None, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Wait for either external shutdown OR any task to fail
|
// Wait for either external shutdown OR any task to fail
|
||||||
|
|
@ -280,7 +282,9 @@ pub async fn run_client_core(
|
||||||
let _ = shutdown_tx.send(true);
|
let _ = shutdown_tx.send(true);
|
||||||
res.map_err(|e| anyhow::anyhow!("Bridge task panicked: {}", e))??;
|
res.map_err(|e| anyhow::anyhow!("Bridge task panicked: {}", e))??;
|
||||||
}
|
}
|
||||||
res = &mut proxy_task => {
|
res = async {
|
||||||
|
if let Some(ref mut t) = proxy_task { t.await } else { std::future::pending().await }
|
||||||
|
} => {
|
||||||
let _ = shutdown_tx.send(true);
|
let _ = shutdown_tx.send(true);
|
||||||
res.map_err(|e| anyhow::anyhow!("Proxy task panicked: {}", e))??;
|
res.map_err(|e| anyhow::anyhow!("Proxy task panicked: {}", e))??;
|
||||||
}
|
}
|
||||||
|
|
@ -294,7 +298,9 @@ pub async fn run_client_core(
|
||||||
|
|
||||||
// Final cleanup: wait for tasks to finish
|
// Final cleanup: wait for tasks to finish
|
||||||
let _ = bridge_task.await;
|
let _ = bridge_task.await;
|
||||||
let _ = proxy_task.await;
|
if let Some(task) = proxy_task {
|
||||||
|
let _ = task.await;
|
||||||
|
}
|
||||||
if let Some(task) = wintun_task {
|
if let Some(task) = wintun_task {
|
||||||
let _ = task.await;
|
let _ = task.await;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,29 @@
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use tokio::sync::watch;
|
use tokio::sync::{mpsc, watch};
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
|
use crate::tunnel::{ProxyEvent, ProxyToClientMsg};
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
use crate::tunnel::tun_device::create_tun_device;
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
use crate::tunnel::smoltcp_stack::run_smoltcp_stack;
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
use std::net::ToSocketAddrs;
|
use std::net::ToSocketAddrs;
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
use std::process::{Command, Stdio, Child};
|
use std::process::Command;
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
use std::io::{BufRead, BufReader};
|
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
struct LinuxRouteGuard {
|
struct LinuxRouteGuard {
|
||||||
server_ip_str: String,
|
server_ip_str: String,
|
||||||
default_gw: String,
|
default_gw: String,
|
||||||
default_if: String,
|
default_if: String,
|
||||||
child: Option<Child>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
impl Drop for LinuxRouteGuard {
|
impl Drop for LinuxRouteGuard {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Some(mut child) = self.child.take() {
|
|
||||||
let _ = child.kill();
|
|
||||||
}
|
|
||||||
let cleanup_script = format!(
|
let cleanup_script = format!(
|
||||||
"ip route del 0.0.0.0/1 dev ostp_tun || true; \
|
"ip route del 0.0.0.0/1 dev ostp_tun || true; \
|
||||||
ip route del 128.0.0.0/1 dev ostp_tun || true; \
|
ip route del 128.0.0.0/1 dev ostp_tun || true; \
|
||||||
|
|
@ -39,39 +41,13 @@ impl Drop for LinuxRouteGuard {
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
pub async fn run_linux_tunnel(
|
pub async fn run_linux_tunnel(
|
||||||
config: crate::config::ClientConfig,
|
config: crate::config::ClientConfig,
|
||||||
|
proxy_events_tx: mpsc::Sender<ProxyEvent>,
|
||||||
|
client_msgs_rx: mpsc::UnboundedReceiver<(u16, ProxyToClientMsg)>,
|
||||||
mut shutdown: watch::Receiver<bool>,
|
mut shutdown: watch::Receiver<bool>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let debug = config.debug;
|
info!("Initializing built-in Linux TUN tunnel...");
|
||||||
if debug {
|
|
||||||
println!("[ostp] Initializing TUN tunnel...");
|
|
||||||
}
|
|
||||||
|
|
||||||
let exe = std::env::current_exe()?;
|
// 1. Pre-flight system checks
|
||||||
let dir = exe.parent().ok_or_else(|| anyhow!("failed to get binary directory"))?;
|
|
||||||
|
|
||||||
let mut tun2socks_exe = dir.join("tun2socks");
|
|
||||||
if !tun2socks_exe.exists() {
|
|
||||||
// Try system PATH via standard command check
|
|
||||||
let in_path = Command::new("which")
|
|
||||||
.arg("tun2socks")
|
|
||||||
.output()
|
|
||||||
.map(|o| o.status.success())
|
|
||||||
.unwrap_or(false);
|
|
||||||
|
|
||||||
if in_path {
|
|
||||||
tun2socks_exe = std::path::PathBuf::from("tun2socks");
|
|
||||||
} else {
|
|
||||||
return Err(anyhow!(
|
|
||||||
"CRITICAL: 'tun2socks' binary is missing!\n\
|
|
||||||
OSTP requires tun2socks for TUN mode on Linux. Please download the appropriate binary for your architecture from: \n\
|
|
||||||
https://github.com/xjasonlyu/tun2socks/releases \n\
|
|
||||||
and place it in the same directory as the ostp executable ({}), or install it globally in your PATH.",
|
|
||||||
dir.display()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1.5. Pre-flight system checks
|
|
||||||
let is_root = Command::new("id")
|
let is_root = Command::new("id")
|
||||||
.arg("-u")
|
.arg("-u")
|
||||||
.output()
|
.output()
|
||||||
|
|
@ -100,10 +76,7 @@ pub async fn run_linux_tunnel(
|
||||||
.ok_or_else(|| anyhow!("Could not resolve host IP for routing exclusion"))?;
|
.ok_or_else(|| anyhow!("Could not resolve host IP for routing exclusion"))?;
|
||||||
|
|
||||||
let server_ip_str = server_ip.to_string();
|
let server_ip_str = server_ip.to_string();
|
||||||
|
info!("Resolved server IP: {}", server_ip_str);
|
||||||
if debug {
|
|
||||||
println!("[ostp] Resolved server IP: {}", server_ip_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Detect current default gateway and interface
|
// 3. Detect current default gateway and interface
|
||||||
let route_output = Command::new("sh")
|
let route_output = Command::new("sh")
|
||||||
|
|
@ -114,7 +87,6 @@ pub async fn run_linux_tunnel(
|
||||||
let route_str = String::from_utf8_lossy(&route_output.stdout);
|
let route_str = String::from_utf8_lossy(&route_output.stdout);
|
||||||
let parts: Vec<&str> = route_str.split_whitespace().collect();
|
let parts: Vec<&str> = route_str.split_whitespace().collect();
|
||||||
|
|
||||||
// Expected: "default via 192.168.1.1 dev eth0 ..."
|
|
||||||
let mut default_gw = String::new();
|
let mut default_gw = String::new();
|
||||||
let mut default_if = String::new();
|
let mut default_if = String::new();
|
||||||
|
|
||||||
|
|
@ -131,95 +103,62 @@ pub async fn run_linux_tunnel(
|
||||||
return Err(anyhow!("Failed to discover active default gateway or network interface on Linux system."));
|
return Err(anyhow!("Failed to discover active default gateway or network interface on Linux system."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if debug {
|
info!("Default route: gateway={} interface={}", default_gw, default_if);
|
||||||
println!("[ostp] Default route: gateway={} interface={}", default_gw, default_if);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Setup commands (Using standard /1 routing trick for fail-proof overriding)
|
// Create the TunDevice inside the client process (creates the interface and sets up IP/MTU/Status)
|
||||||
let setup_script = format!(
|
let tun_dev = create_tun_device("ostp_tun", config.ostp.mtu)?;
|
||||||
"ip tuntap add name ostp_tun mode tun || true; \
|
|
||||||
ip link set dev ostp_tun mtu {}; \
|
|
||||||
ip addr add 10.1.0.2/24 dev ostp_tun || true; \
|
|
||||||
ip link set dev ostp_tun up; \
|
|
||||||
ip route add {} via {} dev {}; \
|
|
||||||
ip route add 1.1.1.1 via {} dev {}; \
|
|
||||||
ip route add 0.0.0.0/1 dev ostp_tun; \
|
|
||||||
ip route add 128.0.0.0/1 dev ostp_tun",
|
|
||||||
config.ostp.mtu, server_ip_str, default_gw, default_if,
|
|
||||||
default_gw, default_if
|
|
||||||
);
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
println!("[ostp] Executing Linux network config: {}", setup_script);
|
|
||||||
}
|
|
||||||
|
|
||||||
let out = Command::new("sh")
|
|
||||||
.args(["-c", &setup_script])
|
|
||||||
.output()?;
|
|
||||||
|
|
||||||
if !out.status.success() && debug {
|
|
||||||
println!("[ostp] Warning: Setup routing returned: {}", String::from_utf8_lossy(&out.stderr));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. Prepare and launch tun2socks
|
|
||||||
// Using HTTP Proxy natively avoids any UDP Associate requests,
|
|
||||||
// providing clean TCP proxying with maximum reliability.
|
|
||||||
let proxy_url = format!("http://{}", config.local_proxy.bind_addr);
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
println!("[ostp] Spawning {} -device ostp_tun -proxy {}", tun2socks_exe.display(), proxy_url);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut child = Command::new(&tun2socks_exe)
|
|
||||||
.args([
|
|
||||||
"-device", "ostp_tun",
|
|
||||||
"-proxy", &proxy_url,
|
|
||||||
])
|
|
||||||
.stdout(if debug { Stdio::piped() } else { Stdio::null() })
|
|
||||||
.stderr(if debug { Stdio::piped() } else { Stdio::null() })
|
|
||||||
.spawn()
|
|
||||||
.map_err(|e| anyhow!("Failed to spawn tun2socks process: {}", e))?;
|
|
||||||
|
|
||||||
let mut _guard = LinuxRouteGuard {
|
let mut _guard = LinuxRouteGuard {
|
||||||
server_ip_str: server_ip_str.clone(),
|
server_ip_str: server_ip_str.clone(),
|
||||||
default_gw: default_gw.clone(),
|
default_gw: default_gw.clone(),
|
||||||
default_if: default_if.clone(),
|
default_if: default_if.clone(),
|
||||||
child: None,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
println!("[ostp] TUN tunnel active. All traffic is routed through OSTP.");
|
// 4. Setup routing rules
|
||||||
|
let setup_script = format!(
|
||||||
|
"ip route add {} via {} dev {}; \
|
||||||
|
ip route add 1.1.1.1 via {} dev {}; \
|
||||||
|
ip route add 0.0.0.0/1 dev ostp_tun; \
|
||||||
|
ip route add 128.0.0.0/1 dev ostp_tun",
|
||||||
|
server_ip_str, default_gw, default_if,
|
||||||
|
default_gw, default_if
|
||||||
|
);
|
||||||
|
|
||||||
if debug {
|
let out = Command::new("sh")
|
||||||
let stdout = child.stdout.take().unwrap();
|
.args(["-c", &setup_script])
|
||||||
let stderr = child.stderr.take().unwrap();
|
.output()?;
|
||||||
|
|
||||||
tokio::spawn(async move {
|
if !out.status.success() {
|
||||||
let reader = BufReader::new(stdout);
|
tracing::warn!("Warning: Setup routing returned: {}", String::from_utf8_lossy(&out.stderr));
|
||||||
for line in reader.lines().map_while(Result::ok) {
|
|
||||||
println!("[tun2socks] {}", line);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
tokio::spawn(async move {
|
|
||||||
let reader = BufReader::new(stderr);
|
|
||||||
for line in reader.lines().map_while(Result::ok) {
|
|
||||||
tracing::warn!("tun2socks: {}", line);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_guard.child = Some(child);
|
info!("TUN tunnel active. Direct in-process packets handling started.");
|
||||||
|
|
||||||
// 6. Wait for shutdown signal
|
// Run the smoltcp stack loop in the background
|
||||||
|
let stack_shutdown_rx = shutdown.clone();
|
||||||
|
let stack_handle = tokio::spawn(async move {
|
||||||
|
if let Err(e) = run_smoltcp_stack(
|
||||||
|
tun_dev.packet_rx,
|
||||||
|
tun_dev.packet_tx,
|
||||||
|
config.ostp.mtu,
|
||||||
|
proxy_events_tx,
|
||||||
|
client_msgs_rx,
|
||||||
|
stack_shutdown_rx,
|
||||||
|
).await {
|
||||||
|
tracing::error!("smoltcp stack loop failed: {:?}", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 5. Wait for shutdown signal
|
||||||
let _ = shutdown.changed().await;
|
let _ = shutdown.changed().await;
|
||||||
|
|
||||||
println!("[ostp] Deactivating TUN tunnel...");
|
info!("Deactivating TUN tunnel...");
|
||||||
|
|
||||||
// Drop guard runs cleanup automatically
|
|
||||||
drop(_guard);
|
drop(_guard);
|
||||||
|
|
||||||
println!("[ostp] TUN tunnel stopped.");
|
// Terminate smoltcp stack
|
||||||
|
let _ = stack_handle.await;
|
||||||
|
|
||||||
|
info!("TUN tunnel stopped.");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -227,6 +166,8 @@ pub async fn run_linux_tunnel(
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub async fn run_linux_tunnel(
|
pub async fn run_linux_tunnel(
|
||||||
_config: crate::config::ClientConfig,
|
_config: crate::config::ClientConfig,
|
||||||
|
_proxy_events_tx: mpsc::Sender<ProxyEvent>,
|
||||||
|
_client_msgs_rx: mpsc::UnboundedReceiver<(u16, ProxyToClientMsg)>,
|
||||||
_shutdown: watch::Receiver<bool>,
|
_shutdown: watch::Receiver<bool>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
Err(anyhow!("Linux tunnel driver executed on a non-Linux host!"))
|
Err(anyhow!("Linux tunnel driver executed on a non-Linux host!"))
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,31 @@
|
||||||
mod proxy;
|
mod proxy;
|
||||||
mod wintun_handler;
|
mod wintun_handler;
|
||||||
mod linux_handler;
|
mod linux_handler;
|
||||||
|
mod tun_device;
|
||||||
|
mod smoltcp_stack;
|
||||||
|
|
||||||
pub async fn run_tun_tunnel(
|
pub async fn run_tun_tunnel(
|
||||||
config: crate::config::ClientConfig,
|
config: crate::config::ClientConfig,
|
||||||
|
proxy_events_tx: mpsc::Sender<ProxyEvent>,
|
||||||
|
client_msgs_rx: mpsc::UnboundedReceiver<(u16, ProxyToClientMsg)>,
|
||||||
shutdown: watch::Receiver<bool>,
|
shutdown: watch::Receiver<bool>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
{
|
{
|
||||||
wintun_handler::run_wintun_tunnel(config, shutdown).await
|
wintun_handler::run_wintun_tunnel(config, proxy_events_tx, client_msgs_rx, shutdown).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
{
|
{
|
||||||
linux_handler::run_linux_tunnel(config, shutdown).await
|
linux_handler::run_linux_tunnel(config, proxy_events_tx, client_msgs_rx, shutdown).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "windows", target_os = "linux")))]
|
#[cfg(not(any(target_os = "windows", target_os = "linux")))]
|
||||||
{
|
{
|
||||||
let _ = shutdown;
|
let _ = shutdown;
|
||||||
let _ = config;
|
let _ = config;
|
||||||
|
let _ = proxy_events_tx;
|
||||||
|
let _ = client_msgs_rx;
|
||||||
anyhow::bail!("Operating system unsupported, text an issue at github.");
|
anyhow::bail!("Operating system unsupported, text an issue at github.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -66,4 +72,7 @@ pub async fn run_local_proxy(
|
||||||
run_local_socks5_proxy(cfg, ostp, exclusions, debug, shutdown, proxy_events_tx, client_msgs_rx).await
|
run_local_socks5_proxy(cfg, ostp, exclusions, debug, shutdown, proxy_events_tx, client_msgs_rx).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub use tun_device::create_tun_device_from_fd;
|
||||||
|
pub use smoltcp_stack::run_smoltcp_stack;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,272 @@
|
||||||
|
use std::collections::{HashMap, VecDeque};
|
||||||
|
use std::time::Instant;
|
||||||
|
use anyhow::Result;
|
||||||
|
use tokio::sync::mpsc;
|
||||||
|
use tokio::sync::watch;
|
||||||
|
use bytes::Bytes;
|
||||||
|
use tracing::{info, error, debug};
|
||||||
|
|
||||||
|
use smoltcp::iface::{Config, Interface, SocketSet, SocketHandle};
|
||||||
|
use smoltcp::phy::{Device, DeviceCapabilities, Medium, RxToken, TxToken};
|
||||||
|
use smoltcp::socket::tcp::{Socket as TcpSocket, State as TcpState};
|
||||||
|
use smoltcp::wire::{IpAddress, IpCidr, Ipv4Packet, IpProtocol, TcpPacket};
|
||||||
|
|
||||||
|
use crate::tunnel::{ProxyEvent, ProxyToClientMsg};
|
||||||
|
|
||||||
|
// Custom smoltcp device that bridges to tokio channels
|
||||||
|
struct ChannelDevice {
|
||||||
|
rx_queue: VecDeque<Vec<u8>>,
|
||||||
|
tx_sender: mpsc::Sender<Vec<u8>>,
|
||||||
|
capabilities: DeviceCapabilities,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ChannelDevice {
|
||||||
|
fn new(tx_sender: mpsc::Sender<Vec<u8>>, mtu: usize) -> Self {
|
||||||
|
let mut caps = DeviceCapabilities::default();
|
||||||
|
caps.medium = Medium::Ip;
|
||||||
|
caps.max_transmission_unit = mtu;
|
||||||
|
Self {
|
||||||
|
rx_queue: VecDeque::new(),
|
||||||
|
tx_sender,
|
||||||
|
capabilities: caps,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ChannelRxToken(Vec<u8>);
|
||||||
|
|
||||||
|
impl RxToken for ChannelRxToken {
|
||||||
|
fn consume<R, F>(mut self, f: F) -> R
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut [u8]) -> R,
|
||||||
|
{
|
||||||
|
f(&mut self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ChannelTxToken(mpsc::Sender<Vec<u8>>);
|
||||||
|
|
||||||
|
impl TxToken for ChannelTxToken {
|
||||||
|
fn consume<R, F>(self, len: usize, f: F) -> R
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut [u8]) -> R,
|
||||||
|
{
|
||||||
|
let mut buffer = vec![0; len];
|
||||||
|
let result = f(&mut buffer);
|
||||||
|
let _ = self.0.try_send(buffer);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Device for ChannelDevice {
|
||||||
|
type RxToken<'a> = ChannelRxToken where Self: 'a;
|
||||||
|
type TxToken<'a> = ChannelTxToken where Self: 'a;
|
||||||
|
|
||||||
|
fn receive(&mut self, _timestamp: smoltcp::time::Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
|
||||||
|
self.rx_queue.pop_front().map(|packet| {
|
||||||
|
(
|
||||||
|
ChannelRxToken(packet),
|
||||||
|
ChannelTxToken(self.tx_sender.clone()),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn transmit(&mut self, _timestamp: smoltcp::time::Instant) -> Option<Self::TxToken<'_>> {
|
||||||
|
Some(ChannelTxToken(self.tx_sender.clone()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn capabilities(&self) -> DeviceCapabilities {
|
||||||
|
self.capabilities.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VirtualStream {
|
||||||
|
_stream_id: u16,
|
||||||
|
socket_handle: SocketHandle,
|
||||||
|
last_activity: Instant,
|
||||||
|
target: String,
|
||||||
|
established: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn run_smoltcp_stack(
|
||||||
|
mut tun_rx: mpsc::Receiver<Vec<u8>>,
|
||||||
|
tun_tx: mpsc::Sender<Vec<u8>>,
|
||||||
|
mtu: usize,
|
||||||
|
proxy_events_tx: mpsc::Sender<ProxyEvent>,
|
||||||
|
mut client_msgs_rx: mpsc::UnboundedReceiver<(u16, ProxyToClientMsg)>,
|
||||||
|
mut shutdown: watch::Receiver<bool>,
|
||||||
|
) -> Result<()> {
|
||||||
|
let mut device = ChannelDevice::new(tun_tx, mtu);
|
||||||
|
|
||||||
|
let config = Config::new(smoltcp::wire::HardwareAddress::Ip);
|
||||||
|
|
||||||
|
let mut interface = Interface::new(config, &mut device, smoltcp::time::Instant::now());
|
||||||
|
interface.set_any_ip(true); // Required to intercept all packets
|
||||||
|
interface.update_ip_addrs(|addrs| {
|
||||||
|
let _ = addrs.push(IpCidr::new(IpAddress::v4(10, 1, 0, 2), 24));
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut sockets = SocketSet::new(vec![]);
|
||||||
|
let mut stream_id_counter: u16 = 1;
|
||||||
|
let mut streams: HashMap<u16, VirtualStream> = HashMap::new();
|
||||||
|
let mut handle_to_stream_id: HashMap<SocketHandle, u16> = HashMap::new();
|
||||||
|
|
||||||
|
// Map to route incoming data from client_msgs_rx to target sockets
|
||||||
|
let mut pending_client_msgs: VecDeque<(u16, ProxyToClientMsg)> = VecDeque::new();
|
||||||
|
|
||||||
|
let mut ticker = tokio::time::interval(std::time::Duration::from_millis(5));
|
||||||
|
|
||||||
|
info!("smoltcp virtual TCP/IP stack runner active.");
|
||||||
|
|
||||||
|
loop {
|
||||||
|
tokio::select! {
|
||||||
|
_ = shutdown.changed() => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_ = ticker.tick() => {
|
||||||
|
// Periodical stack poll
|
||||||
|
}
|
||||||
|
pkt_opt = tun_rx.recv() => {
|
||||||
|
if let Some(pkt) = pkt_opt {
|
||||||
|
// Check if it's a new TCP connection (SYN) and dynamically spawn a listener
|
||||||
|
if let Ok(ipv4_packet) = Ipv4Packet::new_checked(&pkt) {
|
||||||
|
if ipv4_packet.next_header() == IpProtocol::Tcp {
|
||||||
|
if let Ok(tcp_packet) = TcpPacket::new_checked(ipv4_packet.payload()) {
|
||||||
|
if tcp_packet.syn() && !tcp_packet.ack() {
|
||||||
|
let dst_ip = ipv4_packet.dst_addr();
|
||||||
|
let dst_port = tcp_packet.dst_port();
|
||||||
|
|
||||||
|
// Allocate a stream_id
|
||||||
|
let stream_id = stream_id_counter;
|
||||||
|
stream_id_counter = stream_id_counter.wrapping_add(1);
|
||||||
|
if stream_id_counter == 0 {
|
||||||
|
stream_id_counter = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let target = format!("{}:{}", dst_ip, dst_port);
|
||||||
|
debug!("Intercepted TCP SYN to {}, creating virtual socket. Stream ID: {}", target, stream_id);
|
||||||
|
|
||||||
|
// Create socket inside smoltcp
|
||||||
|
let mut tcp_socket = TcpSocket::new(
|
||||||
|
smoltcp::socket::tcp::SocketBuffer::new(vec![0; 65535]),
|
||||||
|
smoltcp::socket::tcp::SocketBuffer::new(vec![0; 65535]),
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Err(e) = tcp_socket.listen((dst_ip, dst_port)) {
|
||||||
|
error!("Failed to set TCP socket to listen: {:?}", e);
|
||||||
|
} else {
|
||||||
|
let handle = sockets.add(tcp_socket);
|
||||||
|
streams.insert(stream_id, VirtualStream {
|
||||||
|
_stream_id: stream_id,
|
||||||
|
socket_handle: handle,
|
||||||
|
last_activity: Instant::now(),
|
||||||
|
target: target.clone(),
|
||||||
|
established: false,
|
||||||
|
});
|
||||||
|
handle_to_stream_id.insert(handle, stream_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
device.rx_queue.push_back(pkt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msg_opt = client_msgs_rx.recv() => {
|
||||||
|
if let Some((stream_id, msg)) = msg_opt {
|
||||||
|
pending_client_msgs.push_back((stream_id, msg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process pending client messages (responses from OSTP bridge)
|
||||||
|
let mut unhandled = VecDeque::new();
|
||||||
|
while let Some((stream_id, msg)) = pending_client_msgs.pop_front() {
|
||||||
|
if let Some(stream) = streams.get_mut(&stream_id) {
|
||||||
|
let socket = sockets.get_mut::<TcpSocket>(stream.socket_handle);
|
||||||
|
match msg {
|
||||||
|
ProxyToClientMsg::ConnectOk => {
|
||||||
|
stream.established = true;
|
||||||
|
debug!("Stream ID {} connected successfully via OSTP.", stream_id);
|
||||||
|
}
|
||||||
|
ProxyToClientMsg::Data(data) => {
|
||||||
|
if socket.can_send() {
|
||||||
|
let _ = socket.send_slice(&data);
|
||||||
|
stream.last_activity = Instant::now();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ProxyToClientMsg::Close | ProxyToClientMsg::Error(_) => {
|
||||||
|
socket.close();
|
||||||
|
// Socket clean-up will occur below
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unhandled.push_back((stream_id, msg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pending_client_msgs = unhandled;
|
||||||
|
|
||||||
|
// Poll the virtual interface
|
||||||
|
let timestamp = smoltcp::time::Instant::now();
|
||||||
|
let _ = interface.poll(timestamp, &mut device, &mut sockets);
|
||||||
|
|
||||||
|
// Process data transfer from virtual sockets -> OSTP client bridge
|
||||||
|
let mut closed_streams = Vec::new();
|
||||||
|
for (&stream_id, stream) in streams.iter_mut() {
|
||||||
|
let socket = sockets.get_mut::<TcpSocket>(stream.socket_handle);
|
||||||
|
|
||||||
|
// 1. Handshake detection & initiation
|
||||||
|
if socket.is_active() && !stream.established {
|
||||||
|
if socket.state() == TcpState::Established {
|
||||||
|
// Send Connect request to the bridge
|
||||||
|
if proxy_events_tx.try_send(ProxyEvent::NewStream {
|
||||||
|
stream_id,
|
||||||
|
target: stream.target.clone(),
|
||||||
|
}).is_ok() {
|
||||||
|
stream.established = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Read inbound data from client OS applications
|
||||||
|
if socket.may_recv() {
|
||||||
|
let mut buf = vec![0; 4096];
|
||||||
|
if let Ok(n) = socket.recv_slice(&mut buf) {
|
||||||
|
if n > 0 {
|
||||||
|
stream.last_activity = Instant::now();
|
||||||
|
let _ = proxy_events_tx.try_send(ProxyEvent::Data {
|
||||||
|
stream_id,
|
||||||
|
payload: Bytes::from(buf[..n].to_vec()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Connection termination detection
|
||||||
|
let mut should_close = false;
|
||||||
|
if !socket.is_active() || socket.state() == TcpState::Closed || socket.state() == TcpState::TimeWait {
|
||||||
|
should_close = true;
|
||||||
|
} else if stream.last_activity.elapsed() > std::time::Duration::from_secs(120) {
|
||||||
|
// Timeout inactive streams
|
||||||
|
should_close = true;
|
||||||
|
socket.abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
if should_close {
|
||||||
|
closed_streams.push(stream_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up closed streams
|
||||||
|
for stream_id in closed_streams {
|
||||||
|
if let Some(stream) = streams.remove(&stream_id) {
|
||||||
|
debug!("Cleaning up virtual socket for stream ID: {}", stream_id);
|
||||||
|
handle_to_stream_id.remove(&stream.socket_handle);
|
||||||
|
sockets.remove(stream.socket_handle);
|
||||||
|
let _ = proxy_events_tx.try_send(ProxyEvent::Close { stream_id });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,216 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
use anyhow::{anyhow, Result};
|
||||||
|
use tokio::sync::mpsc;
|
||||||
|
use tracing::{info, error, debug};
|
||||||
|
|
||||||
|
pub struct TunDevice {
|
||||||
|
pub packet_rx: mpsc::Receiver<Vec<u8>>,
|
||||||
|
pub packet_tx: mpsc::Sender<Vec<u8>>,
|
||||||
|
_shutdown_tx: mpsc::Sender<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
pub fn create_tun_device(tun_name: &str, mtu: usize) -> Result<TunDevice> {
|
||||||
|
let exe = std::env::current_exe()?;
|
||||||
|
let dir = exe.parent().ok_or_else(|| anyhow!("failed to get binary directory"))?;
|
||||||
|
let wintun_dll = dir.join("wintun.dll");
|
||||||
|
|
||||||
|
if !wintun_dll.exists() {
|
||||||
|
return Err(anyhow!(
|
||||||
|
"CRITICAL: 'wintun.dll' is missing at {}!\n\
|
||||||
|
Please make sure wintun.dll is present in the binary directory.",
|
||||||
|
dir.display()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("Loading wintun.dll from: {:?}", wintun_dll);
|
||||||
|
let wintun = unsafe { wintun::load_from_path(wintun_dll)? };
|
||||||
|
|
||||||
|
// Open or create adapter
|
||||||
|
let adapter = match wintun::Adapter::open(&wintun, tun_name) {
|
||||||
|
Ok(a) => a,
|
||||||
|
Err(_) => {
|
||||||
|
info!("TUN adapter '{}' not found, creating a new one...", tun_name);
|
||||||
|
wintun::Adapter::create(&wintun, "Wintun", tun_name, None)?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let session = Arc::new(adapter.start_session(wintun::MAX_RING_CAPACITY)?);
|
||||||
|
|
||||||
|
let (packet_tx_in, packet_rx) = mpsc::channel::<Vec<u8>>(100000);
|
||||||
|
let (packet_tx, mut packet_rx_out) = mpsc::channel::<Vec<u8>>(100000);
|
||||||
|
let (shutdown_tx, _shutdown_rx) = mpsc::channel::<()>(1);
|
||||||
|
|
||||||
|
// Spawning blocking read loop in a dedicated thread
|
||||||
|
let session_read = session.clone();
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
loop {
|
||||||
|
match session_read.receive_blocking() {
|
||||||
|
Ok(packet) => {
|
||||||
|
let bytes: &[u8] = packet.bytes();
|
||||||
|
if packet_tx_in.blocking_send(bytes.to_vec()).is_err() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("Wintun receive packet error: {:?}", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Spawning blocking write loop in a dedicated thread
|
||||||
|
let session_write = session.clone();
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
while let Some(pkt) = packet_rx_out.blocking_recv() {
|
||||||
|
if pkt.len() > mtu {
|
||||||
|
debug!("Dropped packet exceeding MTU: {} > {}", pkt.len(), mtu);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
match session_write.allocate_send_packet(pkt.len() as u16) {
|
||||||
|
Ok(mut send_packet) => {
|
||||||
|
send_packet.bytes_mut().copy_from_slice(&pkt);
|
||||||
|
session_write.send_packet(send_packet);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("Wintun allocate send packet error: {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(TunDevice {
|
||||||
|
packet_rx,
|
||||||
|
packet_tx,
|
||||||
|
_shutdown_tx: shutdown_tx,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
pub fn create_tun_device(tun_name: &str, mtu: usize) -> Result<TunDevice> {
|
||||||
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
|
|
||||||
|
let mut config = tun::Configuration::default();
|
||||||
|
config
|
||||||
|
.name(tun_name)
|
||||||
|
.address("10.1.0.2")
|
||||||
|
.netmask("255.255.255.0")
|
||||||
|
.mtu(mtu as i32)
|
||||||
|
.up();
|
||||||
|
|
||||||
|
let device = tun::create_as_async(&config)?;
|
||||||
|
let (mut reader, mut writer) = tokio::io::split(device);
|
||||||
|
|
||||||
|
let (packet_tx_in, packet_rx) = mpsc::channel::<Vec<u8>>(100000);
|
||||||
|
let (packet_tx, mut packet_rx_out) = mpsc::channel::<Vec<u8>>(100000);
|
||||||
|
let (shutdown_tx, mut shutdown_rx) = mpsc::channel::<()>(1);
|
||||||
|
|
||||||
|
// Read loop
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let mut buf = vec![0_u8; 65535];
|
||||||
|
loop {
|
||||||
|
match reader.read(&mut buf).await {
|
||||||
|
Ok(0) => break,
|
||||||
|
Ok(n) => {
|
||||||
|
if packet_tx_in.send(buf[..n].to_vec()).await.is_err() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("TUN read error: {:?}", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Write loop
|
||||||
|
tokio::spawn(async move {
|
||||||
|
loop {
|
||||||
|
tokio::select! {
|
||||||
|
_ = shutdown_rx.recv() => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pkt_opt = packet_rx_out.recv() => {
|
||||||
|
if let Some(pkt) = pkt_opt {
|
||||||
|
if let Err(e) = writer.write_all(&pkt).await {
|
||||||
|
error!("TUN write error: {:?}", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(TunDevice {
|
||||||
|
packet_rx,
|
||||||
|
packet_tx,
|
||||||
|
_shutdown_tx: shutdown_tx,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "windows", target_os = "linux")))]
|
||||||
|
pub fn create_tun_device(_tun_name: &str, _mtu: usize) -> Result<TunDevice> {
|
||||||
|
Err(anyhow!("Unsupported operating system for TUN device"))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
pub fn create_tun_device_from_fd(fd: i32, mtu: usize) -> Result<TunDevice> {
|
||||||
|
use std::os::unix::io::FromRawFd;
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
|
let file = unsafe { std::fs::File::from_raw_fd(fd) };
|
||||||
|
let mut file_read = file.try_clone()?;
|
||||||
|
let mut file_write = file;
|
||||||
|
|
||||||
|
let (packet_tx_in, packet_rx) = mpsc::channel::<Vec<u8>>(100000);
|
||||||
|
let (packet_tx, mut packet_rx_out) = mpsc::channel::<Vec<u8>>(100000);
|
||||||
|
let (shutdown_tx, _shutdown_rx) = mpsc::channel::<()>(1);
|
||||||
|
|
||||||
|
// Read loop thread
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
let mut buf = vec![0_u8; 65535];
|
||||||
|
loop {
|
||||||
|
match file_read.read(&mut buf) {
|
||||||
|
Ok(0) => break,
|
||||||
|
Ok(n) => {
|
||||||
|
if packet_tx_in.blocking_send(buf[..n].to_vec()).is_err() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("TUN fd read error: {:?}", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Write loop thread
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
while let Some(pkt) = packet_rx_out.blocking_recv() {
|
||||||
|
if pkt.len() > mtu {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if let Err(e) = file_write.write_all(&pkt) {
|
||||||
|
error!("TUN fd write error: {:?}", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(TunDevice {
|
||||||
|
packet_rx,
|
||||||
|
packet_tx,
|
||||||
|
_shutdown_tx: shutdown_tx,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(unix))]
|
||||||
|
pub fn create_tun_device_from_fd(_fd: i32, _mtu: usize) -> Result<TunDevice> {
|
||||||
|
Err(anyhow!("Raw fd TUN device is not supported on this operating system"))
|
||||||
|
}
|
||||||
|
|
@ -1,29 +1,36 @@
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use tokio::sync::watch;
|
use tokio::sync::{mpsc, watch};
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
use std::os::windows::process::CommandExt;
|
||||||
|
|
||||||
|
use crate::tunnel::{ProxyEvent, ProxyToClientMsg};
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
use crate::tunnel::tun_device::create_tun_device;
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
use crate::tunnel::smoltcp_stack::run_smoltcp_stack;
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
pub async fn run_wintun_tunnel(
|
pub async fn run_wintun_tunnel(
|
||||||
config: crate::config::ClientConfig,
|
config: crate::config::ClientConfig,
|
||||||
|
proxy_events_tx: mpsc::Sender<ProxyEvent>,
|
||||||
|
client_msgs_rx: mpsc::UnboundedReceiver<(u16, ProxyToClientMsg)>,
|
||||||
mut shutdown: watch::Receiver<bool>,
|
mut shutdown: watch::Receiver<bool>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
use std::net::ToSocketAddrs;
|
use std::net::ToSocketAddrs;
|
||||||
use std::process::{Command, Stdio, Child};
|
use std::process::Command;
|
||||||
use std::os::windows::process::CommandExt;
|
|
||||||
|
|
||||||
const CREATE_NO_WINDOW: u32 = 0x08000000;
|
const CREATE_NO_WINDOW: u32 = 0x08000000;
|
||||||
const TUN_NAME: &str = "ostp_tun";
|
const TUN_NAME: &str = "ostp_tun";
|
||||||
|
|
||||||
struct WintunGuard {
|
struct WintunGuard {
|
||||||
server_ip_str: String,
|
server_ip_str: String,
|
||||||
child: Option<Child>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for WintunGuard {
|
impl Drop for WintunGuard {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Some(mut child) = self.child.take() {
|
|
||||||
let _ = child.kill();
|
|
||||||
let _ = child.wait();
|
|
||||||
}
|
|
||||||
let cleanup_script = format!(
|
let cleanup_script = format!(
|
||||||
"$remote_ip = '{}'\n\
|
"$remote_ip = '{}'\n\
|
||||||
Remove-NetRoute -DestinationPrefix \"$remote_ip/32\" -Confirm:$false -ErrorAction SilentlyContinue\n\
|
Remove-NetRoute -DestinationPrefix \"$remote_ip/32\" -Confirm:$false -ErrorAction SilentlyContinue\n\
|
||||||
|
|
@ -39,27 +46,9 @@ pub async fn run_wintun_tunnel(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let debug = config.debug;
|
info!("Initializing built-in Wintun TUN tunnel...");
|
||||||
|
|
||||||
tracing::info!("Initializing TUN tunnel...");
|
|
||||||
|
|
||||||
let exe = std::env::current_exe()?;
|
|
||||||
let dir = exe.parent().ok_or_else(|| anyhow!("failed to get binary directory"))?;
|
|
||||||
let tun2socks_exe = dir.join("tun2socks.exe");
|
|
||||||
|
|
||||||
if !tun2socks_exe.exists() {
|
|
||||||
return Err(anyhow!(
|
|
||||||
"CRITICAL: 'tun2socks.exe' binary is missing!\n\
|
|
||||||
OSTP requires tun2socks for TUN mode on Windows. Please download the appropriate binary from: \n\
|
|
||||||
https://github.com/xjasonlyu/tun2socks/releases \n\
|
|
||||||
and place it in the same directory as the ostp executable ({}).",
|
|
||||||
dir.display()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. Delete stale TUN adapter if it exists from a previous run.
|
// 1. Delete stale TUN adapter if it exists from a previous run.
|
||||||
// This prevents wintun from creating "ostp_tun 2", "ostp_tun 3", etc.
|
|
||||||
tracing::info!("Cleaning up stale TUN adapter...");
|
|
||||||
let _ = Command::new("powershell")
|
let _ = Command::new("powershell")
|
||||||
.creation_flags(CREATE_NO_WINDOW)
|
.creation_flags(CREATE_NO_WINDOW)
|
||||||
.args(["-NoProfile", "-Command", &format!(
|
.args(["-NoProfile", "-Command", &format!(
|
||||||
|
|
@ -68,7 +57,6 @@ pub async fn run_wintun_tunnel(
|
||||||
netsh interface set interface \"{TUN_NAME}\" admin=disable 2>$null"
|
netsh interface set interface \"{TUN_NAME}\" admin=disable 2>$null"
|
||||||
)])
|
)])
|
||||||
.output();
|
.output();
|
||||||
// Brief pause to let the driver release the adapter
|
|
||||||
tokio::time::sleep(std::time::Duration::from_millis(200)).await;
|
tokio::time::sleep(std::time::Duration::from_millis(200)).await;
|
||||||
|
|
||||||
// 2. Resolve Server IP for routing table exclusion
|
// 2. Resolve Server IP for routing table exclusion
|
||||||
|
|
@ -79,7 +67,7 @@ pub async fn run_wintun_tunnel(
|
||||||
.ok_or_else(|| anyhow!("Could not resolve host IP for routing exclusion"))?;
|
.ok_or_else(|| anyhow!("Could not resolve host IP for routing exclusion"))?;
|
||||||
|
|
||||||
let server_ip_str = server_ip.to_string();
|
let server_ip_str = server_ip.to_string();
|
||||||
tracing::info!("Resolved server IP: {}", server_ip_str);
|
info!("Resolved server IP: {}", server_ip_str);
|
||||||
|
|
||||||
// 3. Prepare routing and firewall setup script
|
// 3. Prepare routing and firewall setup script
|
||||||
let current_exe = std::env::current_exe()?.to_string_lossy().into_owned();
|
let current_exe = std::env::current_exe()?.to_string_lossy().into_owned();
|
||||||
|
|
@ -106,31 +94,14 @@ pub async fn run_wintun_tunnel(
|
||||||
server_ip_str, current_exe
|
server_ip_str, current_exe
|
||||||
);
|
);
|
||||||
|
|
||||||
// 4. Launch tun2socks + route setup IN PARALLEL to save ~3 seconds
|
// Create the TunDevice inside the client process
|
||||||
let proxy_url = format!("http://{}", config.local_proxy.bind_addr);
|
let tun_dev = create_tun_device(TUN_NAME, config.ostp.mtu)?;
|
||||||
tracing::info!("Starting tun2socks (proxy={})", proxy_url);
|
|
||||||
|
|
||||||
// Spawn tun2socks immediately — it creates the adapter on its own
|
|
||||||
let mut child = Command::new(&tun2socks_exe)
|
|
||||||
.creation_flags(CREATE_NO_WINDOW)
|
|
||||||
.args([
|
|
||||||
"-device", TUN_NAME,
|
|
||||||
"-proxy", &proxy_url,
|
|
||||||
"-loglevel", if debug { "debug" } else { "error" }
|
|
||||||
])
|
|
||||||
.current_dir(dir)
|
|
||||||
.stdout(if debug { Stdio::piped() } else { Stdio::null() })
|
|
||||||
.stderr(if debug { Stdio::piped() } else { Stdio::null() })
|
|
||||||
.spawn()
|
|
||||||
.map_err(|e| anyhow!("Failed to launch tun2socks.exe: {}", e))?;
|
|
||||||
|
|
||||||
let mut _guard = WintunGuard {
|
let mut _guard = WintunGuard {
|
||||||
server_ip_str: server_ip_str.clone(),
|
server_ip_str: server_ip_str.clone(),
|
||||||
child: None,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Run route setup in parallel while tun2socks creates the adapter.
|
// Run route setup in parallel
|
||||||
// Also poll for the adapter to appear (typically <1s).
|
|
||||||
let route_handle = {
|
let route_handle = {
|
||||||
let script = setup_script.clone();
|
let script = setup_script.clone();
|
||||||
tokio::task::spawn_blocking(move || {
|
tokio::task::spawn_blocking(move || {
|
||||||
|
|
@ -141,7 +112,7 @@ pub async fn run_wintun_tunnel(
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
// 5. Wait for TUN adapter to appear (poll with timeout instead of fixed 2s sleep)
|
// 5. Wait for TUN adapter to appear
|
||||||
let adapter_deadline = tokio::time::Instant::now() + tokio::time::Duration::from_secs(8);
|
let adapter_deadline = tokio::time::Instant::now() + tokio::time::Duration::from_secs(8);
|
||||||
let mut adapter_ready = false;
|
let mut adapter_ready = false;
|
||||||
while tokio::time::Instant::now() < adapter_deadline {
|
while tokio::time::Instant::now() < adapter_deadline {
|
||||||
|
|
@ -153,9 +124,6 @@ pub async fn run_wintun_tunnel(
|
||||||
.output();
|
.output();
|
||||||
if let Ok(out) = check {
|
if let Ok(out) = check {
|
||||||
let status = String::from_utf8_lossy(&out.stdout).trim().to_string();
|
let status = String::from_utf8_lossy(&out.stdout).trim().to_string();
|
||||||
if debug {
|
|
||||||
tracing::info!("Adapter status: '{}'", status);
|
|
||||||
}
|
|
||||||
if status == "Up" || status == "Disconnected" || !status.is_empty() {
|
if status == "Up" || status == "Disconnected" || !status.is_empty() {
|
||||||
adapter_ready = true;
|
adapter_ready = true;
|
||||||
break;
|
break;
|
||||||
|
|
@ -167,11 +135,11 @@ pub async fn run_wintun_tunnel(
|
||||||
tracing::warn!("WARNING: TUN adapter did not appear within timeout. Proceeding anyway.");
|
tracing::warn!("WARNING: TUN adapter did not appear within timeout. Proceeding anyway.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for route setup to finish (should already be done by now)
|
// Wait for route setup to finish
|
||||||
let _ = route_handle.await;
|
let _ = route_handle.await;
|
||||||
|
|
||||||
// 6. Configure the adapter (IP, metric, MTU, DNS)
|
// 6. Configure the adapter
|
||||||
tracing::info!("Applying network configuration...");
|
info!("Applying network configuration...");
|
||||||
let mut net_setup = format!(
|
let mut net_setup = format!(
|
||||||
"netsh interface ipv4 set address name=\"{TUN_NAME}\" static 10.1.0.2 255.255.255.0 10.1.0.1\n\
|
"netsh interface ipv4 set address name=\"{TUN_NAME}\" static 10.1.0.2 255.255.255.0 10.1.0.1\n\
|
||||||
netsh interface ipv4 set subinterface \"{TUN_NAME}\" mtu={} store=persistent\n\
|
netsh interface ipv4 set subinterface \"{TUN_NAME}\" mtu={} store=persistent\n\
|
||||||
|
|
@ -181,7 +149,7 @@ pub async fn run_wintun_tunnel(
|
||||||
|
|
||||||
if let Some(ref dns) = config.dns_server {
|
if let Some(ref dns) = config.dns_server {
|
||||||
if !dns.is_empty() {
|
if !dns.is_empty() {
|
||||||
tracing::info!("DNS server: {}", dns);
|
info!("DNS server: {}", dns);
|
||||||
net_setup.push_str(&format!(
|
net_setup.push_str(&format!(
|
||||||
"netsh interface ipv4 set dnsservers name=\"{TUN_NAME}\" static {} primary\n", dns
|
"netsh interface ipv4 set dnsservers name=\"{TUN_NAME}\" static {} primary\n", dns
|
||||||
));
|
));
|
||||||
|
|
@ -193,41 +161,33 @@ pub async fn run_wintun_tunnel(
|
||||||
.args(["-NoProfile", "-Command", &net_setup])
|
.args(["-NoProfile", "-Command", &net_setup])
|
||||||
.output()?;
|
.output()?;
|
||||||
|
|
||||||
tracing::info!("TUN tunnel active. All traffic is routed through OSTP.");
|
info!("TUN tunnel active. Direct in-process packets handling started.");
|
||||||
|
|
||||||
// 7. Spawn debug log readers for tun2socks output
|
// Run the smoltcp stack loop in the background
|
||||||
let mut stdout = child.stdout.take();
|
let stack_shutdown_rx = shutdown.clone();
|
||||||
let mut stderr = child.stderr.take();
|
let stack_handle = tokio::spawn(async move {
|
||||||
_guard.child = Some(child);
|
if let Err(e) = run_smoltcp_stack(
|
||||||
|
tun_dev.packet_rx,
|
||||||
if debug {
|
tun_dev.packet_tx,
|
||||||
std::thread::spawn(move || {
|
config.ostp.mtu,
|
||||||
use std::io::{BufRead, BufReader};
|
proxy_events_tx,
|
||||||
if let Some(out) = stdout.take() {
|
client_msgs_rx,
|
||||||
let reader = BufReader::new(out);
|
stack_shutdown_rx,
|
||||||
for line in reader.lines().map_while(Result::ok) {
|
).await {
|
||||||
tracing::debug!("tun2socks: {}", line);
|
tracing::error!("smoltcp stack loop failed: {:?}", e);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
std::thread::spawn(move || {
|
|
||||||
use std::io::{BufRead, BufReader};
|
|
||||||
if let Some(err) = stderr.take() {
|
|
||||||
let reader = BufReader::new(err);
|
|
||||||
for line in reader.lines().map_while(Result::ok) {
|
|
||||||
tracing::warn!("tun2socks: {}", line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 8. Wait for shutdown signal
|
// 8. Wait for shutdown signal
|
||||||
let _ = shutdown.changed().await;
|
let _ = shutdown.changed().await;
|
||||||
|
|
||||||
tracing::info!("Deactivating TUN tunnel...");
|
info!("Deactivating TUN tunnel...");
|
||||||
drop(_guard);
|
drop(_guard);
|
||||||
tracing::info!("TUN tunnel stopped.");
|
|
||||||
|
|
||||||
|
// Terminate smoltcp stack
|
||||||
|
let _ = stack_handle.await;
|
||||||
|
|
||||||
|
info!("TUN tunnel stopped.");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -235,6 +195,8 @@ pub async fn run_wintun_tunnel(
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub async fn run_wintun_tunnel(
|
pub async fn run_wintun_tunnel(
|
||||||
_config: crate::config::ClientConfig,
|
_config: crate::config::ClientConfig,
|
||||||
|
_proxy_events_tx: mpsc::Sender<ProxyEvent>,
|
||||||
|
_client_msgs_rx: mpsc::UnboundedReceiver<(u16, ProxyToClientMsg)>,
|
||||||
_shutdown: watch::Receiver<bool>,
|
_shutdown: watch::Receiver<bool>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
Err(anyhow!("Wintun driver executed on a non-Windows host!"))
|
Err(anyhow!("Wintun driver executed on a non-Windows host!"))
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ class OstpClientSdk private constructor(private val context: Context) {
|
||||||
|
|
||||||
// ── Native JNI bindings ───────────────────────────────────────────────────
|
// ── Native JNI bindings ───────────────────────────────────────────────────
|
||||||
|
|
||||||
private external fun nativeStartClient(configJson: String): Boolean
|
private external fun nativeStartClient(configJson: String, fd: Int): Boolean
|
||||||
private external fun nativeStopClient(): Boolean
|
private external fun nativeStopClient(): Boolean
|
||||||
private external fun nativeGetMetrics(): String
|
private external fun nativeGetMetrics(): String
|
||||||
private external fun nativeGetLogs(): String
|
private external fun nativeGetLogs(): String
|
||||||
|
|
@ -165,7 +165,7 @@ class OstpClientSdk private constructor(private val context: Context) {
|
||||||
*
|
*
|
||||||
* @return `true` if the native layer accepted the start command.
|
* @return `true` if the native layer accepted the start command.
|
||||||
*/
|
*/
|
||||||
fun start(config: Config): Boolean {
|
fun start(config: Config, fd: Int = -1): Boolean {
|
||||||
if (started.getAndSet(true)) {
|
if (started.getAndSet(true)) {
|
||||||
emitLog("SDK already started; call stop() first to change config")
|
emitLog("SDK already started; call stop() first to change config")
|
||||||
return false
|
return false
|
||||||
|
|
@ -175,7 +175,7 @@ class OstpClientSdk private constructor(private val context: Context) {
|
||||||
_state.value = TunnelState.Connecting
|
_state.value = TunnelState.Connecting
|
||||||
|
|
||||||
val json = config.toNativeJson()
|
val json = config.toNativeJson()
|
||||||
val ok = nativeStartClient(json)
|
val ok = nativeStartClient(json, fd)
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
_state.value = TunnelState.Failed("Native layer rejected config")
|
_state.value = TunnelState.Failed("Native layer rejected config")
|
||||||
started.set(false)
|
started.set(false)
|
||||||
|
|
|
||||||
|
|
@ -8,14 +8,12 @@ use tokio::runtime::Runtime;
|
||||||
use tokio::sync::{mpsc, watch};
|
use tokio::sync::{mpsc, watch};
|
||||||
use ostp_client::bridge::{Bridge, BridgeMetrics};
|
use ostp_client::bridge::{Bridge, BridgeMetrics};
|
||||||
use ostp_client::config::ClientConfig;
|
use ostp_client::config::ClientConfig;
|
||||||
use ostp_client::tunnel;
|
|
||||||
use ostp_client::app::{BridgeCommand, UiEvent};
|
use ostp_client::app::{BridgeCommand, UiEvent};
|
||||||
|
|
||||||
struct SdkState {
|
struct SdkState {
|
||||||
runtime: Option<Runtime>,
|
runtime: Option<Runtime>,
|
||||||
shutdown_tx: Option<watch::Sender<bool>>,
|
shutdown_tx: Option<watch::Sender<bool>>,
|
||||||
metrics: Option<Arc<BridgeMetrics>>,
|
metrics: Option<Arc<BridgeMetrics>>,
|
||||||
tun_child: Option<std::process::Child>,
|
|
||||||
cmd_tx: Option<mpsc::Sender<BridgeCommand>>,
|
cmd_tx: Option<mpsc::Sender<BridgeCommand>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -24,7 +22,6 @@ lazy_static! {
|
||||||
runtime: None,
|
runtime: None,
|
||||||
shutdown_tx: None,
|
shutdown_tx: None,
|
||||||
metrics: None,
|
metrics: None,
|
||||||
tun_child: None,
|
|
||||||
cmd_tx: None,
|
cmd_tx: None,
|
||||||
});
|
});
|
||||||
static ref LOGS: Mutex<VecDeque<String>> = Mutex::new(VecDeque::new());
|
static ref LOGS: Mutex<VecDeque<String>> = Mutex::new(VecDeque::new());
|
||||||
|
|
@ -42,13 +39,11 @@ fn add_log(text: String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "system" fn Java_net_ostp_client_OstpClientSdk_startClient(
|
pub extern "system" fn Java_net_ostp_client_OstpClientSdk_nativeStartClient(
|
||||||
mut env: JNIEnv,
|
mut env: JNIEnv,
|
||||||
_class: JClass,
|
_class: JClass,
|
||||||
config_json: JString,
|
config_json: JString,
|
||||||
fd: jni::sys::jint,
|
fd: jni::sys::jint,
|
||||||
t2s_bin_path: JString,
|
|
||||||
local_proxy: JString,
|
|
||||||
) -> jboolean {
|
) -> jboolean {
|
||||||
let mut state = match STATE.lock() {
|
let mut state = match STATE.lock() {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
|
|
@ -105,16 +100,6 @@ pub extern "system" fn Java_net_ostp_client_OstpClientSdk_startClient(
|
||||||
Err(_) => return jni::sys::JNI_FALSE,
|
Err(_) => return jni::sys::JNI_FALSE,
|
||||||
};
|
};
|
||||||
|
|
||||||
let t2s_path: String = match env.get_string(&t2s_bin_path) {
|
|
||||||
Ok(s) => s.into(),
|
|
||||||
Err(_) => return jni::sys::JNI_FALSE,
|
|
||||||
};
|
|
||||||
|
|
||||||
let proxy_addr: String = match env.get_string(&local_proxy) {
|
|
||||||
Ok(s) => s.into(),
|
|
||||||
Err(_) => return jni::sys::JNI_FALSE,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parse config from JSON
|
// Parse config from JSON
|
||||||
let config: ClientConfig = match serde_json::from_str(&config_str) {
|
let config: ClientConfig = match serde_json::from_str(&config_str) {
|
||||||
Ok(cfg) => cfg,
|
Ok(cfg) => cfg,
|
||||||
|
|
@ -124,8 +109,6 @@ pub extern "system" fn Java_net_ostp_client_OstpClientSdk_startClient(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let debug = config.debug;
|
|
||||||
|
|
||||||
// Create tokio runtime
|
// Create tokio runtime
|
||||||
let rt = match Runtime::new() {
|
let rt = match Runtime::new() {
|
||||||
Ok(r) => r,
|
Ok(r) => r,
|
||||||
|
|
@ -156,7 +139,6 @@ pub extern "system" fn Java_net_ostp_client_OstpClientSdk_startClient(
|
||||||
let (ui_tx, mut ui_rx) = mpsc::channel(512);
|
let (ui_tx, mut ui_rx) = mpsc::channel(512);
|
||||||
let (cmd_tx, cmd_rx) = mpsc::channel(128);
|
let (cmd_tx, cmd_rx) = mpsc::channel(128);
|
||||||
let (shutdown_tx, shutdown_rx) = watch::channel(false);
|
let (shutdown_tx, shutdown_rx) = watch::channel(false);
|
||||||
let proxy_shutdown_rx = shutdown_tx.subscribe();
|
|
||||||
|
|
||||||
let metrics_clone = Arc::clone(&metrics);
|
let metrics_clone = Arc::clone(&metrics);
|
||||||
|
|
||||||
|
|
@ -165,19 +147,51 @@ pub extern "system" fn Java_net_ostp_client_OstpClientSdk_startClient(
|
||||||
bridge.run(ui_tx, cmd_rx, shutdown_rx, proxy_events_rx, client_msgs_tx).await
|
bridge.run(ui_tx, cmd_rx, shutdown_rx, proxy_events_rx, client_msgs_tx).await
|
||||||
});
|
});
|
||||||
|
|
||||||
let config_proxy = config.clone();
|
if config.mode == "tun" {
|
||||||
rt.spawn(async move {
|
if fd < 0 {
|
||||||
tunnel::run_local_proxy(
|
add_log("Error: TUN mode requested but invalid file descriptor provided".to_string());
|
||||||
config_proxy.local_proxy,
|
return jni::sys::JNI_FALSE;
|
||||||
config_proxy.ostp,
|
}
|
||||||
config_proxy.exclusions,
|
|
||||||
config_proxy.debug,
|
let tun_dev = match ostp_client::tunnel::create_tun_device_from_fd(fd, config.ostp.mtu) {
|
||||||
proxy_shutdown_rx,
|
Ok(d) => d,
|
||||||
proxy_events_tx,
|
Err(e) => {
|
||||||
client_msgs_rx,
|
add_log(format!("Failed to wrap TUN fd: {:?}", e));
|
||||||
)
|
return jni::sys::JNI_FALSE;
|
||||||
.await
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
|
let stack_shutdown_rx = shutdown_tx.subscribe();
|
||||||
|
let proxy_events_tx_clone = proxy_events_tx.clone();
|
||||||
|
let mtu = config.ostp.mtu;
|
||||||
|
rt.spawn(async move {
|
||||||
|
if let Err(e) = ostp_client::tunnel::run_smoltcp_stack(
|
||||||
|
tun_dev.packet_rx,
|
||||||
|
tun_dev.packet_tx,
|
||||||
|
mtu,
|
||||||
|
proxy_events_tx_clone,
|
||||||
|
client_msgs_rx,
|
||||||
|
stack_shutdown_rx,
|
||||||
|
).await {
|
||||||
|
add_log(format!("smoltcp stack loop failed: {:?}", e));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
let config_proxy = config.clone();
|
||||||
|
let proxy_shutdown_rx = shutdown_tx.subscribe();
|
||||||
|
rt.spawn(async move {
|
||||||
|
let _ = ostp_client::tunnel::run_local_proxy(
|
||||||
|
config_proxy.local_proxy,
|
||||||
|
config_proxy.ostp,
|
||||||
|
config_proxy.exclusions,
|
||||||
|
config_proxy.debug,
|
||||||
|
proxy_shutdown_rx,
|
||||||
|
proxy_events_tx,
|
||||||
|
client_msgs_rx,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Start logs receiver task
|
// Start logs receiver task
|
||||||
rt.spawn(async move {
|
rt.spawn(async move {
|
||||||
|
|
@ -197,68 +211,9 @@ pub extern "system" fn Java_net_ostp_client_OstpClientSdk_startClient(
|
||||||
let _ = cmd_tx_clone.send(BridgeCommand::ToggleTunnel).await;
|
let _ = cmd_tx_clone.send(BridgeCommand::ToggleTunnel).await;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Spawn tun2socks
|
|
||||||
let fd_str = format!("fd://{}", fd);
|
|
||||||
let proxy_str = format!("socks5://{}", proxy_addr);
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
add_log(format!("Spawning tun2socks: {} -device {} -proxy {}", t2s_path, fd_str, proxy_str));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut cmd = std::process::Command::new(&t2s_path);
|
|
||||||
cmd.arg("-device")
|
|
||||||
.arg(&fd_str)
|
|
||||||
.arg("-proxy")
|
|
||||||
.arg(&proxy_str);
|
|
||||||
|
|
||||||
if config.ostp.mtu > 0 {
|
|
||||||
cmd.arg("-mtu").arg(config.ostp.mtu.to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.stdout(std::process::Stdio::piped())
|
|
||||||
.stderr(std::process::Stdio::piped());
|
|
||||||
|
|
||||||
let mut child = match cmd.spawn() {
|
|
||||||
Ok(c) => c,
|
|
||||||
Err(e) => {
|
|
||||||
add_log(format!("Failed to spawn tun2socks from Rust: {e}"));
|
|
||||||
return jni::sys::JNI_FALSE;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let stdout = child.stdout.take().unwrap();
|
|
||||||
let stderr = child.stderr.take().unwrap();
|
|
||||||
|
|
||||||
// Read stdout
|
|
||||||
std::thread::spawn(move || {
|
|
||||||
use std::io::{BufRead, BufReader};
|
|
||||||
let reader = BufReader::new(stdout);
|
|
||||||
for line in reader.lines() {
|
|
||||||
if let Ok(l) = line {
|
|
||||||
if debug {
|
|
||||||
add_log(format!("tun2socks: {}", l));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Read stderr & wait
|
|
||||||
std::thread::spawn(move || {
|
|
||||||
use std::io::{BufRead, BufReader};
|
|
||||||
let reader = BufReader::new(stderr);
|
|
||||||
for line in reader.lines() {
|
|
||||||
if let Ok(l) = line {
|
|
||||||
if debug {
|
|
||||||
add_log(format!("tun2socks ERROR: {}", l));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
state.runtime = Some(rt);
|
state.runtime = Some(rt);
|
||||||
state.shutdown_tx = Some(shutdown_tx);
|
state.shutdown_tx = Some(shutdown_tx);
|
||||||
state.metrics = Some(metrics_clone);
|
state.metrics = Some(metrics_clone);
|
||||||
state.tun_child = Some(child);
|
|
||||||
state.cmd_tx = Some(cmd_tx);
|
state.cmd_tx = Some(cmd_tx);
|
||||||
|
|
||||||
add_log("OSTP SDK: Client successfully started".to_string());
|
add_log("OSTP SDK: Client successfully started".to_string());
|
||||||
|
|
@ -266,7 +221,7 @@ pub extern "system" fn Java_net_ostp_client_OstpClientSdk_startClient(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "system" fn Java_net_ostp_client_OstpClientSdk_stopClient(
|
pub extern "system" fn Java_net_ostp_client_OstpClientSdk_nativeStopClient(
|
||||||
_env: JNIEnv,
|
_env: JNIEnv,
|
||||||
_class: JClass,
|
_class: JClass,
|
||||||
) -> jboolean {
|
) -> jboolean {
|
||||||
|
|
@ -275,11 +230,6 @@ pub extern "system" fn Java_net_ostp_client_OstpClientSdk_stopClient(
|
||||||
Err(_) => return jni::sys::JNI_FALSE,
|
Err(_) => return jni::sys::JNI_FALSE,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(mut child) = state.tun_child.take() {
|
|
||||||
let _ = child.kill();
|
|
||||||
add_log("Killed tun2socks process".to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(shutdown_tx) = state.shutdown_tx.take() {
|
if let Some(shutdown_tx) = state.shutdown_tx.take() {
|
||||||
let _ = shutdown_tx.send(true);
|
let _ = shutdown_tx.send(true);
|
||||||
}
|
}
|
||||||
|
|
@ -295,7 +245,7 @@ pub extern "system" fn Java_net_ostp_client_OstpClientSdk_stopClient(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "system" fn Java_net_ostp_client_OstpClientSdk_getMetrics(
|
pub extern "system" fn Java_net_ostp_client_OstpClientSdk_nativeGetMetrics(
|
||||||
env: JNIEnv,
|
env: JNIEnv,
|
||||||
_class: JClass,
|
_class: JClass,
|
||||||
) -> jstring {
|
) -> jstring {
|
||||||
|
|
@ -329,7 +279,7 @@ pub extern "system" fn Java_net_ostp_client_OstpClientSdk_getMetrics(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "system" fn Java_net_ostp_client_OstpClientSdk_getLogs(
|
pub extern "system" fn Java_net_ostp_client_OstpClientSdk_nativeGetLogs(
|
||||||
env: JNIEnv,
|
env: JNIEnv,
|
||||||
_class: JClass,
|
_class: JClass,
|
||||||
) -> jstring {
|
) -> jstring {
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,9 @@ use portable_atomic::AtomicU64;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
use axum::{
|
use axum::{
|
||||||
body::Body,
|
|
||||||
extract::{Path, State},
|
extract::{Path, State},
|
||||||
http::{header, Request, StatusCode, Uri},
|
http::{header, StatusCode, Uri},
|
||||||
response::{IntoResponse, Response},
|
response::IntoResponse,
|
||||||
routing::{get, post, put},
|
routing::{get, post, put},
|
||||||
Json, Router,
|
Json, Router,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue