fix port binding
This commit is contained in:
parent
dad8ac498c
commit
785341e883
43 changed files with 1543 additions and 431 deletions
293
Cargo.lock
generated
293
Cargo.lock
generated
|
|
@ -149,7 +149,7 @@ dependencies = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"windows-link",
|
"windows-link 0.1.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -162,12 +162,31 @@ dependencies = [
|
||||||
"inout",
|
"inout",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation-sys"
|
name = "core-foundation-sys"
|
||||||
version = "0.8.7"
|
version = "0.8.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpufeatures"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32fast"
|
name = "crc32fast"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
|
|
@ -187,6 +206,12 @@ dependencies = [
|
||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "data-encoding"
|
||||||
|
version = "2.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deranged"
|
name = "deranged"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
|
@ -229,6 +254,50 @@ version = "1.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-core"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-macro"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.104",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-sink"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-task"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-util"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-macro",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-task",
|
||||||
|
"pin-project-lite",
|
||||||
|
"pin-utils",
|
||||||
|
"slab",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.14.7"
|
version = "0.14.7"
|
||||||
|
|
@ -250,6 +319,18 @@ dependencies = [
|
||||||
"wasi",
|
"wasi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"r-efi",
|
||||||
|
"wasip2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.31.1"
|
version = "0.31.1"
|
||||||
|
|
@ -471,6 +552,12 @@ version = "1.21.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-probe"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.12.4"
|
version = "0.12.4"
|
||||||
|
|
@ -512,6 +599,12 @@ version = "0.2.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
|
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-utils"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "powerfmt"
|
name = "powerfmt"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
|
@ -543,6 +636,7 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"log",
|
"log",
|
||||||
"proxy-common",
|
"proxy-common",
|
||||||
|
"prudplite",
|
||||||
"prudpv0",
|
"prudpv0",
|
||||||
"prudpv1",
|
"prudpv1",
|
||||||
"rnex-core",
|
"rnex-core",
|
||||||
|
|
@ -559,6 +653,20 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prudplite"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
"futures-util",
|
||||||
|
"log",
|
||||||
|
"proxy-common",
|
||||||
|
"rnex-core",
|
||||||
|
"tokio",
|
||||||
|
"tokio-tungstenite",
|
||||||
|
"v-byte-helpers",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prudpv0"
|
name = "prudpv0"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
@ -604,6 +712,12 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "r-efi"
|
||||||
|
version = "5.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.8.5"
|
version = "0.8.5"
|
||||||
|
|
@ -611,8 +725,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"rand_chacha",
|
"rand_chacha 0.3.1",
|
||||||
"rand_core",
|
"rand_core 0.6.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
|
||||||
|
dependencies = [
|
||||||
|
"rand_chacha 0.9.0",
|
||||||
|
"rand_core 0.9.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -622,7 +746,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ppv-lite86",
|
"ppv-lite86",
|
||||||
"rand_core",
|
"rand_core 0.6.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core 0.9.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -631,7 +765,16 @@ version = "0.6.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom 0.2.16",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.9.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom 0.3.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -660,7 +803,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"getrandom",
|
"getrandom 0.2.16",
|
||||||
"libc",
|
"libc",
|
||||||
"untrusted",
|
"untrusted",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
|
|
@ -683,7 +826,7 @@ dependencies = [
|
||||||
"md-5",
|
"md-5",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"paste",
|
"paste",
|
||||||
"rand",
|
"rand 0.8.5",
|
||||||
"rc4",
|
"rc4",
|
||||||
"simplelog",
|
"simplelog",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
|
@ -714,6 +857,18 @@ dependencies = [
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls-native-certs"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63"
|
||||||
|
dependencies = [
|
||||||
|
"openssl-probe",
|
||||||
|
"rustls-pki-types",
|
||||||
|
"schannel",
|
||||||
|
"security-framework",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls-pki-types"
|
name = "rustls-pki-types"
|
||||||
version = "1.12.0"
|
version = "1.12.0"
|
||||||
|
|
@ -740,12 +895,44 @@ version = "1.0.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
|
checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "schannel"
|
||||||
|
version = "0.1.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.61.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "security-framework"
|
||||||
|
version = "3.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"core-foundation",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
"security-framework-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "security-framework-sys"
|
||||||
|
version = "2.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.219"
|
version = "1.0.219"
|
||||||
|
|
@ -766,6 +953,17 @@ dependencies = [
|
||||||
"syn 2.0.104",
|
"syn 2.0.104",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha1"
|
||||||
|
version = "0.10.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shlex"
|
name = "shlex"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
|
|
@ -941,6 +1139,51 @@ dependencies = [
|
||||||
"syn 2.0.104",
|
"syn 2.0.104",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-rustls"
|
||||||
|
version = "0.26.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61"
|
||||||
|
dependencies = [
|
||||||
|
"rustls",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-tungstenite"
|
||||||
|
version = "0.28.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857"
|
||||||
|
dependencies = [
|
||||||
|
"futures-util",
|
||||||
|
"log",
|
||||||
|
"rustls",
|
||||||
|
"rustls-native-certs",
|
||||||
|
"rustls-pki-types",
|
||||||
|
"tokio",
|
||||||
|
"tokio-rustls",
|
||||||
|
"tungstenite",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tungstenite"
|
||||||
|
version = "0.28.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"data-encoding",
|
||||||
|
"http",
|
||||||
|
"httparse",
|
||||||
|
"log",
|
||||||
|
"rand 0.9.2",
|
||||||
|
"rustls",
|
||||||
|
"rustls-pki-types",
|
||||||
|
"sha1",
|
||||||
|
"thiserror",
|
||||||
|
"utf-8",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.18.0"
|
version = "1.18.0"
|
||||||
|
|
@ -1015,6 +1258,15 @@ version = "0.11.1+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasip2"
|
||||||
|
version = "1.0.2+wasi-0.2.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
|
||||||
|
dependencies = [
|
||||||
|
"wit-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.100"
|
version = "0.2.100"
|
||||||
|
|
@ -1099,7 +1351,7 @@ checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-implement",
|
"windows-implement",
|
||||||
"windows-interface",
|
"windows-interface",
|
||||||
"windows-link",
|
"windows-link 0.1.3",
|
||||||
"windows-result",
|
"windows-result",
|
||||||
"windows-strings",
|
"windows-strings",
|
||||||
]
|
]
|
||||||
|
|
@ -1132,13 +1384,19 @@ version = "0.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
|
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-link"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-result"
|
name = "windows-result"
|
||||||
version = "0.3.4"
|
version = "0.3.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
|
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-link",
|
"windows-link 0.1.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1147,7 +1405,7 @@ version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
|
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-link",
|
"windows-link 0.1.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1168,6 +1426,15 @@ dependencies = [
|
||||||
"windows-targets",
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.61.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||||
|
dependencies = [
|
||||||
|
"windows-link 0.2.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-targets"
|
name = "windows-targets"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
|
|
@ -1232,6 +1499,12 @@ version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen"
|
||||||
|
version = "0.51.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.8.26"
|
version = "0.8.26"
|
||||||
|
|
|
||||||
|
|
@ -5,4 +5,4 @@ members = [
|
||||||
"rnex-core",
|
"rnex-core",
|
||||||
"prudpv1",
|
"prudpv1",
|
||||||
"prudpv0"
|
"prudpv0"
|
||||||
, "proxy", "proxy-common"]
|
, "proxy", "proxy-common", "prudplite"]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,17 @@
|
||||||
splatoon:
|
splatoon:
|
||||||
features:
|
features:
|
||||||
- rmc_struct_header
|
|
||||||
- prudpv1
|
- prudpv1
|
||||||
|
- v3-8-15
|
||||||
|
settings:
|
||||||
|
AUTH_REPORT_VERSION: "branch:origin/project/wup-agmj build:3_8_15_2004_0"
|
||||||
|
RNEX_VIRTUAL_PORT_INSECURE: "1:10"
|
||||||
|
RNEX_VIRTUAL_PORT_SECURE: "1:10"
|
||||||
|
RNEX_DEFAULT_PORT: 6000
|
||||||
|
splatoon2:
|
||||||
|
features:
|
||||||
|
- v4-3-11
|
||||||
|
- prudplite
|
||||||
|
- nx
|
||||||
settings:
|
settings:
|
||||||
AUTH_REPORT_VERSION: "branch:origin/project/wup-agmj build:3_8_15_2004_0"
|
AUTH_REPORT_VERSION: "branch:origin/project/wup-agmj build:3_8_15_2004_0"
|
||||||
RNEX_VIRTUAL_PORT_INSECURE: "1:10"
|
RNEX_VIRTUAL_PORT_INSECURE: "1:10"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
[package]
|
[package]
|
||||||
name = "macros"
|
name = "macros"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
authors = ["DJMrTV <tvnebel@gmail.com>"]
|
authors = ["RusticMaple <tvnebel@gmail.com>"]
|
||||||
description = "A `cargo generate` template for quick-starting a procedural macro crate"
|
description = "A `cargo generate` template for quick-starting a procedural macro crate"
|
||||||
keywords = ["template", "proc_macro", "procmacro"]
|
keywords = ["template", "proc_macro", "procmacro"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
@ -14,4 +14,3 @@ doctest = false
|
||||||
quote = "1.0.38"
|
quote = "1.0.38"
|
||||||
proc-macro2 = "1.0.93"
|
proc-macro2 = "1.0.93"
|
||||||
syn = { version = "2.0.98", features = ["full"] }
|
syn = { version = "2.0.98", features = ["full"] }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,11 @@ impl Parse for ProtoInputParams {
|
||||||
fn gen_serialize_data_struct(
|
fn gen_serialize_data_struct(
|
||||||
s: DataStruct,
|
s: DataStruct,
|
||||||
struct_attr: Option<&Attribute>,
|
struct_attr: Option<&Attribute>,
|
||||||
) -> (proc_macro2::TokenStream, proc_macro2::TokenStream, proc_macro2::TokenStream) {
|
) -> (
|
||||||
|
proc_macro2::TokenStream,
|
||||||
|
proc_macro2::TokenStream,
|
||||||
|
proc_macro2::TokenStream,
|
||||||
|
) {
|
||||||
let serialize_base_content = {
|
let serialize_base_content = {
|
||||||
let mut serialize_content = quote! {};
|
let mut serialize_content = quote! {};
|
||||||
|
|
||||||
|
|
@ -123,8 +127,6 @@ fn gen_serialize_data_struct(
|
||||||
let mut size_content = quote! { 0 };
|
let mut size_content = quote! { 0 };
|
||||||
|
|
||||||
for f in &s.fields {
|
for f in &s.fields {
|
||||||
|
|
||||||
|
|
||||||
let ident = f.ident.as_ref().unwrap();
|
let ident = f.ident.as_ref().unwrap();
|
||||||
|
|
||||||
size_content.append_all(quote! {
|
size_content.append_all(quote! {
|
||||||
|
|
@ -140,7 +142,6 @@ fn gen_serialize_data_struct(
|
||||||
write_size
|
write_size
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// generate base with extends stuff
|
// generate base with extends stuff
|
||||||
|
|
||||||
let serialize_base_content = if let Some(attr) = struct_attr {
|
let serialize_base_content = if let Some(attr) = struct_attr {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use proc_macro2::{Ident, Span, TokenStream};
|
use proc_macro2::{Ident, Span, TokenStream};
|
||||||
use quote::{quote, ToTokens};
|
use quote::{quote, ToTokens};
|
||||||
use syn::{LitInt, LitStr, ReturnType, Type};
|
|
||||||
use syn::token::{Brace, Paren, Semi};
|
use syn::token::{Brace, Paren, Semi};
|
||||||
|
use syn::{Attribute, LitInt, LitStr, ReturnType, Type};
|
||||||
|
|
||||||
pub struct ProtoMethodData {
|
pub struct ProtoMethodData {
|
||||||
pub id: LitInt,
|
pub id: LitInt,
|
||||||
|
|
@ -10,7 +10,6 @@ pub struct ProtoMethodData{
|
||||||
pub ret_val: ReturnType,
|
pub ret_val: ReturnType,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// This is a representation of the code generated by `rmc_proto` it serves to split the logic of
|
/// This is a representation of the code generated by `rmc_proto` it serves to split the logic of
|
||||||
/// acquiring data from the actual generation to tidy up the process into first getting then
|
/// acquiring data from the actual generation to tidy up the process into first getting then
|
||||||
/// generating.
|
/// generating.
|
||||||
|
|
@ -20,7 +19,7 @@ pub struct RmcProtocolData{
|
||||||
pub has_returns: bool,
|
pub has_returns: bool,
|
||||||
pub id: LitInt,
|
pub id: LitInt,
|
||||||
pub name: Ident,
|
pub name: Ident,
|
||||||
pub methods: Vec<ProtoMethodData>
|
pub methods: Vec<ProtoMethodData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RmcProtocolData {
|
impl RmcProtocolData {
|
||||||
|
|
@ -29,19 +28,19 @@ impl RmcProtocolData{
|
||||||
has_returns,
|
has_returns,
|
||||||
name,
|
name,
|
||||||
id,
|
id,
|
||||||
methods
|
methods,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
// this gives us the name which the identifier of the corresponding Raw trait
|
// this gives us the name which the identifier of the corresponding Raw trait
|
||||||
let raw_name = Ident::new(&format!("Raw{}", name), name.span());
|
let raw_name = Ident::new(&format!("Raw{}", name), name.span());
|
||||||
|
|
||||||
|
|
||||||
// boilerplate tokens which all raw traits need
|
// boilerplate tokens which all raw traits need
|
||||||
quote! {
|
quote! {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(unused_must_use)]
|
#[allow(unused_must_use)]
|
||||||
pub trait #raw_name: #name
|
pub trait #raw_name: #name
|
||||||
}.to_tokens(tokens);
|
}
|
||||||
|
.to_tokens(tokens);
|
||||||
|
|
||||||
// generate the body of the raw protocol trait
|
// generate the body of the raw protocol trait
|
||||||
Brace::default().surround(tokens, |tokens|{
|
Brace::default().surround(tokens, |tokens|{
|
||||||
|
|
@ -193,7 +192,8 @@ impl RmcProtocolData{
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
impl<T: #name> #raw_name for T{}
|
impl<T: #name> #raw_name for T{}
|
||||||
}.to_tokens(tokens);
|
}
|
||||||
|
.to_tokens(tokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_raw_remote_trait(&self, tokens: &mut TokenStream) {
|
fn generate_raw_remote_trait(&self, tokens: &mut TokenStream) {
|
||||||
|
|
@ -208,13 +208,13 @@ impl RmcProtocolData{
|
||||||
// this gives us the name which the identifier of the corresponding Raw trait
|
// this gives us the name which the identifier of the corresponding Raw trait
|
||||||
let remote_name = Ident::new(&format!("Remote{}", name), name.span());
|
let remote_name = Ident::new(&format!("Remote{}", name), name.span());
|
||||||
|
|
||||||
|
|
||||||
// boilerplate tokens which all raw traits need
|
// boilerplate tokens which all raw traits need
|
||||||
quote! {
|
quote! {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[allow(unused_must_use)]
|
#[allow(unused_must_use)]
|
||||||
pub trait #remote_name: rnex_core::rmc::protocols::HasRmcConnection
|
pub trait #remote_name: rnex_core::rmc::protocols::HasRmcConnection
|
||||||
}.to_tokens(tokens);
|
}
|
||||||
|
.to_tokens(tokens);
|
||||||
|
|
||||||
// generate the body of the raw protocol trait
|
// generate the body of the raw protocol trait
|
||||||
Brace::default().surround(tokens, |tokens|{
|
Brace::default().surround(tokens, |tokens|{
|
||||||
|
|
@ -299,20 +299,13 @@ impl RmcProtocolData{
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_raw_info(&self, tokens: &mut TokenStream) {
|
fn generate_raw_info(&self, tokens: &mut TokenStream) {
|
||||||
let Self{
|
let Self { name, id, .. } = self;
|
||||||
name,
|
|
||||||
id,
|
|
||||||
..
|
|
||||||
} = self;
|
|
||||||
|
|
||||||
let raw_info_name = Ident::new(&format!("Raw{}Info", name), Span::call_site());
|
let raw_info_name = Ident::new(&format!("Raw{}Info", name), Span::call_site());
|
||||||
|
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub struct #raw_info_name;
|
pub struct #raw_info_name;
|
||||||
|
|
@ -320,7 +313,8 @@ impl RmcProtocolData{
|
||||||
impl #raw_info_name {
|
impl #raw_info_name {
|
||||||
pub const PROTOCOL_ID: u16 = #id;
|
pub const PROTOCOL_ID: u16 = #id;
|
||||||
}
|
}
|
||||||
}.to_tokens(tokens);
|
}
|
||||||
|
.to_tokens(tokens);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use rnex_core::{
|
use rnex_core::{
|
||||||
|
PID,
|
||||||
executables::common::{OWN_IP_PUBLIC, try_get_ip},
|
executables::common::{OWN_IP_PUBLIC, try_get_ip},
|
||||||
prudp::{socket_addr::PRUDPSockAddr, virtual_port::VirtualPort},
|
prudp::{socket_addr::PRUDPSockAddr, virtual_port::VirtualPort},
|
||||||
reggie::{RemoteEdgeNodeHolder, UnitPacketWrite},
|
reggie::{RemoteEdgeNodeHolder, UnitPacketWrite},
|
||||||
|
|
@ -83,7 +84,7 @@ impl ProxyStartupParam {
|
||||||
let self_public: SocketAddrV4 = match try_get_env("SERVER_IP_PUBLIC") {
|
let self_public: SocketAddrV4 = match try_get_env("SERVER_IP_PUBLIC") {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => try_get_ip()
|
Err(e) => try_get_ip()
|
||||||
.map(|v| SocketAddrV4::new(v, RNEX_DEFAULT_PORT))
|
.map(|v| SocketAddrV4::new(v, self_private.port()))
|
||||||
.map_err(move |v| Error::PubAddrGetErr(Box::new(e), v))?,
|
.map_err(move |v| Error::PubAddrGetErr(Box::new(e), v))?,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -175,7 +176,7 @@ pub async fn setup_edge_node_connection(
|
||||||
pub async fn new_backend_connection(
|
pub async fn new_backend_connection(
|
||||||
param: &ProxyStartupParam,
|
param: &ProxyStartupParam,
|
||||||
addr: PRUDPSockAddr,
|
addr: PRUDPSockAddr,
|
||||||
pid: u32,
|
pid: PID,
|
||||||
) -> Option<SplittableBufferConnection> {
|
) -> Option<SplittableBufferConnection> {
|
||||||
info!("attempting to connect to: {}", param.forward_destination);
|
info!("attempting to connect to: {}", param.forward_destination);
|
||||||
let mut stream = match TcpStream::connect(param.forward_destination).await {
|
let mut stream = match TcpStream::connect(param.forward_destination).await {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ edition = "2024"
|
||||||
tokio = { version = "1.47.0", features = ["full"] }
|
tokio = { version = "1.47.0", features = ["full"] }
|
||||||
prudpv0 = { path = "../prudpv0", optional = true }
|
prudpv0 = { path = "../prudpv0", optional = true }
|
||||||
prudpv1 = { path = "../prudpv1", optional = true }
|
prudpv1 = { path = "../prudpv1", optional = true }
|
||||||
|
prudplite = { path = "../prudplite", optional = true }
|
||||||
proxy-common = { path = "../proxy-common" }
|
proxy-common = { path = "../proxy-common" }
|
||||||
cfg-if = "1.0.4"
|
cfg-if = "1.0.4"
|
||||||
rnex-core = { path = "../rnex-core", version = "0.1.1" }
|
rnex-core = { path = "../rnex-core", version = "0.1.1" }
|
||||||
|
|
@ -15,6 +16,7 @@ log = "0.4.25"
|
||||||
[features]
|
[features]
|
||||||
prudpv0 = ["dep:prudpv0"]
|
prudpv0 = ["dep:prudpv0"]
|
||||||
prudpv1 = ["dep:prudpv1"]
|
prudpv1 = ["dep:prudpv1"]
|
||||||
|
prudplite = ["dep:prudplite"]
|
||||||
friends = ["prudpv0", "prudpv0/friends"]
|
friends = ["prudpv0", "prudpv0/friends"]
|
||||||
splatoon = ["prudpv1"]
|
splatoon = ["prudpv1"]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ cfg_if! {
|
||||||
pub use prudpv0::*;
|
pub use prudpv0::*;
|
||||||
} else if #[cfg(feature = "prudpv1")] {
|
} else if #[cfg(feature = "prudpv1")] {
|
||||||
pub use prudpv1::*;
|
pub use prudpv1::*;
|
||||||
|
} else if #[cfg(feature = "prudplite")]{
|
||||||
|
pub use prudplite::*;
|
||||||
} else {
|
} else {
|
||||||
compile_error!("no proxy type has been set");
|
compile_error!("no proxy type has been set");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
18
prudplite/Cargo.toml
Normal file
18
prudplite/Cargo.toml
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
[package]
|
||||||
|
name = "prudplite"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
nx = []
|
||||||
|
v4-3-11 = []
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
rnex-core = { path = "../rnex-core", version = "0.1.1" }
|
||||||
|
tokio = { version = "1.47.0", features = ["full"] }
|
||||||
|
bytemuck = { version = "1.23.1", features = ["derive"] }
|
||||||
|
proxy-common = {path = "../proxy-common"}
|
||||||
|
tokio-tungstenite = {version = "0.28.0", features = ["rustls", "rustls-tls-native-roots"]}
|
||||||
|
log = "0.4.25"
|
||||||
|
futures-util = "0.3.31"
|
||||||
|
v-byte-helpers = { git = "https://github.com/RusticMaple/VByteMacros", version = "0.1.1" }
|
||||||
14
prudplite/src/crypto/insecure.rs
Normal file
14
prudplite/src/crypto/insecure.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
use rnex_core::PID;
|
||||||
|
|
||||||
|
use crate::crypto::Crypto;
|
||||||
|
|
||||||
|
pub struct Insecure;
|
||||||
|
|
||||||
|
impl Crypto for Insecure {
|
||||||
|
fn new_connection(&self, data: &[u8]) -> Option<(PID, Vec<u8>)> {
|
||||||
|
Some((100, vec![]))
|
||||||
|
}
|
||||||
|
fn new() -> Self {
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
}
|
||||||
9
prudplite/src/crypto/mod.rs
Normal file
9
prudplite/src/crypto/mod.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
use rnex_core::PID;
|
||||||
|
|
||||||
|
pub mod insecure;
|
||||||
|
pub mod secure;
|
||||||
|
|
||||||
|
pub trait Crypto: 'static + Send + Sync {
|
||||||
|
fn new_connection(&self, data: &[u8]) -> Option<(PID, Vec<u8>)>;
|
||||||
|
fn new() -> Self;
|
||||||
|
}
|
||||||
27
prudplite/src/crypto/secure.rs
Normal file
27
prudplite/src/crypto/secure.rs
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
use rnex_core::{
|
||||||
|
PID, executables::common::SECURE_SERVER_ACCOUNT, nex::account::Account,
|
||||||
|
prudp::ticket::read_secure_connection_data, rmc::structures::RmcSerialize,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::crypto::Crypto;
|
||||||
|
|
||||||
|
pub struct Secure(&'static Account);
|
||||||
|
|
||||||
|
impl Crypto for Secure {
|
||||||
|
fn new_connection(&self, data: &[u8]) -> Option<(PID, Vec<u8>)> {
|
||||||
|
let (_, pid, check_value) = read_secure_connection_data(data, &self.0)?;
|
||||||
|
|
||||||
|
let check_value_response = check_value + 1;
|
||||||
|
|
||||||
|
let data = bytemuck::bytes_of(&check_value_response);
|
||||||
|
|
||||||
|
let mut response = Vec::new();
|
||||||
|
|
||||||
|
data.serialize(&mut response).ok()?;
|
||||||
|
|
||||||
|
Some((pid, response))
|
||||||
|
}
|
||||||
|
fn new() -> Self {
|
||||||
|
Self(&SECURE_SERVER_ACCOUNT)
|
||||||
|
}
|
||||||
|
}
|
||||||
309
prudplite/src/lib.rs
Normal file
309
prudplite/src/lib.rs
Normal file
|
|
@ -0,0 +1,309 @@
|
||||||
|
pub mod crypto;
|
||||||
|
mod packet;
|
||||||
|
|
||||||
|
use std::{collections::HashMap, net::SocketAddr, sync::Arc};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
crypto::{Crypto, insecure::Insecure, secure::Secure},
|
||||||
|
packet::{LiteHeader, LitePacket, PacketSpecificData, StreamTypes, create_packet_from},
|
||||||
|
};
|
||||||
|
use futures_util::{SinkExt, StreamExt};
|
||||||
|
use log::{error, info, warn};
|
||||||
|
use proxy_common::{ProxyStartupParam, new_backend_connection};
|
||||||
|
use rnex_core::{
|
||||||
|
PID,
|
||||||
|
prudp::{
|
||||||
|
socket_addr::PRUDPSockAddr,
|
||||||
|
types_flags::{
|
||||||
|
TypesFlags,
|
||||||
|
flags::{ACK, NEED_ACK, RELIABLE},
|
||||||
|
types::{CONNECT, DATA, DISCONNECT, SYN},
|
||||||
|
},
|
||||||
|
virtual_port::VirtualPort,
|
||||||
|
},
|
||||||
|
util::SplittableBufferConnection,
|
||||||
|
};
|
||||||
|
use tokio::net::{TcpListener, TcpStream};
|
||||||
|
use tokio_tungstenite::{
|
||||||
|
WebSocketStream,
|
||||||
|
tungstenite::{
|
||||||
|
Bytes, Message, client::IntoClientRequest, http::header::ACCESS_CONTROL_REQUEST_METHOD,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConnectionState {
|
||||||
|
param: Arc<ProxyStartupParam>,
|
||||||
|
active: bool,
|
||||||
|
websocket: WebSocketStream<TcpStream>,
|
||||||
|
pid: PID,
|
||||||
|
backend_conn: SplittableBufferConnection,
|
||||||
|
addr: PRUDPSockAddr,
|
||||||
|
incoming_reliable: HashMap<u16, LitePacket<Bytes>>,
|
||||||
|
client_reliable_counter: u16,
|
||||||
|
server_reliable_counter: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConnectionState {
|
||||||
|
pub async fn handle_incoming_prudp(&mut self, packet: LitePacket<Bytes>, sorted: bool) {
|
||||||
|
let Some(header) = packet.header() else {
|
||||||
|
warn!("invalid data on connection");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (header.types_flags.get_flags() & NEED_ACK) != 0 {
|
||||||
|
let data = create_packet_from(
|
||||||
|
LiteHeader {
|
||||||
|
stream_types: StreamTypes::new(
|
||||||
|
self.param.virtual_port.get_stream_type(),
|
||||||
|
self.addr.virtual_port.get_stream_type(),
|
||||||
|
),
|
||||||
|
source_port: self.param.virtual_port.get_port_number(),
|
||||||
|
destination_port: self.addr.virtual_port.get_port_number(),
|
||||||
|
fragment_id: header.fragment_id,
|
||||||
|
types_flags: TypesFlags::default()
|
||||||
|
.types(header.types_flags.get_types())
|
||||||
|
.flags(ACK),
|
||||||
|
sequence_id: header.sequence_id,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
&[],
|
||||||
|
&[],
|
||||||
|
);
|
||||||
|
let data: Bytes = data.into();
|
||||||
|
if header.types_flags.get_types() == DISCONNECT {
|
||||||
|
self.websocket.send(Message::Binary(data.clone())).await;
|
||||||
|
self.websocket.send(Message::Binary(data.clone())).await;
|
||||||
|
}
|
||||||
|
self.websocket.send(Message::Binary(data)).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header.types_flags.get_flags() & ACK) != 0 {
|
||||||
|
// we can just safely ignore acks, we ARE sending over tcp after all already guarantees that our packets will arrive
|
||||||
|
// we can however not guarantee the order of incoming client packets so we should still take care of that
|
||||||
|
// (the client might be doing some funny things which we dont know of)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header.types_flags.get_flags() & RELIABLE != 0) & !sorted {
|
||||||
|
self.incoming_reliable.insert(header.sequence_id, packet);
|
||||||
|
if self.incoming_reliable.len() > 5 {
|
||||||
|
self.active = false;
|
||||||
|
warn!("client is spamming out of order reliable packets, throwing out");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
match header.types_flags.get_types() {
|
||||||
|
DATA => {
|
||||||
|
if header.fragment_id != 0 {
|
||||||
|
warn!("fragmented packets arent yet supported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(payload) = packet.payload() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
self.backend_conn.send(payload.into()).await;
|
||||||
|
}
|
||||||
|
PING => {}
|
||||||
|
v => {
|
||||||
|
info!("unimplemented packet type: {}", v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub async fn process_reliable(&mut self) {
|
||||||
|
while let Some(v) = self.incoming_reliable.remove(&self.client_reliable_counter) {
|
||||||
|
self.handle_incoming_prudp(v, true).await;
|
||||||
|
self.client_reliable_counter += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub async fn handle_connection(&mut self) {
|
||||||
|
while self.active {
|
||||||
|
tokio::select! {
|
||||||
|
v = self.websocket.next() => {
|
||||||
|
match v {
|
||||||
|
Some(Ok(Message::Binary(v))) => {
|
||||||
|
self.handle_incoming_prudp(LitePacket::new(v), false).await;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
info!("client disconnected or errored out");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v = self.backend_conn.recv() => {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn websocket_thread_unconnected<C: Crypto>(
|
||||||
|
param: Arc<ProxyStartupParam>,
|
||||||
|
crypto: Arc<C>,
|
||||||
|
conn: TcpStream,
|
||||||
|
addr: SocketAddr,
|
||||||
|
) {
|
||||||
|
let mut websocket = match tokio_tungstenite::accept_async(conn).await {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
error!("error accepting websocket connection: {}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
while let Some(Ok(v)) = websocket.next().await {
|
||||||
|
match v {
|
||||||
|
Message::Binary(b) => {
|
||||||
|
let packet = LitePacket::new(b);
|
||||||
|
|
||||||
|
let Some(header) = packet.header() else {
|
||||||
|
error!("got malformed message, disconnecting");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
match header.types_flags.get_types() {
|
||||||
|
SYN => {
|
||||||
|
let Some(supported) = packet.packet_specific_iter() else {
|
||||||
|
error!("got malformed message, disconnecting");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(PacketSpecificData::SupportedFunctions(s)) = supported
|
||||||
|
.into_iter()
|
||||||
|
.find(|v| matches!(v, PacketSpecificData::SupportedFunctions(_)))
|
||||||
|
else {
|
||||||
|
error!("got malformed message, disconnecting");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let data = create_packet_from(
|
||||||
|
LiteHeader {
|
||||||
|
destination_port: header.source_port,
|
||||||
|
source_port: param.virtual_port.get_port_number(),
|
||||||
|
stream_types: StreamTypes::new(
|
||||||
|
param.virtual_port.get_stream_type(),
|
||||||
|
header.stream_types.source(),
|
||||||
|
),
|
||||||
|
fragment_id: 0,
|
||||||
|
sequence_id: 0,
|
||||||
|
types_flags: TypesFlags::default().types(SYN).flags(ACK),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
&[
|
||||||
|
PacketSpecificData::SupportedFunctions(s & 0xFF),
|
||||||
|
PacketSpecificData::ConnectionSignature([0; 16]),
|
||||||
|
],
|
||||||
|
&[],
|
||||||
|
);
|
||||||
|
websocket.send(Message::Binary(data.into())).await;
|
||||||
|
}
|
||||||
|
CONNECT => {
|
||||||
|
let Some(supported) = packet.packet_specific_iter() else {
|
||||||
|
error!("got malformed message, disconnecting");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(PacketSpecificData::SupportedFunctions(s)) = supported
|
||||||
|
.into_iter()
|
||||||
|
.find(|v| matches!(v, PacketSpecificData::SupportedFunctions(_)))
|
||||||
|
else {
|
||||||
|
error!("got malformed message, disconnecting");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(data) = packet.payload() else {
|
||||||
|
error!("got malformed message, disconnecting");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some((pid, data)) = crypto.new_connection(data) else {
|
||||||
|
error!("invalid login data");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let data = create_packet_from(
|
||||||
|
LiteHeader {
|
||||||
|
destination_port: header.source_port,
|
||||||
|
source_port: param.virtual_port.get_port_number(),
|
||||||
|
stream_types: StreamTypes::new(
|
||||||
|
param.virtual_port.get_stream_type(),
|
||||||
|
header.stream_types.source(),
|
||||||
|
),
|
||||||
|
fragment_id: 0,
|
||||||
|
sequence_id: 0,
|
||||||
|
types_flags: TypesFlags::default().types(CONNECT).flags(ACK),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
&[
|
||||||
|
PacketSpecificData::SupportedFunctions(s & 0xFF),
|
||||||
|
PacketSpecificData::ConnectionSignature([0; 16]),
|
||||||
|
],
|
||||||
|
&data,
|
||||||
|
);
|
||||||
|
websocket.send(Message::Binary(data.into())).await;
|
||||||
|
|
||||||
|
let addr = PRUDPSockAddr::new(
|
||||||
|
addr,
|
||||||
|
VirtualPort::new(header.source_port, header.stream_types.source()),
|
||||||
|
);
|
||||||
|
let Some(backend_conn) = new_backend_connection(¶m, addr, pid).await
|
||||||
|
else {
|
||||||
|
error!("unable to connect to backend");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let mut connection = ConnectionState {
|
||||||
|
active: true,
|
||||||
|
addr,
|
||||||
|
pid,
|
||||||
|
backend_conn,
|
||||||
|
client_reliable_counter: 2,
|
||||||
|
server_reliable_counter: 1,
|
||||||
|
param,
|
||||||
|
incoming_reliable: HashMap::new(),
|
||||||
|
websocket,
|
||||||
|
};
|
||||||
|
|
||||||
|
connection.handle_connection().await;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
v => {
|
||||||
|
error!(
|
||||||
|
"invalid packet type for unconnected client {}, disconnecting",
|
||||||
|
v,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v => {
|
||||||
|
error!("non binary message({:?}) , disconnecting", v);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn start_proxy<C: Crypto>(param: ProxyStartupParam) {
|
||||||
|
let param = Arc::new(param);
|
||||||
|
let crypto = Arc::new(C::new());
|
||||||
|
let listener = TcpListener::bind(param.self_private)
|
||||||
|
.await
|
||||||
|
.expect("unable to bind to port");
|
||||||
|
|
||||||
|
while let Ok((connection, addr)) = listener.accept().await {
|
||||||
|
let param = param.clone();
|
||||||
|
let crypto = crypto.clone();
|
||||||
|
tokio::spawn(websocket_thread_unconnected(
|
||||||
|
param, crypto, connection, addr,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn start_secure(param: ProxyStartupParam) {
|
||||||
|
start_proxy::<Secure>(param).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn start_insecure(param: ProxyStartupParam) {
|
||||||
|
start_proxy::<Insecure>(param).await;
|
||||||
|
}
|
||||||
45
prudplite/src/main.rs
Normal file
45
prudplite/src/main.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
use futures_util::{SinkExt, StreamExt};
|
||||||
|
use rnex_core::prudp::types_flags::{TypesFlags, flags::NEED_ACK, types::SYN};
|
||||||
|
use tokio_tungstenite::tungstenite::{Message, client::IntoClientRequest, http::header};
|
||||||
|
|
||||||
|
use crate::packet::{LiteHeader, LitePacket, PacketSpecificData, StreamTypes, create_packet_from};
|
||||||
|
|
||||||
|
mod packet;
|
||||||
|
|
||||||
|
const KEY: &str = "4eb18d39";
|
||||||
|
|
||||||
|
const URL: &str = "wss://g2DF33D01-lp1.s.n.srv.nintendo.net";
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
let login = URL.into_client_request().unwrap();
|
||||||
|
let (mut stream, response) = tokio_tungstenite::connect_async(login).await.unwrap();
|
||||||
|
|
||||||
|
println!("response: {:?}", response);
|
||||||
|
|
||||||
|
let packet = create_packet_from(
|
||||||
|
LiteHeader {
|
||||||
|
stream_types: StreamTypes::new(10, 10),
|
||||||
|
source_port: 1,
|
||||||
|
destination_port: 1,
|
||||||
|
fragment_id: 0,
|
||||||
|
types_flags: TypesFlags::default().types(SYN).flags(NEED_ACK),
|
||||||
|
sequence_id: 0,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
&[PacketSpecificData::SupportedFunctions(0x8)],
|
||||||
|
&[],
|
||||||
|
);
|
||||||
|
|
||||||
|
println!("sending ack");
|
||||||
|
stream.send(Message::Binary(packet.into())).await.unwrap();
|
||||||
|
println!("waiting for response");
|
||||||
|
let packet = stream.next().await.unwrap();
|
||||||
|
let Message::Binary(packet) = packet.unwrap() else {
|
||||||
|
panic!()
|
||||||
|
};
|
||||||
|
let packet = LitePacket::new(packet);
|
||||||
|
|
||||||
|
let header = packet.header().unwrap();
|
||||||
|
|
||||||
|
println!("{:?}", header);
|
||||||
|
}
|
||||||
223
prudplite/src/packet.rs
Normal file
223
prudplite/src/packet.rs
Normal file
|
|
@ -0,0 +1,223 @@
|
||||||
|
use std::{
|
||||||
|
fmt::Debug,
|
||||||
|
io::{self, Cursor, Read, Write},
|
||||||
|
};
|
||||||
|
|
||||||
|
use bytemuck::{Pod, Zeroable, bytes_of};
|
||||||
|
use futures_util::Stream;
|
||||||
|
use rnex_core::prudp::types_flags::TypesFlags;
|
||||||
|
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
||||||
|
|
||||||
|
#[derive(Pod, Zeroable, Copy, Clone, Default, Debug)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct LiteHeader {
|
||||||
|
pub magic: u8,
|
||||||
|
pub packet_specific_length: u8,
|
||||||
|
pub payload_size: u16,
|
||||||
|
pub stream_types: StreamTypes,
|
||||||
|
pub source_port: u8,
|
||||||
|
pub destination_port: u8,
|
||||||
|
pub fragment_id: u8,
|
||||||
|
pub types_flags: TypesFlags,
|
||||||
|
pub sequence_id: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum PacketSpecificData {
|
||||||
|
SupportedFunctions(u32),
|
||||||
|
ConnectionSignature([u8; 16]),
|
||||||
|
LiteSignature([u8; 16]),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PacketSpecificData {
|
||||||
|
fn consume(reader: &mut impl Read) -> io::Result<Self> {
|
||||||
|
let mut option_id = 0;
|
||||||
|
reader.read_exact(&mut [option_id])?;
|
||||||
|
let mut size = 0;
|
||||||
|
reader.read_exact(&mut [size])?;
|
||||||
|
|
||||||
|
match option_id {
|
||||||
|
0 => {
|
||||||
|
if size != 4 {
|
||||||
|
Err(io::Error::other(
|
||||||
|
"invalid option size for supported functions",
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Ok(Self::SupportedFunctions(reader.read_le_u32()?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1 => {
|
||||||
|
if size != 16 {
|
||||||
|
Err(io::Error::other(
|
||||||
|
"invalid option size for connection signature",
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Ok(Self::ConnectionSignature(
|
||||||
|
reader.read_struct(IS_BIG_ENDIAN)?,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
0x80 => {
|
||||||
|
if size != 16 {
|
||||||
|
Err(io::Error::other("invalid option size for lite signature"))
|
||||||
|
} else {
|
||||||
|
Ok(Self::LiteSignature(reader.read_struct(IS_BIG_ENDIAN)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Err(io::Error::other("invalid option id")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_size(&self) -> usize {
|
||||||
|
2 + match self {
|
||||||
|
PacketSpecificData::SupportedFunctions(_) => 4,
|
||||||
|
Self::ConnectionSignature(_) => 16,
|
||||||
|
Self::LiteSignature(_) => 16,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_self(&self, writer: &mut impl Write) -> io::Result<()> {
|
||||||
|
match self {
|
||||||
|
PacketSpecificData::SupportedFunctions(v) => {
|
||||||
|
writer.write_all(&[0, 4])?;
|
||||||
|
writer.write_all(&v.to_le_bytes())?;
|
||||||
|
}
|
||||||
|
Self::ConnectionSignature(v) => {
|
||||||
|
writer.write_all(&[1, 16])?;
|
||||||
|
writer.write_all(&v[..])?;
|
||||||
|
}
|
||||||
|
Self::LiteSignature(v) => {
|
||||||
|
writer.write_all(&[0x80, 16])?;
|
||||||
|
writer.write_all(&v[..])?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LitePacket<T: AsRef<[u8]>>(T);
|
||||||
|
|
||||||
|
pub struct PacketSpecificIter<'a>(Cursor<&'a [u8]>);
|
||||||
|
|
||||||
|
impl<'a> Iterator for PacketSpecificIter<'a> {
|
||||||
|
type Item = PacketSpecificData;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
PacketSpecificData::consume(&mut self.0).ok()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: AsRef<[u8]>> LitePacket<T> {
|
||||||
|
pub fn new(inner: T) -> Self {
|
||||||
|
Self(inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn header(&self) -> Option<&LiteHeader> {
|
||||||
|
bytemuck::try_from_bytes(self.0.as_ref().get(..size_of::<LiteHeader>())?).ok()
|
||||||
|
}
|
||||||
|
pub fn header_mut(&mut self) -> Option<&mut LiteHeader>
|
||||||
|
where
|
||||||
|
T: AsMut<[u8]>,
|
||||||
|
{
|
||||||
|
bytemuck::try_from_bytes_mut(self.0.as_mut().get_mut(..size_of::<LiteHeader>())?).ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn payload(&self) -> Option<&[u8]> {
|
||||||
|
let header = self.header()?;
|
||||||
|
self.0
|
||||||
|
.as_ref()
|
||||||
|
.get(size_of::<LiteHeader>() + header.packet_specific_length as usize..)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn payload_mut(&mut self) -> Option<&mut [u8]>
|
||||||
|
where
|
||||||
|
T: AsMut<[u8]>,
|
||||||
|
{
|
||||||
|
let len = self.header()?.packet_specific_length;
|
||||||
|
self.0
|
||||||
|
.as_mut()
|
||||||
|
.get_mut(size_of::<LiteHeader>() + len as usize..)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn packet_specific_raw(&self) -> Option<&[u8]> {
|
||||||
|
let header = self.header()?;
|
||||||
|
self.0.as_ref().get(
|
||||||
|
size_of::<LiteHeader>()
|
||||||
|
..size_of::<LiteHeader>() + header.packet_specific_length as usize,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
pub fn packet_specific_raw_mut(&mut self) -> Option<&mut [u8]>
|
||||||
|
where
|
||||||
|
T: AsMut<[u8]>,
|
||||||
|
{
|
||||||
|
let len = self.header()?.packet_specific_length;
|
||||||
|
self.0
|
||||||
|
.as_mut()
|
||||||
|
.get_mut(size_of::<LiteHeader>()..size_of::<LiteHeader>() + len as usize)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn packet_specific_iter(&self) -> Option<PacketSpecificIter> {
|
||||||
|
self.packet_specific_raw()
|
||||||
|
.map(Cursor::new)
|
||||||
|
.map(PacketSpecificIter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_packet_from(
|
||||||
|
header: LiteHeader,
|
||||||
|
specific_data: &[PacketSpecificData],
|
||||||
|
data: &[u8],
|
||||||
|
) -> Vec<u8> {
|
||||||
|
let specific_size: usize = specific_data.iter().map(|v| v.write_size()).sum();
|
||||||
|
let mut packet = LitePacket::new(vec![
|
||||||
|
0u8;
|
||||||
|
size_of::<LiteHeader>() + specific_size + data.len()
|
||||||
|
]);
|
||||||
|
|
||||||
|
*packet.header_mut().expect("packet malformed in creation") = LiteHeader {
|
||||||
|
magic: 0x80,
|
||||||
|
packet_specific_length: specific_size as u8,
|
||||||
|
payload_size: data.len() as u16,
|
||||||
|
..header
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut cursor = Cursor::new(
|
||||||
|
packet
|
||||||
|
.packet_specific_raw_mut()
|
||||||
|
.expect("packet malformed in creation"),
|
||||||
|
);
|
||||||
|
|
||||||
|
for specific in specific_data {
|
||||||
|
specific.write_self(&mut cursor).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
packet
|
||||||
|
.payload_mut()
|
||||||
|
.expect("packet malformed in creation")
|
||||||
|
.copy_from_slice(data);
|
||||||
|
|
||||||
|
packet.0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Pod, Zeroable, Copy, Clone, Default)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct StreamTypes(u8);
|
||||||
|
|
||||||
|
impl Debug for StreamTypes {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "({},{})", self.source(), self.destination())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StreamTypes {
|
||||||
|
pub fn new(source_stream: u8, dest_stream: u8) -> Self {
|
||||||
|
Self((source_stream & 0xF << 4) & dest_stream & 0xF)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn source(&self) -> u8 {
|
||||||
|
self.0 >> 4
|
||||||
|
}
|
||||||
|
pub fn destination(&self) -> u8 {
|
||||||
|
self.0 & 0xF
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -100,7 +100,7 @@ impl<C: Crypto> Server<C> {
|
||||||
};
|
};
|
||||||
/* we leave the sequence id as is for now as it defaults to 0 */
|
/* we leave the sequence id as is for now as it defaults to 0 */
|
||||||
|
|
||||||
*packet.checksum_mut().expect("packet malformed in creation") =
|
packet.checksum_mut().expect("packet malformed in creation") =
|
||||||
self.crypto.calculate_checksum(
|
self.crypto.calculate_checksum(
|
||||||
packet
|
packet
|
||||||
.checksummed_data()
|
.checksummed_data()
|
||||||
|
|
@ -434,7 +434,7 @@ impl<C: Crypto> Server<C> {
|
||||||
|
|
||||||
info!("len: {}", packet.0.len());
|
info!("len: {}", packet.0.len());
|
||||||
|
|
||||||
let addr = PRUDPSockAddr::new(addr, header.source);
|
let addr = PRUDPSockAddr::new(SocketAddr::V4(addr), header.source);
|
||||||
|
|
||||||
if let Some(conn) = self.get_connection(addr).await {
|
if let Some(conn) = self.get_connection(addr).await {
|
||||||
let mut inner = conn.inner.lock().await;
|
let mut inner = conn.inner.lock().await;
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,11 @@ ureq = "3.1.4"
|
||||||
rmc_struct_header = []
|
rmc_struct_header = []
|
||||||
guest_login = []
|
guest_login = []
|
||||||
friends = ["guest_login"]
|
friends = ["guest_login"]
|
||||||
|
big_pid = []
|
||||||
|
v3-8-15 = ["rmc_struct_header"]
|
||||||
|
v4-3-11 = ["v3-8-15"]
|
||||||
|
nx = ["big_pid"]
|
||||||
|
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "rmc_serialization"
|
name = "rmc_serialization"
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ async fn main() {
|
||||||
if #[cfg(feature = "friends")]{
|
if #[cfg(feature = "friends")]{
|
||||||
start_friends_backend().await;
|
start_friends_backend().await;
|
||||||
} else {
|
} else {
|
||||||
|
use rnex_core::executables::regular_backend;
|
||||||
regular_backend::start_regular_backend().await
|
regular_backend::start_regular_backend().await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,65 @@
|
||||||
use std::sync::{Arc, atomic::AtomicU32};
|
use std::{
|
||||||
|
io::Cursor,
|
||||||
|
net::SocketAddrV4,
|
||||||
|
sync::{Arc, atomic::AtomicU32},
|
||||||
|
};
|
||||||
|
|
||||||
|
use log::error;
|
||||||
|
use tokio::net::TcpListener;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
executables::common::new_simple_backend,
|
executables::common::{OWN_IP_PRIVATE, SERVER_PORT, new_simple_backend},
|
||||||
nex::friends_handler::{FriendsManager, FriendsUser},
|
nex::friends_handler::{FriendsGuest, FriendsManager, FriendsUser},
|
||||||
|
reggie::UnitPacketRead,
|
||||||
|
rmc::{
|
||||||
|
protocols::{RmcCallable, new_rmc_gateway_connection},
|
||||||
|
structures::RmcSerialize,
|
||||||
|
},
|
||||||
|
rnex_proxy_common::ConnectionInitData,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub async fn start_friends_backend() {
|
pub async fn start_friends_backend() {
|
||||||
let fm = Arc::new(FriendsManager {
|
let fm = Arc::new(FriendsManager {
|
||||||
cid_counter: AtomicU32::new(1),
|
cid_counter: AtomicU32::new(1),
|
||||||
});
|
});
|
||||||
|
let listen = TcpListener::bind(SocketAddrV4::new(*OWN_IP_PRIVATE, *SERVER_PORT))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
while let Ok((mut stream, _addr)) = listen.accept().await {
|
||||||
|
let buffer = match stream.read_buffer().await {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
error!(
|
||||||
|
"an error ocurred whilest reading connection data buffer: {:?}",
|
||||||
|
e
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
new_simple_backend(move |c, r| {
|
let user_connection_data = ConnectionInitData::deserialize(&mut Cursor::new(buffer));
|
||||||
|
|
||||||
|
let c = match user_connection_data {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
error!("an error ocurred whilest reading connection data: {:?}", e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
let fm = fm.clone();
|
let fm = fm.clone();
|
||||||
|
if c.pid != 100 {
|
||||||
|
new_rmc_gateway_connection(stream.into(), move |r| {
|
||||||
Arc::new_cyclic(move |this| FriendsUser {
|
Arc::new_cyclic(move |this| FriendsUser {
|
||||||
fm,
|
fm,
|
||||||
addr: c.prudpsock_addr,
|
addr: c.prudpsock_addr,
|
||||||
pid: c.pid,
|
pid: c.pid,
|
||||||
})
|
})
|
||||||
})
|
});
|
||||||
.await;
|
} else {
|
||||||
|
Arc::new_cyclic(move |this| FriendsGuest {
|
||||||
|
fm,
|
||||||
|
addr: c.prudpsock_addr,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
use std::{env, result};
|
use crate::grpc::account::Error::SomethingHappened;
|
||||||
|
use json::{JsonValue, object};
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use rnex_core::PID;
|
||||||
use std::array::TryFromSliceError;
|
use std::array::TryFromSliceError;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use json::{object, JsonValue};
|
use std::{env, result};
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::task::{spawn_blocking, JoinError};
|
use tokio::task::{JoinError, spawn_blocking};
|
||||||
use crate::grpc::account::Error::SomethingHappened;
|
|
||||||
static API_KEY: Lazy<String> = Lazy::new(|| {
|
static API_KEY: Lazy<String> = Lazy::new(|| {
|
||||||
let key = env::var("ACCOUNT_GQL_API_KEY")
|
let key = env::var("ACCOUNT_GQL_API_KEY").expect("no graphql ip specified");
|
||||||
.expect("no graphql ip specified");
|
|
||||||
|
|
||||||
key
|
key
|
||||||
});
|
});
|
||||||
|
|
@ -20,8 +20,6 @@ static CLIENT_URI: Lazy<String> = Lazy::new(||{
|
||||||
.expect("no graphql ip specified")
|
.expect("no graphql ip specified")
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
|
@ -35,7 +33,7 @@ pub enum Error{
|
||||||
#[error("something happened")]
|
#[error("something happened")]
|
||||||
SomethingHappened,
|
SomethingHappened,
|
||||||
#[error("error joining blocking task: {0}")]
|
#[error("error joining blocking task: {0}")]
|
||||||
Join(#[from] JoinError)
|
Join(#[from] JoinError),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Result<T> = result::Result<T, Error>;
|
pub type Result<T> = result::Result<T, Error>;
|
||||||
|
|
@ -70,8 +68,9 @@ impl Client{
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_nex_password(&mut self , pid: u32) -> Result<[u8; 16]>{
|
pub async fn get_nex_password(&mut self, pid: PID) -> Result<[u8; 16]> {
|
||||||
let req = self.do_request(object!{
|
let req = self
|
||||||
|
.do_request(object! {
|
||||||
"query": r"query($pid: Int!){
|
"query": r"query($pid: Int!){
|
||||||
userByPid(pid: $pid){
|
userByPid(pid: $pid){
|
||||||
nexPassword
|
nexPassword
|
||||||
|
|
@ -80,18 +79,24 @@ impl Client{
|
||||||
"variables": {
|
"variables": {
|
||||||
"pid": pid
|
"pid": pid
|
||||||
}
|
}
|
||||||
}).await?;
|
})
|
||||||
|
.await?;
|
||||||
|
|
||||||
let Some(val) = req.entries()
|
let Some(val) = req
|
||||||
|
.entries()
|
||||||
.find(|v| v.0 == "data")
|
.find(|v| v.0 == "data")
|
||||||
.ok_or(SomethingHappened)?.1
|
.ok_or(SomethingHappened)?
|
||||||
|
.1
|
||||||
.entries()
|
.entries()
|
||||||
.find(|v| v.0 == "userByPid")
|
.find(|v| v.0 == "userByPid")
|
||||||
.ok_or(SomethingHappened)?.1
|
.ok_or(SomethingHappened)?
|
||||||
|
.1
|
||||||
.entries()
|
.entries()
|
||||||
.find(|v| v.0 == "nexPassword")
|
.find(|v| v.0 == "nexPassword")
|
||||||
.ok_or(SomethingHappened)?.1
|
.ok_or(SomethingHappened)?
|
||||||
.as_str() else {
|
.1
|
||||||
|
.as_str()
|
||||||
|
else {
|
||||||
return Err(SomethingHappened);
|
return Err(SomethingHappened);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -109,8 +114,6 @@ impl Client{
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
pub struct Client(AccountClient<InterceptedService<Channel, InterceptorFunc>>);
|
pub struct Client(AccountClient<InterceptedService<Channel, InterceptorFunc>>);
|
||||||
|
|
|
||||||
|
|
@ -6,18 +6,21 @@ use hmac::Mac;
|
||||||
use md5::{Digest, Md5};
|
use md5::{Digest, Md5};
|
||||||
use rc4::KeyInit;
|
use rc4::KeyInit;
|
||||||
use rc4::cipher::StreamCipherCoreWrapper;
|
use rc4::cipher::StreamCipherCoreWrapper;
|
||||||
use rc4::consts::U16;
|
|
||||||
use rc4::{Rc4, Rc4Core, StreamCipher};
|
use rc4::{Rc4, Rc4Core, StreamCipher};
|
||||||
use rnex_core::rmc::structures::RmcSerialize;
|
use rnex_core::rmc::structures::RmcSerialize;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
use typenum::U16;
|
||||||
use typenum::Unsigned;
|
use typenum::Unsigned;
|
||||||
|
|
||||||
use rnex_core::rmc::structures::Result;
|
use rnex_core::rmc::structures::Result;
|
||||||
|
|
||||||
|
use rnex_core::PID;
|
||||||
|
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(feature = "friends")]{
|
if #[cfg(feature = "friends")]{
|
||||||
pub type SESSION_KEY_LENGTH_TY = U16;
|
pub type SESSION_KEY_LENGTH_TY = U16;
|
||||||
} else {
|
} else {
|
||||||
|
use rc4::consts::U32;
|
||||||
pub type SESSION_KEY_LENGTH_TY = U32;
|
pub type SESSION_KEY_LENGTH_TY = U32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -25,7 +28,7 @@ pub const SESSION_KEY_LENGTH: usize = SESSION_KEY_LENGTH_TY::USIZE;
|
||||||
|
|
||||||
type Md5Hmac = Hmac<md5::Md5>;
|
type Md5Hmac = Hmac<md5::Md5>;
|
||||||
|
|
||||||
pub fn derive_key(pid: u32, password: &[u8]) -> [u8; 16] {
|
pub fn derive_key(pid: PID, password: &[u8]) -> [u8; 16] {
|
||||||
let iteration_count = 65000 + pid % 1024;
|
let iteration_count = 65000 + pid % 1024;
|
||||||
// we do one iteration out here to ensure the key is always 16 bytes
|
// we do one iteration out here to ensure the key is always 16 bytes
|
||||||
|
|
||||||
|
|
@ -125,12 +128,12 @@ impl RmcSerialize for KerberosDateTime {
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
pub struct TicketInternalData {
|
pub struct TicketInternalData {
|
||||||
pub issued_time: KerberosDateTime,
|
pub issued_time: KerberosDateTime,
|
||||||
pub pid: u32,
|
pub pid: PID,
|
||||||
pub session_key: [u8; SESSION_KEY_LENGTH],
|
pub session_key: [u8; SESSION_KEY_LENGTH],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TicketInternalData {
|
impl TicketInternalData {
|
||||||
pub(crate) fn new(pid: u32) -> Self {
|
pub(crate) fn new(pid: PID) -> Self {
|
||||||
Self {
|
Self {
|
||||||
issued_time: KerberosDateTime::now(),
|
issued_time: KerberosDateTime::now(),
|
||||||
pid,
|
pid,
|
||||||
|
|
@ -162,7 +165,7 @@ impl TicketInternalData {
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
pub struct Ticket {
|
pub struct Ticket {
|
||||||
pub session_key: [u8; SESSION_KEY_LENGTH],
|
pub session_key: [u8; SESSION_KEY_LENGTH],
|
||||||
pub pid: u32,
|
pub pid: PID,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ticket {
|
impl Ticket {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,10 @@
|
||||||
#![allow(async_fn_in_trait)]
|
#![allow(async_fn_in_trait)]
|
||||||
//#![warn(missing_docs)]
|
//#![warn(missing_docs)]
|
||||||
|
|
||||||
|
#[cfg(feature = "big_pid")]
|
||||||
|
pub type PID = u64;
|
||||||
|
#[cfg(not(feature = "big_pid"))]
|
||||||
|
pub type PID = u32;
|
||||||
|
|
||||||
extern crate self as rnex_core;
|
extern crate self as rnex_core;
|
||||||
|
|
||||||
|
|
@ -12,16 +15,16 @@ pub mod prudp;
|
||||||
pub mod rmc;
|
pub mod rmc;
|
||||||
//mod protocols;
|
//mod protocols;
|
||||||
|
|
||||||
|
pub mod common;
|
||||||
|
pub mod executables;
|
||||||
pub mod grpc;
|
pub mod grpc;
|
||||||
pub mod kerberos;
|
pub mod kerberos;
|
||||||
pub mod nex;
|
pub mod nex;
|
||||||
pub mod result;
|
|
||||||
pub mod versions;
|
|
||||||
pub mod common;
|
|
||||||
pub mod reggie;
|
pub mod reggie;
|
||||||
|
pub mod result;
|
||||||
pub mod rnex_proxy_common;
|
pub mod rnex_proxy_common;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
pub mod executables;
|
pub mod versions;
|
||||||
pub use macros::*;
|
pub use macros::*;
|
||||||
|
|
||||||
pub mod config {
|
pub mod config {
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
use macros::RmcSerialize;
|
use macros::RmcSerialize;
|
||||||
|
|
||||||
|
use rnex_core::PID;
|
||||||
|
|
||||||
#[derive(RmcSerialize, Clone)]
|
#[derive(RmcSerialize, Clone)]
|
||||||
pub struct Account {
|
pub struct Account {
|
||||||
pub pid: u32,
|
pub pid: PID,
|
||||||
pub username: String,
|
pub username: String,
|
||||||
pub kerbros_password: Box<[u8]>,
|
pub kerbros_password: Box<[u8]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Account {
|
impl Account {
|
||||||
pub fn new(pid: u32, username: &str, passwd: &str) -> Self {
|
pub fn new(pid: PID, username: &str, passwd: &str) -> Self {
|
||||||
let passwd_data = passwd.as_bytes();
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
kerbros_password: passwd.as_bytes().into(),
|
kerbros_password: passwd.as_bytes().into(),
|
||||||
username: username.into(),
|
username: username.into(),
|
||||||
|
|
@ -18,7 +18,7 @@ impl Account {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_raw_password(pid: u32, username: &str, passwd: &[u8]) -> Self {
|
pub fn new_raw_password(pid: PID, username: &str, passwd: &[u8]) -> Self {
|
||||||
Self {
|
Self {
|
||||||
kerbros_password: passwd.into(),
|
kerbros_password: passwd.into(),
|
||||||
username: username.into(),
|
username: username.into(),
|
||||||
|
|
@ -26,7 +26,7 @@ impl Account {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_login_data(&self) -> (u32, &[u8]) {
|
pub fn get_login_data(&self) -> (PID, &[u8]) {
|
||||||
(self.pid, &self.kerbros_password)
|
(self.pid, &self.kerbros_password)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ use crate::{define_rmc_proto, kerberos};
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use macros::rmc_struct;
|
use macros::rmc_struct;
|
||||||
|
use rnex_core::PID;
|
||||||
use rnex_core::kerberos::{KerberosDateTime, Ticket, derive_key};
|
use rnex_core::kerberos::{KerberosDateTime, Ticket, derive_key};
|
||||||
use rnex_core::nex::account::Account;
|
use rnex_core::nex::account::Account;
|
||||||
use rnex_core::rmc::protocols::OnlyRemote;
|
use rnex_core::rmc::protocols::OnlyRemote;
|
||||||
|
|
@ -16,7 +17,7 @@ use rnex_core::rmc::structures::connection_data::ConnectionDataOld;
|
||||||
use rnex_core::rmc::structures::qresult::QResult;
|
use rnex_core::rmc::structures::qresult::QResult;
|
||||||
use std::hash::{DefaultHasher, Hasher};
|
use std::hash::{DefaultHasher, Hasher};
|
||||||
use std::net::SocketAddrV4;
|
use std::net::SocketAddrV4;
|
||||||
use std::sync::{Arc, LazyLock, OnceLock};
|
use std::sync::{Arc, LazyLock};
|
||||||
|
|
||||||
define_rmc_proto!(
|
define_rmc_proto!(
|
||||||
proto AuthClientProtocol{
|
proto AuthClientProtocol{
|
||||||
|
|
@ -33,8 +34,8 @@ pub struct AuthHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_ticket(
|
pub fn generate_ticket(
|
||||||
source_act_login_data: (u32, &[u8]),
|
source_act_login_data: (PID, &[u8]),
|
||||||
dest_act_login_data: (u32, &[u8]),
|
dest_act_login_data: (PID, &[u8]),
|
||||||
) -> Box<[u8]> {
|
) -> Box<[u8]> {
|
||||||
let source_key = derive_key(source_act_login_data.0, source_act_login_data.1);
|
let source_key = derive_key(source_act_login_data.0, source_act_login_data.1);
|
||||||
let dest_key = derive_key(dest_act_login_data.0, dest_act_login_data.1);
|
let dest_key = derive_key(dest_act_login_data.0, dest_act_login_data.1);
|
||||||
|
|
@ -50,8 +51,28 @@ pub fn generate_ticket(
|
||||||
|
|
||||||
encrypted_session_ticket
|
encrypted_session_ticket
|
||||||
}
|
}
|
||||||
|
pub fn generate_ticket_with_string_user_key(
|
||||||
|
source_act: PID,
|
||||||
|
dest_act_login_data: (PID, &[u8]),
|
||||||
|
) -> (String, Box<[u8]>) {
|
||||||
|
let source_key: [u8; 8] = rand::random();
|
||||||
|
let key_string = hex::encode(source_key);
|
||||||
|
let key_data: [u8; 16] = key_string.as_bytes().try_into().unwrap();
|
||||||
|
let dest_key = derive_key(dest_act_login_data.0, dest_act_login_data.1);
|
||||||
|
|
||||||
async fn get_login_data_by_pid(pid: u32) -> Option<(u32, Box<[u8]>)> {
|
let internal_data = kerberos::TicketInternalData::new(source_act);
|
||||||
|
|
||||||
|
let encrypted_inner = internal_data.encrypt(dest_key);
|
||||||
|
let encrypted_session_ticket = Ticket {
|
||||||
|
pid: dest_act_login_data.0,
|
||||||
|
session_key: internal_data.session_key,
|
||||||
|
}
|
||||||
|
.encrypt(key_data, &encrypted_inner);
|
||||||
|
|
||||||
|
(key_string, encrypted_session_ticket)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_login_data_by_pid(pid: PID) -> Option<(PID, Box<[u8]>)> {
|
||||||
if pid == GUEST_ACCOUNT.pid {
|
if pid == GUEST_ACCOUNT.pid {
|
||||||
let source_login_data = GUEST_ACCOUNT.get_login_data();
|
let source_login_data = GUEST_ACCOUNT.get_login_data();
|
||||||
|
|
||||||
|
|
@ -84,7 +105,7 @@ impl AuthHandler {
|
||||||
pub async fn generate_ticket_from_name(
|
pub async fn generate_ticket_from_name(
|
||||||
&self,
|
&self,
|
||||||
name: &str,
|
name: &str,
|
||||||
) -> Result<(u32, Box<[u8]>), ErrorCode> {
|
) -> Result<(PID, Box<[u8]>), ErrorCode> {
|
||||||
#[cfg(feature = "guest_login")]
|
#[cfg(feature = "guest_login")]
|
||||||
{
|
{
|
||||||
if name == GUEST_ACCOUNT.username {
|
if name == GUEST_ACCOUNT.username {
|
||||||
|
|
@ -120,13 +141,39 @@ impl AuthHandler {
|
||||||
generate_ticket(source_login_data, destination_login_data),
|
generate_ticket(source_login_data, destination_login_data),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn generate_ticket_from_name_string_user_key(
|
||||||
|
&self,
|
||||||
|
name: &str,
|
||||||
|
) -> Result<(PID, String, Box<[u8]>), ErrorCode> {
|
||||||
|
#[cfg(feature = "guest_login")]
|
||||||
|
{
|
||||||
|
if name == GUEST_ACCOUNT.username {
|
||||||
|
let source_login_data = GUEST_ACCOUNT.get_login_data();
|
||||||
|
let destination_login_data = self.destination_server_acct.get_login_data();
|
||||||
|
|
||||||
|
return Ok((
|
||||||
|
source_login_data.0,
|
||||||
|
generate_ticket(source_login_data, destination_login_data),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let Ok(pid) = name.parse() else {
|
||||||
|
warn!("unable to connect to parse pid: {}", name);
|
||||||
|
return Err(ErrorCode::Core_InvalidArgument);
|
||||||
|
};
|
||||||
|
let destination_login_data = self.destination_server_acct.get_login_data();
|
||||||
|
|
||||||
|
let data = generate_ticket_with_string_user_key(pid, destination_login_data);
|
||||||
|
Ok((pid, data.0, data.1))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Auth for AuthHandler {
|
impl Auth for AuthHandler {
|
||||||
async fn login(
|
async fn login(
|
||||||
&self,
|
&self,
|
||||||
name: String,
|
name: String,
|
||||||
) -> Result<(QResult, u32, Vec<u8>, ConnectionDataOld, String), ErrorCode> {
|
) -> Result<(QResult, PID, Vec<u8>, ConnectionDataOld, String), ErrorCode> {
|
||||||
let (pid, ticket) = self.generate_ticket_from_name(&name).await?;
|
let (pid, ticket) = self.generate_ticket_from_name(&name).await?;
|
||||||
|
|
||||||
let result = QResult::success(Core_Unknown);
|
let result = QResult::success(Core_Unknown);
|
||||||
|
|
@ -157,12 +204,74 @@ impl Auth for AuthHandler {
|
||||||
info!("data: {:?}", ret);
|
info!("data: {:?}", ret);
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
cfg_if! {
|
||||||
|
|
||||||
|
if #[cfg(feature = "nx")]{
|
||||||
async fn login_ex(
|
async fn login_ex(
|
||||||
&self,
|
&self,
|
||||||
name: String,
|
name: String,
|
||||||
_extra_data: Any,
|
_extra_data: Any,
|
||||||
) -> Result<(QResult, u32, Vec<u8>, ConnectionData, String), ErrorCode> {
|
) -> Result<(QResult, PID, Vec<u8>, ConnectionData, String, String), ErrorCode> {
|
||||||
|
let (pid, key, ticket) = self.generate_ticket_from_name_string_user_key(&name).await?;
|
||||||
|
|
||||||
|
let result = QResult::success(Core_Unknown);
|
||||||
|
|
||||||
|
let mut hasher = DefaultHasher::new();
|
||||||
|
|
||||||
|
hasher.write(name.as_bytes());
|
||||||
|
|
||||||
|
let Ok(addr) = self.control_server.get_url(hasher.finish()).await else {
|
||||||
|
warn!("no secure proxies");
|
||||||
|
return Err(ErrorCode::Core_Exception);
|
||||||
|
};
|
||||||
|
|
||||||
|
let connection_data = ConnectionData {
|
||||||
|
station_url: station_url_from_sock_addr(addr),
|
||||||
|
special_station_url: "".to_string(),
|
||||||
|
//date_time: KerberosDateTime::new(1,1,1,1,1,1),
|
||||||
|
date_time: KerberosDateTime::now(),
|
||||||
|
special_protocols: Vec::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let ret = (
|
||||||
|
result,
|
||||||
|
pid,
|
||||||
|
ticket.into(),
|
||||||
|
connection_data,
|
||||||
|
self.build_name.to_string(),
|
||||||
|
key
|
||||||
|
);
|
||||||
|
|
||||||
|
info!("data: {:?}", ret);
|
||||||
|
Ok(ret)
|
||||||
|
}
|
||||||
|
async fn request_ticket(
|
||||||
|
&self,
|
||||||
|
source_pid: PID,
|
||||||
|
destination_pid: PID,
|
||||||
|
) -> Result<(QResult, Vec<u8>, String), ErrorCode> {
|
||||||
|
let Some((pid, _)) = get_login_data_by_pid(source_pid).await else {
|
||||||
|
return Err(ErrorCode::Core_Exception);
|
||||||
|
};
|
||||||
|
|
||||||
|
let desgination_login_data = if destination_pid == self.destination_server_acct.pid {
|
||||||
|
self.destination_server_acct.get_login_data()
|
||||||
|
} else {
|
||||||
|
return Err(ErrorCode::RendezVous_InvalidOperation);
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = QResult::success(Core_Unknown);
|
||||||
|
|
||||||
|
let ticket = generate_ticket_with_string_user_key(pid, desgination_login_data);
|
||||||
|
|
||||||
|
Ok((result, ticket.1.into(), ticket.0))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
async fn login_ex(
|
||||||
|
&self,
|
||||||
|
name: String,
|
||||||
|
_extra_data: Any,
|
||||||
|
) -> Result<(QResult, PID, Vec<u8>, ConnectionData, String), ErrorCode> {
|
||||||
let (pid, ticket) = self.generate_ticket_from_name(&name).await?;
|
let (pid, ticket) = self.generate_ticket_from_name(&name).await?;
|
||||||
|
|
||||||
let result = QResult::success(Core_Unknown);
|
let result = QResult::success(Core_Unknown);
|
||||||
|
|
@ -195,11 +304,10 @@ impl Auth for AuthHandler {
|
||||||
info!("data: {:?}", ret);
|
info!("data: {:?}", ret);
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn request_ticket(
|
async fn request_ticket(
|
||||||
&self,
|
&self,
|
||||||
source_pid: u32,
|
source_pid: PID,
|
||||||
destination_pid: u32,
|
destination_pid: PID,
|
||||||
) -> Result<(QResult, Vec<u8>), ErrorCode> {
|
) -> Result<(QResult, Vec<u8>), ErrorCode> {
|
||||||
let Some((pid, passwd)) = get_login_data_by_pid(source_pid).await else {
|
let Some((pid, passwd)) = get_login_data_by_pid(source_pid).await else {
|
||||||
return Err(ErrorCode::Core_Exception);
|
return Err(ErrorCode::Core_Exception);
|
||||||
|
|
@ -217,43 +325,14 @@ impl Auth for AuthHandler {
|
||||||
|
|
||||||
Ok((result, ticket.into()))
|
Ok((result, ticket.into()))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn get_pid(&self, _username: String) -> Result<u32, ErrorCode> {
|
async fn get_pid(&self, _username: String) -> Result<u32, ErrorCode> {
|
||||||
Err(ErrorCode::Core_Exception)
|
Err(ErrorCode::Core_Exception)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_name(&self, _pid: u32) -> Result<String, ErrorCode> {
|
async fn get_name(&self, _pid: PID) -> Result<String, ErrorCode> {
|
||||||
Err(ErrorCode::Core_Exception)
|
Err(ErrorCode::Core_Exception)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use rnex_core::rmc::response::RMCResponse;
|
|
||||||
use rnex_core::rmc::structures::RmcSerialize;
|
|
||||||
use rnex_core::rmc::structures::connection_data::ConnectionData;
|
|
||||||
use rnex_core::rmc::structures::qresult::QResult;
|
|
||||||
use std::io::Cursor;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test() {
|
|
||||||
return;
|
|
||||||
let stuff = hex::decode("200100000a0106000000028000000100010051b3995774000000a6321c7f78847c1c5e9fb825eb26bd91841f1a40d92fc694159666119cb13527f1463ac48ad42a63e6613ede67041554b1770978112e6f1f3e177a2bfc75933216dbe38f70133a1eb28e2ae32a4b5c4b0c3e3efd4c02907992e259b257270b57a9dbe7792f4721b07f8fafb9e32d50f2555c616a015c0000004b007072756470733a2f5049443d323b7369643d313b73747265616d3d31303b747970653d323b616464726573733d322e3234332e39352e3131333b706f72743d31303030313b4349443d3100000000000100002c153ba51f00000033006272616e63683a6f726967696e2f70726f6a6563742f7775702d61676d6a206275696c643a335f385f31355f323030345f3000").unwrap();
|
|
||||||
let stuff = RMCResponse::new(&mut Cursor::new(stuff)).unwrap();
|
|
||||||
|
|
||||||
let rnex_core::rmc::response::RMCResponseResult::Success { .. } = stuff.response_result
|
|
||||||
else {
|
|
||||||
panic!()
|
|
||||||
};
|
|
||||||
|
|
||||||
// let stuff = hex::decode("0100010051B399577400000085F1736FCFBE93660275A3FE36FED6C2EFC57222AC99A9219CF54170A415B02DF1463AC48AD42A6307813FDE67041554B177097832ED000F892D9551A09F88E9CB0388DC1BC9527CC7384556A3287B2A349ABBF7E34A5A3EC14C2287CC7F78DA616BC3B03A035347FBD2E9A505C8EF42447CD809015F0000004E007072756470733A2F73747265616D3D31303B747970653D323B616464726573733D3139322E3136382E3137382E3132303B706F72743D31303030313B4349443D313B5049443D323B7369643D310000000000010000CDF53AA51F00000033006272616E63683A6F726967696E2F70726F6A6563742F7775702D61676D6A206275696C643A335F385F31355F323030345F3000").unwrap();
|
|
||||||
let stuff = hex::decode("0100010051b399577400000037d3d4814d2b16dd546c94a75d32637b45f856b5abe73cf26cfaa235c5f2c1cef1463ac48ad42a637d873fde67041554b177097880cfa7e10bb810eaf686bfb0a0cf3d65b1f476ebc046d0855327986f557dca14fbb8594883c186b863f2206f22baa0309dbcc81da2f883cb2cdc12628ec7fced015c0000004b007072756470733a2f5049443d323b7369643d313b73747265616d3d31303b747970653d323b616464726573733d322e3234332e39352e3131333b706f72743d31303030313b4349443d310000000000010000b7f33aa51f00000033006272616e63683a6f726967696e2f70726f6a6563742f7775702d61676d6a206275696c643a335f385f31355f323030345f3000").unwrap();
|
|
||||||
|
|
||||||
let data = <(QResult, u32, Vec<u8>, ConnectionData, String) as RmcSerialize>::deserialize(
|
|
||||||
&mut Cursor::new(stuff),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
println!("data: {:?}", data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,12 @@ use rnex_core::rmc::response::ErrorCode::Core_Exception;
|
||||||
use rnex_core::prudp::socket_addr::PRUDPSockAddr;
|
use rnex_core::prudp::socket_addr::PRUDPSockAddr;
|
||||||
use rnex_core::rmc::response::ErrorCode;
|
use rnex_core::rmc::response::ErrorCode;
|
||||||
|
|
||||||
|
use rnex_core::PID;
|
||||||
|
|
||||||
pub async fn get_station_urls(
|
pub async fn get_station_urls(
|
||||||
station_urls: &[StationUrl],
|
station_urls: &[StationUrl],
|
||||||
addr: PRUDPSockAddr,
|
addr: PRUDPSockAddr,
|
||||||
pid: u32,
|
pid: PID,
|
||||||
cid: u32,
|
cid: u32,
|
||||||
) -> Result<Vec<StationUrl>, ErrorCode> {
|
) -> Result<Vec<StationUrl>, ErrorCode> {
|
||||||
let mut public_station: Option<StationUrl> = None;
|
let mut public_station: Option<StationUrl> = None;
|
||||||
|
|
@ -66,7 +68,7 @@ pub async fn get_station_urls(
|
||||||
|
|
||||||
public_station
|
public_station
|
||||||
.options
|
.options
|
||||||
.push(Address(*addr.regular_socket_addr.ip()));
|
.push(Address(addr.regular_socket_addr.ip().clone()));
|
||||||
public_station
|
public_station
|
||||||
.options
|
.options
|
||||||
.push(Port(addr.regular_socket_addr.port()));
|
.push(Port(addr.regular_socket_addr.port()));
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
use std::sync::{Arc, atomic::AtomicU32};
|
use std::sync::{Arc, atomic::AtomicU32};
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
use log::info;
|
use log::info;
|
||||||
use macros::rmc_struct;
|
use macros::rmc_struct;
|
||||||
|
|
@ -20,21 +19,33 @@ use rnex_core::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use std::sync::atomic::Ordering::Relaxed;
|
use std::sync::atomic::Ordering::Relaxed;
|
||||||
use tokio::time::sleep;
|
|
||||||
|
|
||||||
use rnex_core::rmc::protocols::friends::{GameKey, MiiV2, PrincipalBasicInfo};
|
use rnex_core::rmc::protocols::friends::{GameKey, MiiV2, PrincipalBasicInfo};
|
||||||
|
|
||||||
|
use rnex_core::PID;
|
||||||
|
|
||||||
define_rmc_proto!(
|
define_rmc_proto!(
|
||||||
proto FriendsUser{
|
proto FriendsUser{
|
||||||
Secure,
|
Secure,
|
||||||
Friends
|
Friends
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
define_rmc_proto!(
|
||||||
|
proto FriendsGuest{
|
||||||
|
Secure
|
||||||
|
}
|
||||||
|
);
|
||||||
#[rmc_struct(FriendsUser)]
|
#[rmc_struct(FriendsUser)]
|
||||||
pub struct FriendsUser {
|
pub struct FriendsUser {
|
||||||
pub fm: Arc<FriendsManager>,
|
pub fm: Arc<FriendsManager>,
|
||||||
pub addr: PRUDPSockAddr,
|
pub addr: PRUDPSockAddr,
|
||||||
pub pid: u32,
|
pub pid: PID,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rmc_struct(FriendsGuest)]
|
||||||
|
pub struct FriendsGuest {
|
||||||
|
pub fm: Arc<FriendsManager>,
|
||||||
|
pub addr: PRUDPSockAddr,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FriendsManager {
|
pub struct FriendsManager {
|
||||||
|
|
@ -50,9 +61,9 @@ impl FriendsManager {
|
||||||
impl Friends for FriendsUser {
|
impl Friends for FriendsUser {
|
||||||
async fn update_and_get_all_information(
|
async fn update_and_get_all_information(
|
||||||
&self,
|
&self,
|
||||||
info: NNAInfo,
|
_info: NNAInfo,
|
||||||
presence: NintendoPresenceV2,
|
_presence: NintendoPresenceV2,
|
||||||
date_time: KerberosDateTime,
|
_date_time: KerberosDateTime,
|
||||||
) -> Result<
|
) -> Result<
|
||||||
(
|
(
|
||||||
PrincipalPreference,
|
PrincipalPreference,
|
||||||
|
|
@ -89,10 +100,10 @@ impl Friends for FriendsUser {
|
||||||
nna_info: NNAInfo {
|
nna_info: NNAInfo {
|
||||||
principal_basic_info: PrincipalBasicInfo {
|
principal_basic_info: PrincipalBasicInfo {
|
||||||
pid: 101,
|
pid: 101,
|
||||||
nnid: "dummyaccount".to_string(),
|
nnid: "dummy:3".to_string(),
|
||||||
mii: MiiV2{
|
mii: MiiV2{
|
||||||
date_time: KerberosDateTime::now(),
|
date_time: KerberosDateTime::now(),
|
||||||
name: "Dummy Account".to_string(),
|
name: "TheDummy".to_string(),
|
||||||
mii_data: hex::decode("030000402bd7c32986a771f2dc6b35e31da15e37ff7c0000391e6f006f006d0069000000000000000000000000004040001065033568641e2013661a611821640f0000290052485000000000000000000000000000000000000000000000e838").unwrap(),
|
mii_data: hex::decode("030000402bd7c32986a771f2dc6b35e31da15e37ff7c0000391e6f006f006d0069000000000000000000000000004040001065033568641e2013661a611821640f0000290052485000000000000000000000000000000000000000000000e838").unwrap(),
|
||||||
unk: 0,
|
unk: 0,
|
||||||
unk2: 0,
|
unk2: 0,
|
||||||
|
|
@ -149,12 +160,37 @@ impl Secure for FriendsUser {
|
||||||
async fn register_ex(
|
async fn register_ex(
|
||||||
&self,
|
&self,
|
||||||
station_urls: Vec<StationUrl>,
|
station_urls: Vec<StationUrl>,
|
||||||
data: Any,
|
_data: Any,
|
||||||
) -> Result<(QResult, u32, StationUrl), ErrorCode> {
|
) -> Result<(QResult, u32, StationUrl), ErrorCode> {
|
||||||
info!("register");
|
info!("register");
|
||||||
self.register(station_urls).await
|
self.register(station_urls).await
|
||||||
}
|
}
|
||||||
async fn replace_url(&self, target: StationUrl, dest: StationUrl) -> Result<(), ErrorCode> {
|
async fn replace_url(&self, _target: StationUrl, _dest: StationUrl) -> Result<(), ErrorCode> {
|
||||||
|
Err(ErrorCode::Core_NotImplemented)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Secure for FriendsGuest {
|
||||||
|
async fn register(
|
||||||
|
&self,
|
||||||
|
station_urls: Vec<StationUrl>,
|
||||||
|
) -> Result<(QResult, u32, StationUrl), ErrorCode> {
|
||||||
|
let cid = self.fm.next_cid();
|
||||||
|
Ok((
|
||||||
|
QResult::success(ErrorCode::Core_Unknown),
|
||||||
|
cid,
|
||||||
|
get_station_urls(&station_urls, self.addr, 100, cid).await?[0].clone(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
async fn register_ex(
|
||||||
|
&self,
|
||||||
|
station_urls: Vec<StationUrl>,
|
||||||
|
_data: Any,
|
||||||
|
) -> Result<(QResult, u32, StationUrl), ErrorCode> {
|
||||||
|
info!("register");
|
||||||
|
self.register(station_urls).await
|
||||||
|
}
|
||||||
|
async fn replace_url(&self, _target: StationUrl, _dest: StationUrl) -> Result<(), ErrorCode> {
|
||||||
Err(ErrorCode::Core_NotImplemented)
|
Err(ErrorCode::Core_NotImplemented)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ use crate::nex::user::User;
|
||||||
use crate::rmc::protocols::notifications::{NotificationEvent, RemoteNotification};
|
use crate::rmc::protocols::notifications::{NotificationEvent, RemoteNotification};
|
||||||
use log::info;
|
use log::info;
|
||||||
use rand::random;
|
use rand::random;
|
||||||
|
use rnex_core::PID;
|
||||||
use rnex_core::kerberos::KerberosDateTime;
|
use rnex_core::kerberos::KerberosDateTime;
|
||||||
use rnex_core::rmc::protocols::notifications::notification_types::{
|
use rnex_core::rmc::protocols::notifications::notification_types::{
|
||||||
HOST_CHANGED, OWNERSHIP_CHANGED,
|
HOST_CHANGED, OWNERSHIP_CHANGED,
|
||||||
|
|
@ -208,7 +209,7 @@ impl ExtendedMatchmakeSession {
|
||||||
.process_notification_event(NotificationEvent {
|
.process_notification_event(NotificationEvent {
|
||||||
pid_source: initiating_pid,
|
pid_source: initiating_pid,
|
||||||
notif_type: 122000,
|
notif_type: 122000,
|
||||||
param_1: self.session.gathering.self_gid,
|
param_1: self.session.gathering.self_gid as PID,
|
||||||
param_2: other_pid,
|
param_2: other_pid,
|
||||||
str_param: "".into(),
|
str_param: "".into(),
|
||||||
param_3: 0,
|
param_3: 0,
|
||||||
|
|
@ -240,7 +241,7 @@ impl ExtendedMatchmakeSession {
|
||||||
.process_notification_event(NotificationEvent {
|
.process_notification_event(NotificationEvent {
|
||||||
pid_source: initiating_pid,
|
pid_source: initiating_pid,
|
||||||
notif_type: 3001,
|
notif_type: 3001,
|
||||||
param_1: self.session.gathering.self_gid,
|
param_1: self.session.gathering.self_gid as PID,
|
||||||
param_2: *pid,
|
param_2: *pid,
|
||||||
str_param: join_msg.clone(),
|
str_param: join_msg.clone(),
|
||||||
param_3: self.connected_players.len() as _,
|
param_3: self.connected_players.len() as _,
|
||||||
|
|
@ -261,7 +262,7 @@ impl ExtendedMatchmakeSession {
|
||||||
.process_notification_event(NotificationEvent {
|
.process_notification_event(NotificationEvent {
|
||||||
pid_source: initiating_pid,
|
pid_source: initiating_pid,
|
||||||
notif_type: 3001,
|
notif_type: 3001,
|
||||||
param_1: self.session.gathering.self_gid,
|
param_1: self.session.gathering.self_gid as PID,
|
||||||
param_2: older_pid,
|
param_2: older_pid,
|
||||||
str_param: join_msg.clone(),
|
str_param: join_msg.clone(),
|
||||||
param_3: self.connected_players.len() as _,
|
param_3: self.connected_players.len() as _,
|
||||||
|
|
@ -393,7 +394,7 @@ impl ExtendedMatchmakeSession {
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn migrate_ownership(&mut self, initiator_pid: u32) -> Result<(), ErrorCode> {
|
pub async fn migrate_ownership(&mut self, initiator_pid: PID) -> Result<(), ErrorCode> {
|
||||||
let players: Vec<_> = self
|
let players: Vec<_> = self
|
||||||
.connected_players
|
.connected_players
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -414,7 +415,7 @@ impl ExtendedMatchmakeSession {
|
||||||
self.broadcast_notification(&NotificationEvent {
|
self.broadcast_notification(&NotificationEvent {
|
||||||
pid_source: initiator_pid,
|
pid_source: initiator_pid,
|
||||||
notif_type: OWNERSHIP_CHANGED,
|
notif_type: OWNERSHIP_CHANGED,
|
||||||
param_1: self.session.gathering.self_gid,
|
param_1: self.session.gathering.self_gid as PID,
|
||||||
param_2: new_owner.pid,
|
param_2: new_owner.pid,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
|
|
@ -423,7 +424,7 @@ impl ExtendedMatchmakeSession {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn migrate_host(&mut self, initiator_pid: u32) -> Result<(), ErrorCode> {
|
pub async fn migrate_host(&mut self, initiator_pid: PID) -> Result<(), ErrorCode> {
|
||||||
// let players: Vec<_> = self.connected_players.iter().filter_map(|p| p.upgrade()).collect();
|
// let players: Vec<_> = self.connected_players.iter().filter_map(|p| p.upgrade()).collect();
|
||||||
|
|
||||||
self.session.gathering.host_pid = self.session.gathering.owner_pid;
|
self.session.gathering.host_pid = self.session.gathering.owner_pid;
|
||||||
|
|
@ -431,7 +432,7 @@ impl ExtendedMatchmakeSession {
|
||||||
self.broadcast_notification(&NotificationEvent {
|
self.broadcast_notification(&NotificationEvent {
|
||||||
pid_source: initiator_pid,
|
pid_source: initiator_pid,
|
||||||
notif_type: HOST_CHANGED,
|
notif_type: HOST_CHANGED,
|
||||||
param_1: self.session.gathering.self_gid,
|
param_1: self.session.gathering.self_gid as PID,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
@ -441,7 +442,7 @@ impl ExtendedMatchmakeSession {
|
||||||
|
|
||||||
pub async fn remove_player_from_session(
|
pub async fn remove_player_from_session(
|
||||||
&mut self,
|
&mut self,
|
||||||
pid: u32,
|
pid: PID,
|
||||||
message: &str,
|
message: &str,
|
||||||
) -> Result<(), ErrorCode> {
|
) -> Result<(), ErrorCode> {
|
||||||
self.connected_players
|
self.connected_players
|
||||||
|
|
@ -468,7 +469,7 @@ impl ExtendedMatchmakeSession {
|
||||||
.process_notification_event(NotificationEvent {
|
.process_notification_event(NotificationEvent {
|
||||||
notif_type: 3008,
|
notif_type: 3008,
|
||||||
pid_source: pid,
|
pid_source: pid,
|
||||||
param_1: self.session.gathering.self_gid,
|
param_1: self.session.gathering.self_gid as PID,
|
||||||
param_2: pid,
|
param_2: pid,
|
||||||
str_param: message.to_owned(),
|
str_param: message.to_owned(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,10 @@ use crate::rmc::protocols::nat_traversal::{
|
||||||
NatTraversal, RawNatTraversal, RawNatTraversalInfo, RemoteNatTraversal,
|
NatTraversal, RawNatTraversal, RawNatTraversalInfo, RemoteNatTraversal,
|
||||||
RemoteNatTraversalConsole,
|
RemoteNatTraversalConsole,
|
||||||
};
|
};
|
||||||
|
use rnex_core::PID;
|
||||||
use rnex_core::prudp::station_url::StationUrl;
|
use rnex_core::prudp::station_url::StationUrl;
|
||||||
use rnex_core::prudp::station_url::UrlOptions::{
|
use rnex_core::prudp::station_url::UrlOptions::{
|
||||||
Address, NatFiltering, NatMapping, NatType, Port, PrincipalID, RVConnectionID,
|
Address, NatFiltering, NatMapping, Port, RVConnectionID,
|
||||||
};
|
};
|
||||||
use rnex_core::rmc::protocols::matchmake_ext::{
|
use rnex_core::rmc::protocols::matchmake_ext::{
|
||||||
MatchmakeExt, RawMatchmakeExt, RawMatchmakeExtInfo, RemoteMatchmakeExt,
|
MatchmakeExt, RawMatchmakeExt, RawMatchmakeExtInfo, RemoteMatchmakeExt,
|
||||||
|
|
@ -31,10 +32,7 @@ use crate::rmc::protocols::notifications::{NotificationEvent, RemoteNotification
|
||||||
use log::info;
|
use log::info;
|
||||||
use macros::rmc_struct;
|
use macros::rmc_struct;
|
||||||
use rnex_core::prudp::socket_addr::PRUDPSockAddr;
|
use rnex_core::prudp::socket_addr::PRUDPSockAddr;
|
||||||
use rnex_core::prudp::station_url::nat_types::PUBLIC;
|
use rnex_core::rmc::response::ErrorCode::{Core_InvalidArgument, RendezVous_AccountExpired};
|
||||||
use rnex_core::rmc::response::ErrorCode::{
|
|
||||||
Core_Exception, Core_InvalidArgument, RendezVous_AccountExpired,
|
|
||||||
};
|
|
||||||
use rnex_core::rmc::structures::qresult::QResult;
|
use rnex_core::rmc::structures::qresult::QResult;
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
use tokio::sync::{Mutex, RwLock};
|
use tokio::sync::{Mutex, RwLock};
|
||||||
|
|
@ -52,7 +50,7 @@ define_rmc_proto!(
|
||||||
|
|
||||||
#[rmc_struct(UserProtocol)]
|
#[rmc_struct(UserProtocol)]
|
||||||
pub struct User {
|
pub struct User {
|
||||||
pub pid: u32,
|
pub pid: PID,
|
||||||
pub ip: PRUDPSockAddr,
|
pub ip: PRUDPSockAddr,
|
||||||
pub this: Weak<User>,
|
pub this: Weak<User>,
|
||||||
pub remote: RemoteConsole,
|
pub remote: RemoteConsole,
|
||||||
|
|
@ -423,7 +421,7 @@ impl Matchmake for User {
|
||||||
.process_notification_event(NotificationEvent {
|
.process_notification_event(NotificationEvent {
|
||||||
notif_type: 110000,
|
notif_type: 110000,
|
||||||
pid_source: self.pid,
|
pid_source: self.pid,
|
||||||
param_1: gid,
|
param_1: gid as PID,
|
||||||
param_2: self.pid,
|
param_2: self.pid,
|
||||||
param_3: 0,
|
param_3: 0,
|
||||||
str_param: "".to_string(),
|
str_param: "".to_string(),
|
||||||
|
|
@ -444,7 +442,7 @@ impl Matchmake for User {
|
||||||
.process_notification_event(NotificationEvent {
|
.process_notification_event(NotificationEvent {
|
||||||
notif_type: 4000,
|
notif_type: 4000,
|
||||||
pid_source: self.pid,
|
pid_source: self.pid,
|
||||||
param_1: gid,
|
param_1: gid as PID,
|
||||||
param_2: self.pid,
|
param_2: self.pid,
|
||||||
param_3: 0,
|
param_3: 0,
|
||||||
str_param: "".to_string(),
|
str_param: "".to_string(),
|
||||||
|
|
@ -459,7 +457,7 @@ impl Matchmake for User {
|
||||||
async fn migrate_gathering_ownership(
|
async fn migrate_gathering_ownership(
|
||||||
&self,
|
&self,
|
||||||
gid: u32,
|
gid: u32,
|
||||||
candidates: Vec<u32>,
|
candidates: Vec<PID>,
|
||||||
_participants_only: bool,
|
_participants_only: bool,
|
||||||
) -> Result<(), ErrorCode> {
|
) -> Result<(), ErrorCode> {
|
||||||
let session = self.matchmake_manager.get_session(gid).await?;
|
let session = self.matchmake_manager.get_session(gid).await?;
|
||||||
|
|
@ -479,8 +477,8 @@ impl Matchmake for User {
|
||||||
.process_notification_event(NotificationEvent {
|
.process_notification_event(NotificationEvent {
|
||||||
notif_type: 4000,
|
notif_type: 4000,
|
||||||
pid_source: self.pid,
|
pid_source: self.pid,
|
||||||
param_1: gid,
|
param_1: gid as PID,
|
||||||
param_2: *candidate,
|
param_2: *candidate as PID,
|
||||||
param_3: 0,
|
param_3: 0,
|
||||||
str_param: "".to_string(),
|
str_param: "".to_string(),
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -3,19 +3,19 @@ use macros::RmcSerialize;
|
||||||
use md5::digest::Mac;
|
use md5::digest::Mac;
|
||||||
use rnex_core::prudp::virtual_port::VirtualPort;
|
use rnex_core::prudp::virtual_port::VirtualPort;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::net::SocketAddrV4;
|
use std::net::{IpAddr, SocketAddr};
|
||||||
|
|
||||||
type Md5Hmac = Hmac<md5::Md5>;
|
type Md5Hmac = Hmac<md5::Md5>;
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Hash, Debug, Copy, Clone, Ord, PartialOrd, RmcSerialize)]
|
#[derive(Eq, PartialEq, Hash, Debug, Copy, Clone, Ord, PartialOrd, RmcSerialize)]
|
||||||
#[rmc_struct(0)]
|
#[rmc_struct(0)]
|
||||||
pub struct PRUDPSockAddr {
|
pub struct PRUDPSockAddr {
|
||||||
pub regular_socket_addr: SocketAddrV4,
|
pub regular_socket_addr: SocketAddr,
|
||||||
pub virtual_port: VirtualPort,
|
pub virtual_port: VirtualPort,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PRUDPSockAddr {
|
impl PRUDPSockAddr {
|
||||||
pub fn new(regular_socket_addr: SocketAddrV4, virtual_port: VirtualPort) -> Self {
|
pub fn new(regular_socket_addr: SocketAddr, virtual_port: VirtualPort) -> Self {
|
||||||
Self {
|
Self {
|
||||||
regular_socket_addr,
|
regular_socket_addr,
|
||||||
virtual_port,
|
virtual_port,
|
||||||
|
|
@ -23,9 +23,12 @@ impl PRUDPSockAddr {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn calculate_connection_signature(&self) -> [u8; 16] {
|
pub fn calculate_connection_signature(&self) -> [u8; 16] {
|
||||||
let mut hmac = Md5Hmac::new_from_slice(&[0; 16]).expect("fuck");
|
let mut hmac = Md5Hmac::new_from_slice(&[0; 16]).expect("?");
|
||||||
|
|
||||||
let data = self.regular_socket_addr.ip().octets().to_vec();
|
let data = match self.regular_socket_addr.ip() {
|
||||||
|
IpAddr::V4(v) => v.octets().to_vec(),
|
||||||
|
IpAddr::V6(v) => v.octets().to_vec(),
|
||||||
|
};
|
||||||
//data.extend_from_slice(&self.regular_socket_addr.port().to_be_bytes());
|
//data.extend_from_slice(&self.regular_socket_addr.port().to_be_bytes());
|
||||||
|
|
||||||
hmac.write_all(&data)
|
hmac.write_all(&data)
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,20 @@
|
||||||
use std::net::Ipv4Addr;
|
use crate::prudp::station_url::Type::{PRUDP, PRUDPS, UDP};
|
||||||
|
use crate::prudp::station_url::UrlOptions::{
|
||||||
|
Address, ConnectionID, NatFiltering, NatMapping, NatType, PID, PMP, Platform, Port,
|
||||||
|
PrincipalID, RVConnectionID, StreamID, StreamType, UPNP,
|
||||||
|
};
|
||||||
|
use crate::rmc::structures::Error::StationUrlInvalid;
|
||||||
|
use crate::rmc::structures::RmcSerialize;
|
||||||
|
use crate::rmc::structures::helpers::DummyFormatWriter;
|
||||||
use log::error;
|
use log::error;
|
||||||
use std::fmt::{Debug, Display, Formatter, Write};
|
use std::fmt::{Debug, Display, Formatter, Write};
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use crate::prudp::station_url::Type::{PRUDP, PRUDPS, UDP};
|
use std::net::IpAddr;
|
||||||
use crate::prudp::station_url::UrlOptions::{Address, ConnectionID, NatFiltering, NatMapping, NatType, Platform, PMP, Port, PrincipalID, RVConnectionID, StreamID, StreamType, UPNP, PID};
|
|
||||||
use crate::rmc::structures::Error::StationUrlInvalid;
|
|
||||||
use crate::rmc::structures::helpers::DummyFormatWriter;
|
|
||||||
use crate::rmc::structures::RmcSerialize;
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
UDP,
|
UDP,
|
||||||
PRUDP,
|
PRUDP,
|
||||||
PRUDPS
|
PRUDPS,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod nat_types {
|
pub mod nat_types {
|
||||||
|
|
@ -21,12 +24,12 @@ pub mod nat_types{
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq)]
|
#[derive(Clone, Eq, PartialEq)]
|
||||||
pub enum UrlOptions {
|
pub enum UrlOptions {
|
||||||
Address(Ipv4Addr),
|
Address(IpAddr),
|
||||||
Port(u16),
|
Port(u16),
|
||||||
StreamType(u8),
|
StreamType(u8),
|
||||||
StreamID(u8),
|
StreamID(u8),
|
||||||
ConnectionID(u8),
|
ConnectionID(u8),
|
||||||
PrincipalID(u32),
|
PrincipalID(rnex_core::PID),
|
||||||
NatType(u8),
|
NatType(u8),
|
||||||
NatMapping(u8),
|
NatMapping(u8),
|
||||||
NatFiltering(u8),
|
NatFiltering(u8),
|
||||||
|
|
@ -35,13 +38,12 @@ pub enum UrlOptions {
|
||||||
Platform(u8),
|
Platform(u8),
|
||||||
PMP(u8),
|
PMP(u8),
|
||||||
PID(u32),
|
PID(u32),
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq)]
|
#[derive(Clone, PartialEq, Eq)]
|
||||||
pub struct StationUrl {
|
pub struct StationUrl {
|
||||||
pub url_type: Type,
|
pub url_type: Type,
|
||||||
pub options: Vec<UrlOptions>
|
pub options: Vec<UrlOptions>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StationUrl {
|
impl StationUrl {
|
||||||
|
|
@ -49,61 +51,32 @@ impl StationUrl{
|
||||||
let mut options_out = Vec::new();
|
let mut options_out = Vec::new();
|
||||||
|
|
||||||
for option in options.split(';') {
|
for option in options.split(';') {
|
||||||
if option == "" { continue; }
|
if option == "" {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let mut option_parts = option.split('=');
|
let mut option_parts = option.split('=');
|
||||||
let option_name = option_parts.next()?.to_ascii_lowercase();
|
let option_name = option_parts.next()?.to_ascii_lowercase();
|
||||||
let option_value = option_parts.next()?;
|
let option_value = option_parts.next()?;
|
||||||
|
|
||||||
match option_name.as_ref() {
|
match option_name.as_ref() {
|
||||||
"address" => {
|
"address" => options_out.push(Address(option_value.parse().ok()?)),
|
||||||
options_out.push(Address(option_value.parse().ok()?))
|
"port" => options_out.push(Port(option_value.parse().ok()?)),
|
||||||
},
|
"natf" => options_out.push(NatFiltering(option_value.parse().ok()?)),
|
||||||
"port" => {
|
"natm" => options_out.push(NatMapping(option_value.parse().ok()?)),
|
||||||
options_out.push(Port(option_value.parse().ok()?))
|
"sid" => options_out.push(StreamID(option_value.parse().ok()?)),
|
||||||
}
|
"upnp" => options_out.push(UPNP(option_value.parse().ok()?)),
|
||||||
"natf" => {
|
"type" => options_out.push(NatType(option_value.parse().ok()?)),
|
||||||
options_out.push(NatFiltering(option_value.parse().ok()?))
|
"stream" => options_out.push(StreamType(option_value.parse().ok()?)),
|
||||||
}
|
"RVCID" => options_out.push(RVConnectionID(option_value.parse().ok()?)),
|
||||||
"natm" => {
|
"rvcid" => options_out.push(RVConnectionID(option_value.parse().ok()?)),
|
||||||
options_out.push(NatMapping(option_value.parse().ok()?))
|
"pl" => options_out.push(Platform(option_value.parse().ok()?)),
|
||||||
}
|
"pmp" => options_out.push(PMP(option_value.parse().ok()?)),
|
||||||
"sid" => {
|
"pid" => options_out.push(PID(option_value.parse().ok()?)),
|
||||||
options_out.push(StreamID(option_value.parse().ok()?))
|
"PID" => options_out.push(PID(option_value.parse().ok()?)),
|
||||||
}
|
|
||||||
"upnp" => {
|
|
||||||
options_out.push(UPNP(option_value.parse().ok()?))
|
|
||||||
}
|
|
||||||
"type" => {
|
|
||||||
options_out.push(NatType(option_value.parse().ok()?))
|
|
||||||
}
|
|
||||||
"stream" => {
|
|
||||||
options_out.push(StreamType(option_value.parse().ok()?))
|
|
||||||
}
|
|
||||||
"RVCID" => {
|
|
||||||
options_out.push(RVConnectionID(option_value.parse().ok()?))
|
|
||||||
}
|
|
||||||
"rvcid" => {
|
|
||||||
options_out.push(RVConnectionID(option_value.parse().ok()?))
|
|
||||||
}
|
|
||||||
"pl" => {
|
|
||||||
options_out.push(Platform(option_value.parse().ok()?))
|
|
||||||
}
|
|
||||||
"pmp" => {
|
|
||||||
options_out.push(PMP(option_value.parse().ok()?))
|
|
||||||
},
|
|
||||||
"pid" => {
|
|
||||||
options_out.push(PID(option_value.parse().ok()?))
|
|
||||||
},
|
|
||||||
"PID" => {
|
|
||||||
options_out.push(PID(option_value.parse().ok()?))
|
|
||||||
},
|
|
||||||
_ => {
|
_ => {
|
||||||
error!("unimplemented option type, skipping: {}", option_name);
|
error!("unimplemented option type, skipping: {}", option_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(options_out)
|
Some(options_out)
|
||||||
|
|
@ -122,17 +95,12 @@ impl TryFrom<&str> for StationUrl{
|
||||||
"udp" => UDP,
|
"udp" => UDP,
|
||||||
"prudp" => PRUDP,
|
"prudp" => PRUDP,
|
||||||
"prudps" => PRUDPS,
|
"prudps" => PRUDPS,
|
||||||
_ => return Err(())
|
_ => return Err(()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let options = Self::read_options(options).ok_or(())?;
|
let options = Self::read_options(options).ok_or(())?;
|
||||||
|
|
||||||
Ok(
|
Ok(Self { url_type, options })
|
||||||
Self{
|
|
||||||
url_type,
|
|
||||||
options
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,7 +109,7 @@ impl Display for StationUrl{
|
||||||
let url_type_str = match self.url_type {
|
let url_type_str = match self.url_type {
|
||||||
UDP => "udp:/",
|
UDP => "udp:/",
|
||||||
PRUDP => "prudp:/",
|
PRUDP => "prudp:/",
|
||||||
PRUDPS => "prudps:/"
|
PRUDPS => "prudps:/",
|
||||||
};
|
};
|
||||||
write!(f, "{}", url_type_str)?;
|
write!(f, "{}", url_type_str)?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use std::io::Cursor;
|
||||||
|
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use rc4::{KeyInit, Rc4, Rc4Core, StreamCipher, cipher::StreamCipherCoreWrapper};
|
use rc4::{KeyInit, Rc4, Rc4Core, StreamCipher, cipher::StreamCipherCoreWrapper};
|
||||||
use typenum::{U16, U32};
|
use typenum::U16;
|
||||||
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -10,19 +10,17 @@ use crate::{
|
||||||
nex::account::Account,
|
nex::account::Account,
|
||||||
rmc::structures::RmcSerialize,
|
rmc::structures::RmcSerialize,
|
||||||
};
|
};
|
||||||
|
use rnex_core::PID;
|
||||||
|
|
||||||
pub fn read_secure_connection_data(
|
pub fn read_secure_connection_data(
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
act: &Account,
|
act: &Account,
|
||||||
) -> Option<([u8; SESSION_KEY_LENGTH], u32, u32)> {
|
) -> Option<([u8; SESSION_KEY_LENGTH], PID, u32)> {
|
||||||
let mut cursor = Cursor::new(data);
|
let mut cursor = Cursor::new(data);
|
||||||
|
|
||||||
let mut ticket_data: Vec<u8> = Vec::deserialize(&mut cursor).ok()?;
|
let mut ticket_data: Vec<u8> = Vec::deserialize(&mut cursor).ok()?;
|
||||||
let mut request_data: Vec<u8> = Vec::deserialize(&mut cursor).ok()?;
|
let mut request_data: Vec<u8> = Vec::deserialize(&mut cursor).ok()?;
|
||||||
info!(
|
info!("done request data {}", SESSION_KEY_LENGTH);
|
||||||
"done
|
|
||||||
request data"
|
|
||||||
);
|
|
||||||
|
|
||||||
let ticket_data_size = ticket_data.len();
|
let ticket_data_size = ticket_data.len();
|
||||||
|
|
||||||
|
|
@ -62,7 +60,7 @@ pub fn read_secure_connection_data(
|
||||||
|
|
||||||
let mut reqest_data_cursor = Cursor::new(request_data);
|
let mut reqest_data_cursor = Cursor::new(request_data);
|
||||||
|
|
||||||
let pid: u32 = reqest_data_cursor.read_struct(IS_BIG_ENDIAN).ok()?;
|
let pid: PID = reqest_data_cursor.read_struct(IS_BIG_ENDIAN).ok()?;
|
||||||
|
|
||||||
if pid != ticket_source_pid {
|
if pid != ticket_source_pid {
|
||||||
let ticket_created_on = issued_time.to_regular_time();
|
let ticket_created_on = issued_time.to_regular_time();
|
||||||
|
|
|
||||||
4
rnex-core/src/rmc/protocols/account_management.rs
Normal file
4
rnex-core/src/rmc/protocols/account_management.rs
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
use macros::rmc_proto;
|
||||||
|
|
||||||
|
#[rmc_proto(25)]
|
||||||
|
pub trait AccountManagement {}
|
||||||
|
|
@ -1,9 +1,21 @@
|
||||||
use crate::rmc::structures::connection_data::{ConnectionData, ConnectionDataOld};
|
use crate::rmc::structures::connection_data::{ConnectionData, ConnectionDataOld};
|
||||||
|
use cfg_if::cfg_if;
|
||||||
use macros::{method_id, rmc_proto};
|
use macros::{method_id, rmc_proto};
|
||||||
|
use rnex_core::PID;
|
||||||
use rnex_core::rmc::response::ErrorCode;
|
use rnex_core::rmc::response::ErrorCode;
|
||||||
use rnex_core::rmc::structures::any::Any;
|
use rnex_core::rmc::structures::any::Any;
|
||||||
use rnex_core::rmc::structures::qresult::QResult;
|
use rnex_core::rmc::structures::qresult::QResult;
|
||||||
|
|
||||||
|
cfg_if! {
|
||||||
|
if #[cfg(feature = "nx")]{
|
||||||
|
type LOGIN_EX_RET = (QResult, PID, Vec<u8>, ConnectionData, String, String);
|
||||||
|
type REQUEST_TICKET_RET = (QResult, Vec<u8>, String);
|
||||||
|
} else {
|
||||||
|
type LOGIN_EX_RET = (QResult, PID, Vec<u8>, ConnectionData, String);
|
||||||
|
type REQUEST_TICKET_RET = (QResult, Vec<u8>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// This is the representation for `Ticket Granting`(for details see the
|
/// This is the representation for `Ticket Granting`(for details see the
|
||||||
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
||||||
#[rmc_proto(10)]
|
#[rmc_proto(10)]
|
||||||
|
|
@ -14,25 +26,22 @@ pub trait Auth {
|
||||||
async fn login(
|
async fn login(
|
||||||
&self,
|
&self,
|
||||||
name: String,
|
name: String,
|
||||||
) -> Result<(QResult, u32, Vec<u8>, ConnectionDataOld, String), ErrorCode>;
|
) -> Result<(QResult, PID, Vec<u8>, ConnectionDataOld, String), ErrorCode>;
|
||||||
|
|
||||||
/// representation of the `LoginEx` method(for details see the
|
/// representation of the `LoginEx` method(for details see the
|
||||||
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
||||||
#[method_id(2)]
|
#[method_id(2)]
|
||||||
async fn login_ex(
|
async fn login_ex(&self, name: String, extra_data: Any) -> Result<LOGIN_EX_RET, ErrorCode>;
|
||||||
&self,
|
|
||||||
name: String,
|
|
||||||
extra_data: Any,
|
|
||||||
) -> Result<(QResult, u32, Vec<u8>, ConnectionData, String), ErrorCode>;
|
|
||||||
|
|
||||||
/// representation of the `RequestTicket` method(for details see the
|
|
||||||
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
|
||||||
#[method_id(3)]
|
#[method_id(3)]
|
||||||
async fn request_ticket(
|
async fn request_ticket(
|
||||||
&self,
|
&self,
|
||||||
source_pid: u32,
|
source_pid: PID,
|
||||||
destination_pid: u32,
|
destination_pid: PID,
|
||||||
) -> Result<(QResult, Vec<u8>), ErrorCode>;
|
) -> Result<REQUEST_TICKET_RET, ErrorCode>;
|
||||||
|
|
||||||
|
/// representation of the `RequestTicket` method(for details see the
|
||||||
|
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
||||||
|
|
||||||
/// representation of the `GetPID` method(for details see the
|
/// representation of the `GetPID` method(for details see the
|
||||||
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
||||||
|
|
@ -42,7 +51,7 @@ pub trait Auth {
|
||||||
/// representation of the `LoginWithContext` method(for details see the
|
/// representation of the `LoginWithContext` method(for details see the
|
||||||
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
/// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol))
|
||||||
#[method_id(5)]
|
#[method_id(5)]
|
||||||
async fn get_name(&self, pid: u32) -> Result<String, ErrorCode>;
|
async fn get_name(&self, pid: PID) -> Result<String, ErrorCode>;
|
||||||
|
|
||||||
// `LoginWithContext` is left out here because we don't need it right now and versioning still
|
// `LoginWithContext` is left out here because we don't need it right now and versioning still
|
||||||
// needs to be figured out
|
// needs to be figured out
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ use macros::{method_id, rmc_proto};
|
||||||
use rnex_core::prudp::station_url::StationUrl;
|
use rnex_core::prudp::station_url::StationUrl;
|
||||||
use rnex_core::rmc::response::ErrorCode;
|
use rnex_core::rmc::response::ErrorCode;
|
||||||
|
|
||||||
|
use rnex_core::PID;
|
||||||
|
|
||||||
#[rmc_proto(21)]
|
#[rmc_proto(21)]
|
||||||
pub trait Matchmake {
|
pub trait Matchmake {
|
||||||
#[method_id(2)]
|
#[method_id(2)]
|
||||||
|
|
@ -11,5 +13,10 @@ pub trait Matchmake{
|
||||||
#[method_id(42)]
|
#[method_id(42)]
|
||||||
async fn update_session_host(&self, gid: u32, change_owner: bool) -> Result<(), ErrorCode>;
|
async fn update_session_host(&self, gid: u32, change_owner: bool) -> Result<(), ErrorCode>;
|
||||||
#[method_id(44)]
|
#[method_id(44)]
|
||||||
async fn migrate_gathering_ownership(&self, gid: u32, candidates: Vec<u32>, participants_only: bool) -> Result<(), ErrorCode>;
|
async fn migrate_gathering_ownership(
|
||||||
|
&self,
|
||||||
|
gid: u32,
|
||||||
|
candidates: Vec<PID>,
|
||||||
|
participants_only: bool,
|
||||||
|
) -> Result<(), ErrorCode>;
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#![allow(async_fn_in_trait)]
|
#![allow(async_fn_in_trait)]
|
||||||
|
|
||||||
|
pub mod account_management;
|
||||||
pub mod auth;
|
pub mod auth;
|
||||||
pub mod friends;
|
pub mod friends;
|
||||||
pub mod matchmake;
|
pub mod matchmake;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
use macros::{method_id, rmc_proto, rmc_struct, RmcSerialize};
|
use macros::{RmcSerialize, method_id, rmc_proto, rmc_struct};
|
||||||
|
|
||||||
|
use rnex_core::PID;
|
||||||
|
|
||||||
pub mod notification_types {
|
pub mod notification_types {
|
||||||
pub const OWNERSHIP_CHANGED: u32 = 4000;
|
pub const OWNERSHIP_CHANGED: u32 = 4000;
|
||||||
|
|
@ -8,12 +10,12 @@ pub mod notification_types{
|
||||||
#[derive(RmcSerialize, Debug, Default, Clone)]
|
#[derive(RmcSerialize, Debug, Default, Clone)]
|
||||||
#[rmc_struct(0)]
|
#[rmc_struct(0)]
|
||||||
pub struct NotificationEvent {
|
pub struct NotificationEvent {
|
||||||
pub pid_source: u32,
|
pub pid_source: PID,
|
||||||
pub notif_type: u32,
|
pub notif_type: u32,
|
||||||
pub param_1: u32,
|
pub param_1: PID,
|
||||||
pub param_2: u32,
|
pub param_2: PID,
|
||||||
pub str_param: String,
|
pub str_param: String,
|
||||||
pub param_3: u32,
|
pub param_3: PID,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rmc_proto(14, NoReturn)]
|
#[rmc_proto(14, NoReturn)]
|
||||||
|
|
@ -21,4 +23,3 @@ pub trait Notification {
|
||||||
#[method_id(1)]
|
#[method_id(1)]
|
||||||
async fn process_notification_event(&self, event: NotificationEvent);
|
async fn process_notification_event(&self, event: NotificationEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ pub trait Secure {
|
||||||
&self,
|
&self,
|
||||||
station_urls: Vec<StationUrl>,
|
station_urls: Vec<StationUrl>,
|
||||||
) -> Result<(QResult, u32, StationUrl), ErrorCode>;
|
) -> Result<(QResult, u32, StationUrl), ErrorCode>;
|
||||||
|
|
||||||
#[method_id(4)]
|
#[method_id(4)]
|
||||||
async fn register_ex(
|
async fn register_ex(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,16 @@
|
||||||
|
use macros::RmcSerialize;
|
||||||
use rnex_core::kerberos::KerberosDateTime;
|
use rnex_core::kerberos::KerberosDateTime;
|
||||||
use rnex_core::rmc::structures::variant::Variant;
|
use rnex_core::rmc::structures::variant::Variant;
|
||||||
use macros::RmcSerialize;
|
|
||||||
|
use rnex_core::PID;
|
||||||
|
|
||||||
// rmc structure
|
// rmc structure
|
||||||
#[derive(RmcSerialize, Debug, Clone, Default)]
|
#[derive(RmcSerialize, Debug, Clone, Default)]
|
||||||
#[rmc_struct(0)]
|
#[rmc_struct(0)]
|
||||||
pub struct Gathering {
|
pub struct Gathering {
|
||||||
pub self_gid: u32,
|
pub self_gid: u32,
|
||||||
pub owner_pid: u32,
|
pub owner_pid: PID,
|
||||||
pub host_pid: u32,
|
pub host_pid: PID,
|
||||||
pub minimum_participants: u16,
|
pub minimum_participants: u16,
|
||||||
pub maximum_participants: u16,
|
pub maximum_participants: u16,
|
||||||
pub participant_policy: u32,
|
pub participant_policy: u32,
|
||||||
|
|
@ -73,7 +75,7 @@ pub struct MatchmakeSessionSearchCriteria {
|
||||||
#[rmc_struct(0)]
|
#[rmc_struct(0)]
|
||||||
pub struct AutoMatchmakeParam {
|
pub struct AutoMatchmakeParam {
|
||||||
pub matchmake_session: MatchmakeSession,
|
pub matchmake_session: MatchmakeSession,
|
||||||
pub additional_participants: Vec<u32>,
|
pub additional_participants: Vec<PID>,
|
||||||
pub gid_for_participation_check: u32,
|
pub gid_for_participation_check: u32,
|
||||||
pub auto_matchmake_option: u32,
|
pub auto_matchmake_option: u32,
|
||||||
pub join_message: String,
|
pub join_message: String,
|
||||||
|
|
@ -86,7 +88,7 @@ pub struct AutoMatchmakeParam {
|
||||||
#[rmc_struct(0)]
|
#[rmc_struct(0)]
|
||||||
pub struct CreateMatchmakeSessionParam {
|
pub struct CreateMatchmakeSessionParam {
|
||||||
pub matchmake_session: MatchmakeSession,
|
pub matchmake_session: MatchmakeSession,
|
||||||
pub additional_participants: Vec<u32>,
|
pub additional_participants: Vec<PID>,
|
||||||
pub gid_for_participation_check: u32,
|
pub gid_for_participation_check: u32,
|
||||||
pub create_matchmake_session_option: u32,
|
pub create_matchmake_session_option: u32,
|
||||||
pub join_message: String,
|
pub join_message: String,
|
||||||
|
|
@ -103,7 +105,7 @@ pub struct MatchmakeBlockListParam {
|
||||||
#[rmc_struct(0)]
|
#[rmc_struct(0)]
|
||||||
pub struct JoinMatchmakeSessionParam {
|
pub struct JoinMatchmakeSessionParam {
|
||||||
pub gid: u32,
|
pub gid: u32,
|
||||||
pub additional_participants: Vec<u32>,
|
pub additional_participants: Vec<PID>,
|
||||||
pub gid_for_participation_check: u32,
|
pub gid_for_participation_check: u32,
|
||||||
pub join_matchmake_session_open: u32,
|
pub join_matchmake_session_open: u32,
|
||||||
pub join_matchmake_session_behavior: u8,
|
pub join_matchmake_session_behavior: u8,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,35 @@
|
||||||
use std::io::{Read, Write};
|
use crate::rmc::structures::{Error, Result, RmcSerialize};
|
||||||
use std::net::{Ipv4Addr, SocketAddrV4};
|
|
||||||
use rnex_core::prudp::virtual_port::VirtualPort;
|
use rnex_core::prudp::virtual_port::VirtualPort;
|
||||||
use crate::rmc::structures::RmcSerialize;
|
use std::io::{Read, Write};
|
||||||
|
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
|
||||||
|
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
||||||
|
|
||||||
|
impl RmcSerialize for SocketAddr {
|
||||||
|
fn deserialize(reader: &mut impl std::io::Read) -> Result<Self>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
let val: u8 = reader.read_struct(IS_BIG_ENDIAN)?;
|
||||||
|
match val {
|
||||||
|
4 => Ok(SocketAddr::V4(SocketAddrV4::deserialize(reader)?)),
|
||||||
|
6 => Ok(SocketAddr::V6(SocketAddrV6::deserialize(reader)?)),
|
||||||
|
v => Err(Error::UnexpectedValue(v as u64)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn serialize(&self, writer: &mut impl Write) -> Result<()> {
|
||||||
|
match self {
|
||||||
|
SocketAddr::V4(v) => {
|
||||||
|
writer.write_all(&[4])?;
|
||||||
|
v.serialize(writer)?;
|
||||||
|
}
|
||||||
|
SocketAddr::V6(v) => {
|
||||||
|
writer.write_all(&[6])?;
|
||||||
|
v.serialize(writer)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl RmcSerialize for SocketAddrV4 {
|
impl RmcSerialize for SocketAddrV4 {
|
||||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||||
|
|
@ -21,7 +49,33 @@ impl RmcSerialize for SocketAddrV4{
|
||||||
Ok(6)
|
Ok(6)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl RmcSerialize for SocketAddrV6 {
|
||||||
|
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||||
|
self.ip().to_bits().serialize(writer)?;
|
||||||
|
self.port().serialize(writer)?;
|
||||||
|
self.flowinfo().serialize(writer)?;
|
||||||
|
self.scope_id().serialize(writer)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
|
||||||
|
let ip = u128::deserialize(reader)?;
|
||||||
|
let port = u16::deserialize(reader)?;
|
||||||
|
let flowinfo = u32::deserialize(reader)?;
|
||||||
|
let scope_id = u32::deserialize(reader)?;
|
||||||
|
|
||||||
|
Ok(SocketAddrV6::new(
|
||||||
|
Ipv6Addr::from_bits(ip),
|
||||||
|
port,
|
||||||
|
flowinfo,
|
||||||
|
scope_id,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
|
||||||
|
Ok(6)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl RmcSerialize for VirtualPort {
|
impl RmcSerialize for VirtualPort {
|
||||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::rmc::structures::RmcSerialize;
|
use crate::rmc::structures::RmcSerialize;
|
||||||
use bytemuck::bytes_of;
|
use bytemuck::{bytes_of, bytes_of_mut};
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions};
|
||||||
|
|
||||||
|
|
@ -110,6 +110,23 @@ impl RmcSerialize for u64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RmcSerialize for u128 {
|
||||||
|
#[inline(always)]
|
||||||
|
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||||
|
Ok(writer.write_all(bytes_of(self))?)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result<Self> {
|
||||||
|
let mut data = 0u128;
|
||||||
|
reader.read_exact(&mut bytes_of_mut(&mut data))?;
|
||||||
|
Ok(data)
|
||||||
|
}
|
||||||
|
#[inline(always)]
|
||||||
|
fn serialize_write_size(&self) -> crate::rmc::structures::Result<u32> {
|
||||||
|
Ok(8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl RmcSerialize for i64 {
|
impl RmcSerialize for i64 {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> {
|
||||||
|
|
|
||||||
|
|
@ -20,55 +20,3 @@ struct UploadCompetitionData {
|
||||||
struct UserData {
|
struct UserData {
|
||||||
name: [u16; 0x10],
|
name: [u16; 0x10],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use crate::rmc::structures::ranking::{UploadCompetitionData, UserData};
|
|
||||||
use bytemuck::from_bytes;
|
|
||||||
use rnex_core::rmc::structures::RmcSerialize;
|
|
||||||
use std::io::Cursor;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test() {
|
|
||||||
return;
|
|
||||||
let data: [u8; 0xBD] = [
|
|
||||||
0x00, 0xB8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFC, 0x03, 0x00, 0x00, 0x02,
|
|
||||||
0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0xA0,
|
|
||||||
0x00, 0x00, 0x49, 0x00, 0x7A, 0x00, 0x7A, 0x00, 0x79, 0x00, 0x53, 0x00, 0x50, 0x00,
|
|
||||||
0x46, 0x00, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
|
|
||||||
0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0xF2, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x1F, 0x5E, 0x00, 0x00, 0x00, 0x01, 0x00,
|
|
||||||
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x90, 0x00,
|
|
||||||
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x14, 0x87, 0x00, 0x00, 0x00, 0x01, 0x00,
|
|
||||||
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00,
|
|
||||||
];
|
|
||||||
|
|
||||||
let mut cursor = Cursor::new(data);
|
|
||||||
|
|
||||||
let data =
|
|
||||||
UploadCompetitionData::deserialize(&mut cursor).expect("unable to deserialize data");
|
|
||||||
|
|
||||||
let user_data: &UserData = from_bytes(&data.player_data.0[..size_of::<UserData>()]);
|
|
||||||
|
|
||||||
let pos = user_data
|
|
||||||
.name
|
|
||||||
.iter()
|
|
||||||
.position(|v| *v == 0x0000)
|
|
||||||
.unwrap_or(0x10);
|
|
||||||
|
|
||||||
let mut name = user_data.name[0..pos].to_vec();
|
|
||||||
|
|
||||||
name.iter_mut().for_each(|v| *v = v.swap_bytes());
|
|
||||||
|
|
||||||
let name = String::from_utf16(&name).expect("unable to get name");
|
|
||||||
|
|
||||||
println!("{:?}", name);
|
|
||||||
|
|
||||||
assert!(u8::deserialize(&mut cursor).is_err())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
|
use crate::{PID, prudp::socket_addr::PRUDPSockAddr};
|
||||||
use macros::RmcSerialize;
|
use macros::RmcSerialize;
|
||||||
use crate::prudp::socket_addr::PRUDPSockAddr;
|
|
||||||
|
|
||||||
#[derive(Debug, RmcSerialize)]
|
#[derive(Debug, RmcSerialize)]
|
||||||
#[rmc_struct(0)]
|
#[rmc_struct(0)]
|
||||||
pub struct ConnectionInitData {
|
pub struct ConnectionInitData {
|
||||||
pub prudpsock_addr: PRUDPSockAddr,
|
pub prudpsock_addr: PRUDPSockAddr,
|
||||||
pub pid: u32,
|
pub pid: PID,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue