diff --git a/Cargo.lock b/Cargo.lock index 0fbdcee..25373ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,6 +80,21 @@ dependencies = [ "syn 2.0.96", ] +[[package]] +name = "atomic" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" + +[[package]] +name = "atomic" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994" +dependencies = [ + "bytemuck", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -127,8 +142,8 @@ dependencies = [ "axum-core", "bytes", "futures-util", - "http", - "http-body", + "http 1.2.0", + "http-body 1.0.1", "http-body-util", "itoa", "matchit", @@ -153,8 +168,8 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http", - "http-body", + "http 1.2.0", + "http-body 1.0.1", "http-body-util", "mime", "pin-project-lite", @@ -176,7 +191,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -185,6 +200,12 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "binascii" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72" + [[package]] name = "bindgen" version = "0.69.5" @@ -298,7 +319,7 @@ dependencies = [ "js-sys", "num-traits", "wasm-bindgen", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -331,6 +352,17 @@ dependencies = [ "cc", ] +[[package]] +name = "cookie" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" +dependencies = [ + "percent-encoding", + "time", + "version_check", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -356,6 +388,39 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "devise" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1d90b0c4c777a2cad215e3c7be59ac7c15adf45cf76317009b7d096d46f651d" +dependencies = [ + "devise_codegen", + "devise_core", +] + +[[package]] +name = "devise_codegen" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71b28680d8be17a570a2334922518be6adc3f58ecc880cbb404eaeb8624fd867" +dependencies = [ + "devise_core", + "quote", +] + +[[package]] +name = "devise_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b035a542cf7abf01f2e3c4d5a7acbaebfefe120ae4efc7bde3df98186e4b8af7" +dependencies = [ + "bitflags", + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn 2.0.96", +] + [[package]] name = "digest" version = "0.10.7" @@ -385,6 +450,15 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -407,6 +481,20 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "figment" +version = "0.10.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cb01cd46b0cf372153850f4c6c272d9cbea2da513e07538405148f95bd789f3" +dependencies = [ + "atomic 0.6.0", + "pear", + "serde", + "toml", + "uncased", + "version_check", +] + [[package]] name = "fixedbitset" version = "0.4.2" @@ -425,6 +513,20 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.31" @@ -432,6 +534,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -440,6 +543,12 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + [[package]] name = "futures-sink" version = "0.3.31" @@ -458,10 +567,28 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ + "futures-channel", "futures-core", + "futures-io", + "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", + "slab", +] + +[[package]] +name = "generator" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "windows", ] [[package]] @@ -497,7 +624,7 @@ dependencies = [ "rustix", "wasi 0.13.3+wasi-0.2.2", "wasm-bindgen", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -512,6 +639,25 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap 2.7.1", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "h2" version = "0.4.7" @@ -523,7 +669,7 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http", + "http 1.2.0", "indexmap 2.7.1", "slab", "tokio", @@ -549,6 +695,18 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + [[package]] name = "hex" version = "0.4.3" @@ -573,6 +731,17 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http" version = "1.2.0" @@ -584,6 +753,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.12", + "pin-project-lite", +] + [[package]] name = "http-body" version = "1.0.1" @@ -591,7 +771,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http", + "http 1.2.0", ] [[package]] @@ -602,8 +782,8 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", - "http", - "http-body", + "http 1.2.0", + "http-body 1.0.1", "pin-project-lite", ] @@ -619,6 +799,30 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "hyper" +version = "0.14.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + [[package]] name = "hyper" version = "1.6.0" @@ -628,9 +832,9 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2", - "http", - "http-body", + "h2 0.4.7", + "http 1.2.0", + "http-body 1.0.1", "httparse", "httpdate", "itoa", @@ -646,7 +850,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ - "hyper", + "hyper 1.6.0", "hyper-util", "pin-project-lite", "tokio", @@ -662,9 +866,9 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http", - "http-body", - "hyper", + "http 1.2.0", + "http-body 1.0.1", + "hyper 1.6.0", "pin-project-lite", "socket2", "tokio", @@ -713,8 +917,15 @@ checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", "hashbrown 0.15.2", + "serde", ] +[[package]] +name = "inlinable_string" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" + [[package]] name = "inout" version = "0.1.3" @@ -724,6 +935,17 @@ dependencies = [ "generic-array", ] +[[package]] +name = "is-terminal" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e19b23d53f35ce9f56aebc7d1bb4e6ac1e9c0db7ac85c8d1760c04379edced37" +dependencies = [ + "hermit-abi 0.4.0", + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "itertools" version = "0.12.1" @@ -783,7 +1005,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -792,12 +1014,37 @@ version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "serde", + "serde_json", + "tracing", + "tracing-subscriber", +] + [[package]] name = "macros" version = "0.0.0" @@ -807,6 +1054,15 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + [[package]] name = "matchit" version = "0.7.3" @@ -861,6 +1117,25 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "multer" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" +dependencies = [ + "bytes", + "encoding_rs", + "futures-util", + "http 1.2.0", + "httparse", + "memchr", + "mime", + "spin", + "tokio", + "tokio-util", + "version_check", +] + [[package]] name = "multimap" version = "0.10.0" @@ -877,6 +1152,16 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -892,6 +1177,16 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi 0.3.9", + "libc", +] + [[package]] name = "num_threads" version = "0.1.7" @@ -916,12 +1211,64 @@ version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + [[package]] name = "paste" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pear" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdeeaa00ce488657faba8ebf44ab9361f9365a97bd39ffb8a60663f57ff4b467" +dependencies = [ + "inlinable_string", + "pear_codegen", + "yansi", +] + +[[package]] +name = "pear_codegen" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bab5b985dc082b345f812b7df84e1bef27e7207b39e448439ba8bd69c93f147" +dependencies = [ + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn 2.0.96", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -1004,6 +1351,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "proc-macro2-diagnostics" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", + "version_check", + "yansi", +] + [[package]] name = "prost" version = "0.13.4" @@ -1135,6 +1495,35 @@ dependencies = [ "cipher", ] +[[package]] +name = "redox_syscall" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +dependencies = [ + "bitflags", +] + +[[package]] +name = "ref-cast" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + [[package]] name = "regex" version = "1.11.1" @@ -1143,8 +1532,17 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata", - "regex-syntax", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", ] [[package]] @@ -1155,9 +1553,15 @@ checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.8.5", ] +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + [[package]] name = "regex-syntax" version = "0.8.5" @@ -1179,6 +1583,88 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rocket" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a516907296a31df7dc04310e7043b61d71954d703b603cc6867a026d7e72d73f" +dependencies = [ + "async-stream", + "async-trait", + "atomic 0.5.3", + "binascii", + "bytes", + "either", + "figment", + "futures", + "indexmap 2.7.1", + "log", + "memchr", + "multer", + "num_cpus", + "parking_lot", + "pin-project-lite", + "rand 0.8.5", + "ref-cast", + "rocket_codegen", + "rocket_http", + "serde", + "serde_json", + "state", + "tempfile", + "time", + "tokio", + "tokio-stream", + "tokio-util", + "ubyte", + "version_check", + "yansi", +] + +[[package]] +name = "rocket_codegen" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "575d32d7ec1a9770108c879fc7c47815a80073f96ca07ff9525a94fcede1dd46" +dependencies = [ + "devise", + "glob", + "indexmap 2.7.1", + "proc-macro2", + "quote", + "rocket_http", + "syn 2.0.96", + "unicode-xid", + "version_check", +] + +[[package]] +name = "rocket_http" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e274915a20ee3065f611c044bd63c40757396b6dbc057d6046aec27f14f882b9" +dependencies = [ + "cookie", + "either", + "futures", + "http 0.2.12", + "hyper 0.14.32", + "indexmap 2.7.1", + "log", + "memchr", + "pear", + "percent-encoding", + "pin-project-lite", + "ref-cast", + "serde", + "smallvec", + "stable-pattern", + "state", + "time", + "tokio", + "uncased", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -1243,6 +1729,24 @@ version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" +[[package]] +name = "ryu" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "serde" version = "1.0.217" @@ -1263,12 +1767,51 @@ dependencies = [ "syn 2.0.96", ] +[[package]] +name = "serde_json" +version = "1.0.138" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + [[package]] name = "simplelog" version = "0.12.2" @@ -1316,6 +1859,7 @@ name = "splatoon-server-rust" version = "0.1.0" dependencies = [ "anyhow", + "async-trait", "bytemuck", "chrono", "dotenv", @@ -1328,7 +1872,9 @@ dependencies = [ "prost", "rand 0.9.0-beta.3", "rc4", + "rocket", "rustls", + "serde", "simplelog", "thiserror", "tokio", @@ -1338,6 +1884,24 @@ dependencies = [ "v_byte_macros", ] +[[package]] +name = "stable-pattern" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4564168c00635f88eaed410d5efa8131afa8d8699a612c80c455a0ba05c21045" +dependencies = [ + "memchr", +] + +[[package]] +name = "state" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b8c4a4445d81357df8b1a650d0d0d6fbbbfe99d064aa5e02f3e4022061476d8" +dependencies = [ + "loom", +] + [[package]] name = "subtle" version = "2.6.1" @@ -1415,6 +1979,16 @@ dependencies = [ "syn 2.0.96", ] +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + [[package]] name = "time" version = "0.3.37" @@ -1459,6 +2033,7 @@ dependencies = [ "libc", "mio", "pin-project-lite", + "signal-hook-registry", "socket2", "tokio-macros", "windows-sys 0.52.0", @@ -1499,6 +2074,40 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +dependencies = [ + "indexmap 2.7.1", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "tonic" version = "0.12.3" @@ -1510,11 +2119,11 @@ dependencies = [ "axum", "base64", "bytes", - "h2", - "http", - "http-body", + "h2 0.4.7", + "http 1.2.0", + "http-body 1.0.1", "http-body-util", - "hyper", + "hyper 1.6.0", "hyper-timeout", "hyper-util", "percent-encoding", @@ -1618,6 +2227,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", ] [[package]] @@ -1632,12 +2271,37 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "ubyte" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f720def6ce1ee2fc44d40ac9ed6d3a59c361c80a75a7aa8e75bb9baed31cf2ea" +dependencies = [ + "serde", +] + +[[package]] +name = "uncased" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697" +dependencies = [ + "serde", + "version_check", +] + [[package]] name = "unicode-ident" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "untrusted" version = "0.9.0" @@ -1654,6 +2318,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + [[package]] name = "version_check" version = "0.9.5" @@ -1754,6 +2424,22 @@ dependencies = [ "rustix", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.9" @@ -1763,13 +2449,28 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-core" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1778,7 +2479,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1787,7 +2488,22 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -1796,28 +2512,46 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -1830,30 +2564,63 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "winnow" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59690dea168f2198d1a3b0cac23b8063efcd11012f10ae4698f284808c8ef603" +dependencies = [ + "memchr", +] + [[package]] name = "wit-bindgen-rt" version = "0.33.0" @@ -1863,6 +2630,15 @@ dependencies = [ "bitflags", ] +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" +dependencies = [ + "is-terminal", +] + [[package]] name = "zerocopy" version = "0.7.35" diff --git a/Cargo.toml b/Cargo.toml index 321ded6..4c86ce9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,9 @@ prost = "0.13.4" hex = "0.4.3" macros = { path = "macros" } +rocket = { version = "0.5.1", features = ["json", "serde_json"] } +serde = { version = "1.0.217", features = ["derive"] } +async-trait = "0.1.86" [build-dependencies] tonic-build = "0.12.3" @@ -32,4 +35,4 @@ tonic-build = "0.12.3" [features] default = ["secure", "auth"] secure = [] -auth = [] \ No newline at end of file +auth = [] diff --git a/src/main.rs b/src/main.rs index 2b445c7..bb44bc5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,25 +14,21 @@ use simplelog::{ColorChoice, CombinedLogger, Config, LevelFilter, TerminalMode, use tokio::sync::RwLock; use tokio::task::JoinHandle; use crate::nex::account::Account; -use crate::protocols::{auth, block_if_maintenance}; -use crate::protocols::auth::AuthProtocolConfig; -use crate::protocols::matchmake_common::MatchmakeData; -use crate::protocols::server::RMCProtocolServer; -use crate::prudp::socket::{ActiveSecureConnectionData, EncryptionPair, Socket}; +use crate::prudp::socket::{EncryptionPair, Unsecure}; use crate::prudp::packet::{VirtualPort}; use crate::prudp::router::Router; -use crate::prudp::secure::{generate_secure_encryption_pairs, read_secure_connection_data}; -use crate::rmc::message::RMCMessage; -use crate::rmc::structures::RmcSerialize; +use crate::prudp::sockaddr::PRUDPSockAddr; +use crate::prudp::station_url::Type::PRUDP; mod endianness; mod prudp; pub mod rmc; -mod protocols; +//mod protocols; mod nex; mod grpc; mod kerberos; +mod web; static KERBEROS_SERVER_PASSWORD: Lazy = Lazy::new(||{ env::var("AUTH_SERVER_PASSWORD") @@ -97,6 +93,7 @@ async fn main() { start_servers().await; } +/* struct AuthServer{ router: Arc, @@ -236,74 +233,66 @@ async fn start_secure_server() -> SecureServer{ router, socket, } -} +}*/ async fn start_servers(){ + + + + let a = tokio::spawn(async{ + let (router_auth, _) = + Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *AUTH_SERVER_PORT)).await.expect("unable to start router"); + + let mut socket_auth = router_auth.add_socket(VirtualPort::new(1,10), Unsecure("CD&ML")).await + .expect("unable to add socket"); + + let mut conn = socket_auth.accept().await.unwrap(); + info!("got conn"); + + if let Some(data) = conn.recv().await{ + let str = String::from_utf8(data).unwrap(); + + println!("{}", str) + } + }); + + let b = tokio::spawn(async{ + let auth_ip = SocketAddrV4::new(*OWN_IP_PRIVATE, *AUTH_SERVER_PORT); + let auth_port = VirtualPort::new(1,10); + + let auth_sockaddr = PRUDPSockAddr::new(auth_ip,auth_port); + + + let (router_secure, _) = + Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *SECURE_SERVER_PORT)).await.expect("unable to start router"); + + let mut socket_secure = router_secure.add_socket(VirtualPort::new(1,10), Unsecure("CD&ML")).await + .expect("unable to add socket"); + + let conn = socket_secure.connect(auth_sockaddr).await.unwrap(); + + let conn = conn.duplicate_sender(); + + conn.send("Yippie".as_bytes().to_owned()).await; + + info!("got conn"); + }); + + a.await; + b.await; + +/* #[cfg(feature = "auth")] let auth_server = start_auth_server().await; #[cfg(feature = "secure")] let secure_server = start_secure_server().await; + let web_server = web::start_web().await; #[cfg(feature = "auth")] auth_server.join_handle.await.expect("auth server crashed"); #[cfg(feature = "secure")] secure_server.join_handle.await.expect("auth server crashed"); -} - - -#[cfg(test)] -mod test{ - use std::io::Cursor; - use std::num::ParseIntError; - use std::str::from_utf8; - use hmac::digest::consts::U5; - use rc4::{KeyInit, Rc4, StreamCipher}; - use crate::prudp::packet::PRUDPPacket; - use crate::rmc; - - fn from_hex_stream(val: &str) -> Result, ParseIntError> { - let res: Result, _> = val.as_bytes() - .chunks_exact(2) - .map(|c| from_utf8(c).expect("unable to convert back to string")) - .map(|s| u8::from_str_radix(s, 16)) - .collect(); - - res - } - - #[tokio::test] - async fn simulate_packets(){ - let val = from_hex_stream("ead001037d00afa1e200a5000200d9e4a4050368c18c6de4e2fb1cc40f0c020100768744db99f92c5005a061fd2a1df280cd64d5c1a565952c6befa607cbaf34661312b16db0fa6fccfb81e28b5a3a9bed02b49152bbc99cc112b7e29b9e45ec3d4b89df0fe71390883d9a927c264d07ada0de9cd28499e3ccdf3fd079e4a9848d4d783778c42da2af06106a7326634dc5bec5c3438ef18e30109839ffcc").expect("uuuuh"); - - let mut packet = PRUDPPacket::new(&mut Cursor::new(&val)).expect("invalid packet"); - - let mut rc4: Rc4 = - Rc4::new_from_slice("CD&ML".as_bytes().into()).expect("invalid key"); - - rc4.apply_keystream(&mut packet.payload); - - println!("packet: {:?}", packet); - - let rmc_packet = rmc::message::RMCMessage::new(&mut Cursor::new(&packet.payload)).expect("unable to read message"); - - let mut a = Cursor::new(&rmc_packet.rest_of_data); - - //let pid = rmc::structures::string::read(&mut a).expect("unable to read pid"); - } - - #[tokio::test] - async fn simulate_packets_response(){ - let val = from_hex_stream("ead001032501a1af6200a500010013ffcdbc3a2ebc44efc6e38ea32a72b40201002e8644db19fe2a5005a2637d2a16f3b1fe5633037c1ed61c5aefad8afebdf2ff8600e9350fba1298b570c70f6dd647eac2d3faf0ab74ef761e2ee43dc10e249e5f91aed6813dcc04b3c707d9442b6e353b9b0b654e98f860fe5379c41d3c2a1874b7dd37ebf499e03bd2fd3e9a9203c0959feb760c38f504dcd0c9e99b17fd410657da4efa3e01c8a68ab3042d6d489788d5580778d32249cdf1fba8bf68cf4019d116ea7c580622ea1e3635139d91b44635d5e95b6c35b33898fdc0117fa6fc7162840d07a49f1e7089aa0ea65409a8ddeb2334449ba73a0ff7de462cf4a706a696de0f0521b84ae5a3f8587f3585d202d3cc0fb0451519c1b830b5e3cdd6de52e9add7325cbbf08a7c2f8b875934942b226703a22b4bc8931932dab055049051e4144b02").expect("uuuuh"); - - let mut packet = PRUDPPacket::new(&mut Cursor::new(&val)).expect("invalid packet"); - - let mut rc4: Rc4 = - Rc4::new_from_slice("CD&ML".as_bytes().into()).expect("invalid key"); - - rc4.apply_keystream(&mut packet.payload); - - println!("packet: {:?}", packet); - } + web_server.await.expect("webserver crashed");*/ } diff --git a/src/protocols/auth/method_login.rs b/src/nex-implementation/auth/method_login.rs similarity index 93% rename from src/protocols/auth/method_login.rs rename to src/nex-implementation/auth/method_login.rs index d2c1642..aface70 100644 --- a/src/protocols/auth/method_login.rs +++ b/src/nex-implementation/auth/method_login.rs @@ -3,7 +3,6 @@ use std::sync::Arc; use log::error; use tokio::sync::Mutex; use crate::protocols::auth::AuthProtocolConfig; -use crate::prudp::socket::{ConnectionData, SocketData}; use crate::rmc::message::RMCMessage; use crate::rmc::response::{ErrorCode, RMCResponseResult}; use crate::rmc::structures::RmcSerialize; diff --git a/src/protocols/auth/method_login_ex.rs b/src/nex-implementation/auth/method_login_ex.rs similarity index 98% rename from src/protocols/auth/method_login_ex.rs rename to src/nex-implementation/auth/method_login_ex.rs index 63ff73f..413ab82 100644 --- a/src/protocols/auth/method_login_ex.rs +++ b/src/nex-implementation/auth/method_login_ex.rs @@ -7,7 +7,6 @@ use crate::grpc::account; use crate::kerberos::KerberosDateTime; use crate::protocols::auth::AuthProtocolConfig; use crate::protocols::auth::ticket_generation::generate_ticket; -use crate::prudp::socket::{ConnectionData, SocketData}; use crate::rmc; use crate::rmc::message::RMCMessage; use crate::rmc::response::{ErrorCode, RMCResponseResult}; diff --git a/src/protocols/auth/method_request_ticket.rs b/src/nex-implementation/auth/method_request_ticket.rs similarity index 97% rename from src/protocols/auth/method_request_ticket.rs rename to src/nex-implementation/auth/method_request_ticket.rs index 6f2d767..aa89448 100644 --- a/src/protocols/auth/method_request_ticket.rs +++ b/src/nex-implementation/auth/method_request_ticket.rs @@ -4,7 +4,6 @@ use tokio::sync::Mutex; use crate::endianness::{IS_BIG_ENDIAN, ReadExtensions}; use crate::protocols::auth::{AuthProtocolConfig, get_login_data_by_pid}; use crate::protocols::auth::ticket_generation::generate_ticket; -use crate::prudp::socket::{ConnectionData, SocketData}; use crate::rmc::message::RMCMessage; use crate::rmc::response::{ErrorCode, RMCResponseResult}; use crate::rmc::response::ErrorCode::Core_Unknown; diff --git a/src/protocols/auth/mod.rs b/src/nex-implementation/auth/mod.rs similarity index 100% rename from src/protocols/auth/mod.rs rename to src/nex-implementation/auth/mod.rs diff --git a/src/protocols/auth/ticket_generation.rs b/src/nex-implementation/auth/ticket_generation.rs similarity index 100% rename from src/protocols/auth/ticket_generation.rs rename to src/nex-implementation/auth/ticket_generation.rs diff --git a/src/protocols/matchmake/method_unregister_gathering.rs b/src/nex-implementation/matchmake/method_unregister_gathering.rs similarity index 95% rename from src/protocols/matchmake/method_unregister_gathering.rs rename to src/nex-implementation/matchmake/method_unregister_gathering.rs index d055afb..22ec79f 100644 --- a/src/protocols/matchmake/method_unregister_gathering.rs +++ b/src/nex-implementation/matchmake/method_unregister_gathering.rs @@ -2,7 +2,6 @@ use std::io::Cursor; use std::sync::Arc; use tokio::sync::{Mutex, RwLock}; use crate::protocols::matchmake_common::MatchmakeData; -use crate::prudp::socket::{ConnectionData, SocketData}; use crate::rmc::message::RMCMessage; use crate::rmc::response::{ErrorCode, RMCResponseResult}; use crate::rmc::structures::qresult::QResult; diff --git a/src/protocols/matchmake/mod.rs b/src/nex-implementation/matchmake/mod.rs similarity index 100% rename from src/protocols/matchmake/mod.rs rename to src/nex-implementation/matchmake/mod.rs diff --git a/src/protocols/matchmake_common/mod.rs b/src/nex-implementation/matchmake_common/mod.rs similarity index 97% rename from src/protocols/matchmake_common/mod.rs rename to src/nex-implementation/matchmake_common/mod.rs index f016457..c4265d3 100644 --- a/src/protocols/matchmake_common/mod.rs +++ b/src/nex-implementation/matchmake_common/mod.rs @@ -5,7 +5,6 @@ use rand::random; use tokio::sync::{Mutex, RwLock}; use crate::kerberos::KerberosDateTime; use crate::protocols::notification::Notification; -use crate::prudp::socket::{ActiveConnectionData, ConnectionData, SocketData}; use crate::rmc::structures::matchmake::{Gathering, MatchmakeParam, MatchmakeSession}; use crate::rmc::structures::variant::Variant; @@ -44,7 +43,7 @@ impl ExtendedMatchmakeSession{ let mm_session = MatchmakeSession{ gathering: Gathering{ - self_gid: random(), + self_gid: 1, owner_pid: active_secure_connection_data.pid, host_pid: active_secure_connection_data.pid, ..session.gathering.clone() diff --git a/src/protocols/matchmake_extension/method_auto_matchmake_with_param_postpone.rs b/src/nex-implementation/matchmake_extension/method_auto_matchmake_with_param_postpone.rs similarity index 98% rename from src/protocols/matchmake_extension/method_auto_matchmake_with_param_postpone.rs rename to src/nex-implementation/matchmake_extension/method_auto_matchmake_with_param_postpone.rs index c822dc0..4c5d70a 100644 --- a/src/protocols/matchmake_extension/method_auto_matchmake_with_param_postpone.rs +++ b/src/nex-implementation/matchmake_extension/method_auto_matchmake_with_param_postpone.rs @@ -7,7 +7,6 @@ use rand::random; use tokio::sync::{Mutex, RwLock}; use tokio::time::sleep; use crate::protocols::matchmake_common::{ExtendedMatchmakeSession, MatchmakeData}; -use crate::prudp::socket::{ConnectionData, SocketData}; use crate::rmc::message::RMCMessage; use crate::rmc::response::{ErrorCode, RMCResponseResult}; use crate::rmc::structures::matchmake::{AutoMatchmakeParam, MatchmakeSession}; diff --git a/src/protocols/matchmake_extension/method_create_matchmake_session_with_param.rs b/src/nex-implementation/matchmake_extension/method_create_matchmake_session_with_param.rs similarity index 70% rename from src/protocols/matchmake_extension/method_create_matchmake_session_with_param.rs rename to src/nex-implementation/matchmake_extension/method_create_matchmake_session_with_param.rs index 6fa7214..438a9ed 100644 --- a/src/protocols/matchmake_extension/method_create_matchmake_session_with_param.rs +++ b/src/nex-implementation/matchmake_extension/method_create_matchmake_session_with_param.rs @@ -1,10 +1,11 @@ use std::io::Cursor; use std::sync::Arc; +use std::time::Duration; use log::info; use tokio::sync::{Mutex, RwLock}; +use tokio::time::sleep; use crate::protocols::matchmake_common::{add_matchmake_session, ExtendedMatchmakeSession, MatchmakeData}; use crate::protocols::matchmake_extension::method_auto_matchmake_with_param_postpone::auto_matchmake_with_param_postpone; -use crate::prudp::socket::{ConnectionData, SocketData}; use crate::rmc::message::RMCMessage; use crate::rmc::response::{ErrorCode, RMCResponseResult}; use crate::rmc::structures::matchmake::{AutoMatchmakeParam, CreateMatchmakeSessionParam}; @@ -29,13 +30,17 @@ pub async fn create_matchmake_session_with_param( session.add_player(&socket, conn.clone(), create_matchmake_session.join_message).await; - println!("{:?}", session); + let mut response = Vec::new(); session.session.serialize(&mut response).expect("unable to serialize session"); + println!("{}", hex::encode(&response)); + + + rmcmessage.success_with_data(response) } @@ -51,7 +56,32 @@ pub async fn create_matchmake_session_with_param_raw_params( return rmcmessage.error_result_with_code(ErrorCode::Core_InvalidArgument); }; - - create_matchmake_session_with_param(rmcmessage, connection_data, socket, data, matchmake_param).await +} + +#[cfg(test)] +mod test{ + use std::io::Cursor; + use crate::prudp::packet::PRUDPPacket; + use crate::rmc::message::RMCMessage; + use crate::rmc::structures::matchmake::MatchmakeSession; + use crate::rmc::structures::RmcSerialize; + + #[test] + fn test(){ + let data = hex::decode("ead001030000a1af12001800050002010000000000000000000000000000000000").unwrap(); + + let packet = PRUDPPacket::new(&mut Cursor::new(data)).unwrap(); + + println!("{:?}", packet); + } + + #[test] + fn test_2(){ + let data = hex::decode("250000008e0100000001000000001700000051b39957b90b00000100000051b3995701000001000000").unwrap(); + + let msg = RMCMessage::new(&mut Cursor::new(data)).unwrap(); + + println!("{:?}", msg) + } } \ No newline at end of file diff --git a/src/protocols/matchmake_extension/method_get_playing_session.rs b/src/nex-implementation/matchmake_extension/method_get_playing_session.rs similarity index 95% rename from src/protocols/matchmake_extension/method_get_playing_session.rs rename to src/nex-implementation/matchmake_extension/method_get_playing_session.rs index bc4eb3c..d88a6f5 100644 --- a/src/protocols/matchmake_extension/method_get_playing_session.rs +++ b/src/nex-implementation/matchmake_extension/method_get_playing_session.rs @@ -3,7 +3,6 @@ use std::sync::Arc; use log::info; use tokio::sync::{Mutex, RwLock}; use crate::protocols::matchmake_common::MatchmakeData; -use crate::prudp::socket::{ConnectionData, SocketData}; use crate::rmc::message::RMCMessage; use crate::rmc::response::{ErrorCode, RMCResponseResult}; use crate::rmc::structures::RmcSerialize; diff --git a/src/protocols/matchmake_extension/mod.rs b/src/nex-implementation/matchmake_extension/mod.rs similarity index 100% rename from src/protocols/matchmake_extension/mod.rs rename to src/nex-implementation/matchmake_extension/mod.rs diff --git a/src/protocols/mod.rs b/src/nex-implementation/mod.rs similarity index 98% rename from src/protocols/mod.rs rename to src/nex-implementation/mod.rs index 51c37e1..16bf0bf 100644 --- a/src/protocols/mod.rs +++ b/src/nex-implementation/mod.rs @@ -6,7 +6,6 @@ use log::warn; use once_cell::sync::Lazy; use tokio::sync::Mutex; use crate::grpc; -use crate::prudp::socket::{ConnectionData, SocketData}; use crate::rmc::message::RMCMessage; use crate::rmc::response::{ErrorCode, RMCResponse}; @@ -17,7 +16,7 @@ pub mod secure; pub mod matchmake_extension; pub mod matchmake_common; pub mod matchmake; -mod notification; +pub mod notification; pub mod nat_traversal; static IS_MAINTENANCE: Lazy = Lazy::new(|| { diff --git a/src/protocols/nat_traversal/method_report_nat_properties.rs b/src/nex-implementation/nat_traversal/method_report_nat_properties.rs similarity index 89% rename from src/protocols/nat_traversal/method_report_nat_properties.rs rename to src/nex-implementation/nat_traversal/method_report_nat_properties.rs index 32ba30d..7d01740 100644 --- a/src/protocols/nat_traversal/method_report_nat_properties.rs +++ b/src/nex-implementation/nat_traversal/method_report_nat_properties.rs @@ -1,8 +1,9 @@ use std::io::Cursor; use std::sync::Arc; +use std::time::Duration; use tokio::sync::{Mutex, RwLock}; +use tokio::time::sleep; use crate::protocols::matchmake_common::MatchmakeData; -use crate::prudp::socket::{ConnectionData, SocketData}; use crate::rmc::message::RMCMessage; use crate::rmc::response::{ErrorCode, RMCResponseResult}; use crate::rmc::structures::matchmake::CreateMatchmakeSessionParam; @@ -12,6 +13,7 @@ pub async fn report_nat_properties( socket: &Arc, connection_data: &Arc>, ) -> RMCResponseResult{ + sleep(Duration::from_millis(50)).await; rmcmessage.success_with_data(Vec::new()) } diff --git a/src/protocols/nat_traversal/mod.rs b/src/nex-implementation/nat_traversal/mod.rs similarity index 100% rename from src/protocols/nat_traversal/mod.rs rename to src/nex-implementation/nat_traversal/mod.rs diff --git a/src/protocols/notification/mod.rs b/src/nex-implementation/notification/mod.rs similarity index 86% rename from src/protocols/notification/mod.rs rename to src/nex-implementation/notification/mod.rs index 87340a7..50cc992 100644 --- a/src/protocols/notification/mod.rs +++ b/src/nex-implementation/notification/mod.rs @@ -3,7 +3,6 @@ use rand::random; use crate::prudp::packet::{PRUDPHeader, PRUDPPacket, PacketOption, TypesFlags}; use crate::prudp::packet::flags::{NEED_ACK, RELIABLE}; use crate::prudp::packet::types::DATA; -use crate::prudp::socket::{ConnectionData, SocketData}; use crate::rmc::message::RMCMessage; use crate::rmc::structures::RmcSerialize; @@ -30,10 +29,11 @@ impl ConnectionData{ let message = RMCMessage{ protocol_id: 14, method_id: 1, - call_id: random(), + call_id: 1, rest_of_data: data }; + println!("notif: {}", hex::encode(message.to_data())); let mut prudp_packet = PRUDPPacket{ @@ -99,23 +99,6 @@ mod test{ println!("{:?}", notif); } - #[test] - fn test3(){ - - let data = hex::decode("ead001032900a1af620084000300020100250000008e0100000001000000001700000051b39957b90b00000100000051b399570100000100000000000000000000000000000000000000").unwrap(); - let packet = PRUDPPacket::new(&mut Cursor::new(data)).expect("invalid packet"); - - println!("{:?}", packet); - - let rmc = RMCMessage::new(&mut Cursor::new(packet.payload)).expect("invalid rmc message"); - - println!("{:?}", rmc); - - let notif = Notification::deserialize(&mut Cursor::new(rmc.rest_of_data)).expect("invalid notification"); - - println!("{:?}", notif); - } - #[test] fn test_rmc_serialization(){ let notif = Notification{ diff --git a/src/protocols/secure/method_register.rs b/src/nex-implementation/secure/method_register.rs similarity index 97% rename from src/protocols/secure/method_register.rs rename to src/nex-implementation/secure/method_register.rs index fcfb438..0d1cd61 100644 --- a/src/protocols/secure/method_register.rs +++ b/src/nex-implementation/secure/method_register.rs @@ -2,7 +2,6 @@ use std::io::{Cursor, Write}; use std::sync::Arc; use bytemuck::bytes_of; use tokio::sync::Mutex; -use crate::prudp::socket::{ConnectionData, SocketData}; use crate::prudp::station_url::{nat_types, StationUrl}; use crate::prudp::station_url::Type::PRUDPS; use crate::prudp::station_url::UrlOptions::{Address, NatFiltering, NatMapping, NatType, Port, PrincipalID, RVConnectionID}; diff --git a/src/protocols/secure/method_send_report.rs b/src/nex-implementation/secure/method_send_report.rs similarity index 82% rename from src/protocols/secure/method_send_report.rs rename to src/nex-implementation/secure/method_send_report.rs index 81322f9..8242371 100644 --- a/src/protocols/secure/method_send_report.rs +++ b/src/nex-implementation/secure/method_send_report.rs @@ -3,11 +3,11 @@ use std::sync::Arc; use log::error; use tokio::sync::Mutex; use crate::endianness::{IS_BIG_ENDIAN, ReadExtensions}; -use crate::prudp::socket::{ConnectionData, SocketData}; use crate::rmc::message::RMCMessage; use crate::rmc::response::{RMCResponseResult}; use crate::rmc::response::ErrorCode::Core_InvalidArgument; -use crate::rmc::structures::qbuffer; +use crate::rmc::structures::{qbuffer, RmcSerialize}; +use crate::rmc::structures::qbuffer::QBuffer; pub async fn send_report(rmcmessage: &RMCMessage, report_id: u32, data: Vec) -> RMCResponseResult{ let result = tokio::fs::write(format!("./reports/{}", report_id), data).await; @@ -17,7 +17,7 @@ pub async fn send_report(rmcmessage: &RMCMessage, report_id: u32, data: Vec) Err(e) => error!("{}", e) } - return rmcmessage.success_with_data(Vec::new()); + rmcmessage.success_with_data(Vec::new()) } pub async fn send_report_raw_params(rmcmessage: &RMCMessage, _: &Arc, _conn_data: &Arc>, _: ()) -> RMCResponseResult{ @@ -27,7 +27,7 @@ pub async fn send_report_raw_params(rmcmessage: &RMCMessage, _: &Arc return rmcmessage.error_result_with_code(Core_InvalidArgument); }; - let Ok(data) = qbuffer::read(&mut reader) else { + let Ok(QBuffer(data)) = QBuffer::deserialize(&mut reader) else { return rmcmessage.error_result_with_code(Core_InvalidArgument); }; diff --git a/src/protocols/secure/mod.rs b/src/nex-implementation/secure/mod.rs similarity index 100% rename from src/protocols/secure/mod.rs rename to src/nex-implementation/secure/mod.rs diff --git a/src/protocols/server.rs b/src/nex-implementation/server.rs similarity index 86% rename from src/protocols/server.rs rename to src/nex-implementation/server.rs index 68fd7c2..dbf93de 100644 --- a/src/protocols/server.rs +++ b/src/nex-implementation/server.rs @@ -5,10 +5,11 @@ use std::sync::Arc; use log::error; use tokio::sync::Mutex; use crate::prudp::packet::PRUDPPacket; -use crate::prudp::socket::{ConnectionData, SocketData}; use crate::rmc::message::RMCMessage; use crate::rmc::response::{RMCResponse, RMCResponseResult, send_response}; use crate::rmc::response::ErrorCode::Core_NotImplemented; +use crate::web::DirectionalData::Incoming; +use crate::web::WEB_DATA; type ContainedProtocolList = Box<[Box Fn(&'a RMCMessage, &'a Arc, &'a Arc>) -> Pin> + Send + 'a>> + Send + Sync>]>; @@ -20,6 +21,13 @@ impl RMCProtocolServer{ } pub async fn process_message(&self, packet: PRUDPPacket, socket: Arc, connection: Arc>){ + let locked = connection.lock().await; + let addr = locked.sock_addr.regular_socket_addr; + drop(locked); + let mut web = WEB_DATA.lock().await; + web.data.push((addr, Incoming(hex::encode(&packet.payload)))); + drop(web); + let Ok(rmc) = RMCMessage::new(&mut Cursor::new(&packet.payload)) else { error!("error reading rmc message"); return; diff --git a/src/prudp/mod.rs b/src/prudp/mod.rs index b86e522..41f721c 100644 --- a/src/prudp/mod.rs +++ b/src/prudp/mod.rs @@ -2,6 +2,6 @@ pub mod packet; pub mod router; pub mod socket; mod auth_module; -mod sockaddr; -pub mod secure; +pub mod sockaddr; +//pub mod secure; pub mod station_url; \ No newline at end of file diff --git a/src/prudp/packet.rs b/src/prudp/packet.rs index 470f6b2..75dc211 100644 --- a/src/prudp/packet.rs +++ b/src/prudp/packet.rs @@ -96,10 +96,11 @@ impl Debug for TypesFlags { } #[repr(transparent)] -#[derive(PartialEq, Eq, Copy, Clone, Pod, Zeroable, SwapEndian, Hash)] +#[derive(PartialEq, Eq, Ord, PartialOrd, Copy, Clone, Pod, Zeroable, SwapEndian, Hash)] pub struct VirtualPort(pub(crate) u8); impl VirtualPort { + #[inline] pub const fn get_stream_type(self) -> u8 { (self.0 & 0xF0) >> 4 @@ -236,7 +237,7 @@ impl PacketOption{ } } -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Default, Clone, Eq, PartialEq)] pub struct PRUDPPacket { pub header: PRUDPHeader, pub packet_signature: [u8; 16], @@ -375,6 +376,7 @@ impl PRUDPPacket { types_and_flags: flags, sequence_id: self.header.sequence_id, substream_id: self.header.substream_id, + session_id: self.header.session_id, ..base.header }, options, diff --git a/src/prudp/router.rs b/src/prudp/router.rs index f70d5ec..5fd4198 100644 --- a/src/prudp/router.rs +++ b/src/prudp/router.rs @@ -11,7 +11,7 @@ use once_cell::sync::Lazy; use log::{error, info, trace}; use thiserror::Error; use tokio::sync::RwLock; -use crate::prudp::socket::SocketData; +use crate::prudp::socket::{new_socket_pair, AnyInternalSocket, CryptoHandler, ExternalSocket}; use crate::prudp::packet::{PRUDPPacket, VirtualPort}; use crate::prudp::router::Error::VirtualPortTaken; @@ -22,10 +22,9 @@ static SERVER_DATAGRAMS: Lazy = Lazy::new(||{ }); pub struct Router { - endpoints: RwLock<[Option>; 16]>, + endpoints: RwLock<[Option>; 16]>, running: AtomicBool, socket: Arc, - //pub auth_module: Arc _no_outside_construction: PhantomData<()> } #[derive(Debug, Error)] @@ -36,9 +35,6 @@ pub enum Error{ impl Router { - fn process_prudp_packet(&self, _packet: &PRUDPPacket){ - - } async fn process_prudp_packets<'a>(self: Arc, _socket: Arc, addr: SocketAddrV4, udp_message: Vec){ let mut stream = Cursor::new(&udp_message); @@ -69,7 +65,9 @@ impl Router { trace!("sending packet to endpoint"); - endpoint.process_packet(connection, &packet).await; + tokio::spawn(async move { + endpoint.recieve_packet(connection, packet).await + }); } } @@ -88,6 +86,7 @@ impl Router { continue; }; + let current_msg = &msg_buffer[0..len]; tokio::spawn(self.clone().process_prudp_packets(socket.clone(), addr, current_msg.to_vec())); @@ -144,18 +143,22 @@ impl Router { } // returns Some(()) i - pub(crate) async fn add_socket(&self, socket: Arc) -> Result<(), Error>{ + pub(crate) async fn add_socket(&self, virtual_port: VirtualPort, encryption: E) + -> Result{ let mut endpoints = self.endpoints.write().await; - let idx = socket.get_virual_port().get_port_number() as usize; + let idx = virtual_port.get_port_number() as usize; - if endpoints[idx].is_none() { - endpoints[idx] = Some(socket); - } else { + // dont create the socket if we dont need to + if !endpoints[idx].is_none(){ return Err(VirtualPortTaken(idx as u8)); } - Ok(()) + let (internal, external) = new_socket_pair(virtual_port, encryption, self.socket.clone()); + + endpoints[idx] = Some(internal); + + Ok(external) } pub fn get_own_address(&self) -> SocketAddrV4{ diff --git a/src/prudp/secure.rs b/src/prudp/secure.rs index 916971d..2689963 100644 --- a/src/prudp/secure.rs +++ b/src/prudp/secure.rs @@ -73,12 +73,12 @@ pub fn read_secure_connection_data(data: &[u8], act: &Account) -> Option<([u8; 3 type Rc4U32 = StreamCipherCoreWrapper>; -pub fn generate_secure_encryption_pairs(mut session_key: [u8; 32], count: u8) -> Vec{ +pub fn generate_secure_encryption_pairs(mut session_key: [u8; 32], count: u8) -> Vec>>{ let mut vec = Vec::with_capacity(count as usize); vec.push(EncryptionPair{ - send: Box::new(Rc4U32::new_from_slice(&session_key).expect("unable to create rc4")), - recv: Box::new(Rc4U32::new_from_slice(&session_key).expect("unable to create rc4")) + send: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4"), + recv: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4") }); for _ in 1..=count{ @@ -91,8 +91,8 @@ pub fn generate_secure_encryption_pairs(mut session_key: [u8; 32], count: u8) -> } vec.push(EncryptionPair{ - send: Box::new(Rc4U32::new_from_slice(&session_key).expect("unable to create rc4")), - recv: Box::new(Rc4U32::new_from_slice(&session_key).expect("unable to create rc4")) + send: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4"), + recv: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4") }); } diff --git a/src/prudp/sockaddr.rs b/src/prudp/sockaddr.rs index b48b8c1..75254bf 100644 --- a/src/prudp/sockaddr.rs +++ b/src/prudp/sockaddr.rs @@ -5,14 +5,24 @@ use crate::prudp::packet::VirtualPort; type Md5Hmac = Hmac; -#[derive(Eq, PartialEq, Hash, Debug, Copy, Clone)] +#[derive(Eq, PartialEq, Hash, Debug, Copy, Clone, Ord, PartialOrd)] pub struct PRUDPSockAddr{ pub regular_socket_addr: SocketAddrV4, pub virtual_port: VirtualPort } + + impl PRUDPSockAddr{ - pub fn calculate_connection_signature(&self) -> [u8; 16] { + + pub fn new(regular_socket_addr: SocketAddrV4, virtual_port: VirtualPort) -> Self{ + Self{ + regular_socket_addr, + virtual_port + } + } + + pub(super) fn calculate_connection_signature(&self) -> [u8; 16] { let mut hmac = Md5Hmac::new_from_slice(&[0; 16]).expect("fuck"); let mut data = self.regular_socket_addr.ip().octets().to_vec(); diff --git a/src/prudp/socket.rs b/src/prudp/socket.rs index 9068ba2..9c4db03 100644 --- a/src/prudp/socket.rs +++ b/src/prudp/socket.rs @@ -1,156 +1,57 @@ -use log::info; -use std::collections::{HashMap, VecDeque}; -use std::fmt::{Debug, Formatter}; -use std::future::Future; -use std::ops::Deref; -use std::pin::Pin; -use tokio::net::UdpSocket; -use std::sync::{Arc}; -use tokio::sync::{Mutex, RwLock}; -use log::{error, trace, warn}; -use rand::random; -use rc4::StreamCipher; -use crate::prudp::packet::{PacketOption, PRUDPPacket, VirtualPort}; use crate::prudp::packet::flags::{ACK, HAS_SIZE, MULTI_ACK, NEED_ACK, RELIABLE}; -use crate::prudp::packet::PacketOption::{ConnectionSignature, MaximumSubstreamId, SupportedFunctions}; use crate::prudp::packet::types::{CONNECT, DATA, DISCONNECT, PING, SYN}; +use crate::prudp::packet::PacketOption::{ConnectionSignature, FragmentId, MaximumSubstreamId, SupportedFunctions}; +use crate::prudp::packet::{PRUDPHeader, PRUDPPacket, PacketOption, TypesFlags, VirtualPort}; use crate::prudp::router::{Error, Router}; use crate::prudp::sockaddr::PRUDPSockAddr; - - +use crate::web::DirectionalData::Outgoing; +use crate::web::WEB_DATA; +use async_trait::async_trait; +use hmac::digest::consts::U5; +use log::info; +use log::{error, trace, warn}; +use once_cell::sync::Lazy; +use rand::random; +use rc4::{Key, KeyInit, Rc4, StreamCipher}; +use rocket::http::hyper::body::HttpBody; +use std::collections::{BTreeMap, HashMap, VecDeque}; +use std::fmt::{Debug, Formatter}; +use std::future::Future; +use std::marker::PhantomData; +use std::mem; +use std::net::SocketAddrV4; +use std::ops::Deref; +use std::pin::Pin; +use std::sync::{Arc, Weak}; +use tokio::net::UdpSocket; +use tokio::sync::mpsc::{channel, Receiver, Sender}; +use tokio::sync::{Mutex, RwLock}; +use tokio_stream::Stream; // due to the way this is designed crashing the router thread causes deadlock, sorry ;-; // (maybe i will fix that some day) /// PRUDP Socket for accepting connections to then send and recieve data from those clients -pub struct Socket { - socket_data: Arc, - router: Arc, + + +pub struct EncryptionPair { + pub send: T, + pub recv: T, } - -type OnConnectHandlerFn = Box Pin, Vec, Option)>> + Send>> + Send + Sync>; -type OnDataHandlerFn = Box, Arc>) -> Pin + Send>> + Send + Sync>; - -#[derive(Debug)] -pub struct ActiveSecureConnectionData { - pub(crate) pid: u32, - pub(crate) session_key: [u8; 32], -} - -pub struct SocketData { - virtual_port: VirtualPort, - pub socket: Arc, - pub access_key: &'static str, - connections: RwLock>, Arc>)>>, - on_connect_handler: OnConnectHandlerFn, - on_data_handler: OnDataHandlerFn, - -} - -pub struct EncryptionPair{ - pub send: Box, - pub recv: Box -} - -impl Debug for EncryptionPair{ - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "Stubbed") - } -} - -#[derive(Debug)] -pub struct ActiveConnectionData { - pub reliable_client_counter: u16, - pub reliable_server_counter: u16, - pub reliable_client_queue: VecDeque, - pub encryption_pairs: Vec, - pub server_session_id: u8, - pub connection_id: u32, - pub active_secure_connection_data: Option -} - - -#[derive(Debug)] -pub struct ConnectionData { - pub sock_addr: PRUDPSockAddr, - pub id: u64, - pub signature: [u8; 16], - pub server_signature: [u8; 16], - pub active_connection_data: Option, -} - - - - -impl Socket { - pub async fn new( - router: Arc, - port: VirtualPort, - access_key: &'static str, - on_connection_handler: OnConnectHandlerFn, - on_data_handler: OnDataHandlerFn, - ) -> Result { - trace!("creating socket on router at {} on virtual port {:?}", router.get_own_address(), port); - - let socket_data = Arc::new( - SocketData::new_unbound(&router, port, access_key, on_connection_handler, on_data_handler) - ); - - router.add_socket(socket_data.clone()).await?; - - Ok(Self { - socket_data, - router, - }) - } -} - -impl Drop for Socket { - fn drop(&mut self) { - { - let router = self.router.clone(); - - let virtual_port = self.virtual_port; - trace!("socket dropped socket will be removed from router soon"); - // it's not that important to remove it immediately so we can delay the deletion a bit if needed - tokio::spawn(async move { - router.remove_socket(virtual_port).await; - trace!("socket removed from router successfully"); - }); +impl EncryptionPair { + fn init_both T>(func: F) -> Self { + Self { + recv: func(), + send: func(), } } } - -impl Deref for Socket { - type Target = SocketData; - fn deref(&self) -> &Self::Target { - &self.socket_data - } -} - - -impl SocketData { - fn new_unbound(router: &Router, - port: VirtualPort, - access_key: &'static str, - on_connect_handler: OnConnectHandlerFn, - on_data_handler: OnDataHandlerFn, - ) -> Self { - SocketData { - socket: router.get_udp_socket(), - virtual_port: port, - connections: Default::default(), - access_key, - on_connect_handler, - on_data_handler, - } - } - - pub fn get_virual_port(&self) -> VirtualPort { - self.virtual_port - } - - pub async fn process_packet(self: &Arc, client_address: PRUDPSockAddr, packet: &PRUDPPacket) { +/* + pub async fn process_packet( + self: &Arc, + client_address: PRUDPSockAddr, + packet: &PRUDPPacket, + ) { let conn = self.connections.read().await; if !conn.contains_key(&client_address) { @@ -159,14 +60,20 @@ impl SocketData { let mut conn = self.connections.write().await; //only insert if we STILL dont have the connection preventing double insertion if !conn.contains_key(&client_address) { - conn.insert(client_address, (Arc::new(Mutex::new(ConnectionData { - sock_addr: client_address, - id: random(), - signature: [0; 16], - server_signature: [0; 16], + conn.insert( + client_address, + ( + Arc::new(Mutex::new(ConnectionData { + sock_addr: client_address, + id: random(), + signature: [0; 16], + server_signature: [0; 16], - active_connection_data: None, - })), Arc::new(Mutex::new(())))); + active_connection_data: None, + })), + Arc::new(Mutex::new(())), + ), + ); } drop(conn); } else { @@ -199,7 +106,6 @@ impl SocketData { return; } - match packet.header.types_and_flags.get_types() { SYN => { println!("got syn"); @@ -212,16 +118,18 @@ impl SocketData { connection.signature = client_address.calculate_connection_signature(); - response_packet.options.push(ConnectionSignature(connection.signature)); + response_packet + .options + .push(ConnectionSignature(connection.signature)); for options in &packet.options { match options { - SupportedFunctions(functions) => { - response_packet.options.push(SupportedFunctions(*functions & 0x04)) - } - MaximumSubstreamId(max_substream) => { - response_packet.options.push(MaximumSubstreamId(*max_substream)) - } + SupportedFunctions(functions) => response_packet + .options + .push(SupportedFunctions(*functions & 0x04)), + MaximumSubstreamId(max_substream) => response_packet + .options + .push(MaximumSubstreamId(*max_substream)), _ => { /* ??? */ } } } @@ -232,26 +140,32 @@ impl SocketData { let mut vec = Vec::new(); - response_packet.write_to(&mut vec).expect("somehow failed to convert backet to bytes"); + response_packet + .write_to(&mut vec) + .expect("somehow failed to convert backet to bytes"); - self.socket.send_to(&vec, client_address.regular_socket_addr).await.expect("failed to send data back"); + self.socket + .send_to(&vec, client_address.regular_socket_addr) + .await + .expect("failed to send data back"); } CONNECT => { println!("got connect"); - let Some(MaximumSubstreamId(max_substream)) = packet.options.iter().find(|v| matches!(v, MaximumSubstreamId(_))) else { + let Some(MaximumSubstreamId(max_substream)) = packet + .options + .iter() + .find(|v| matches!(v, MaximumSubstreamId(_))) + else { return; }; - let Some(( - response_data, - encryption_pairs, - active_secure_connection_data - )) = (self.on_connect_handler)(packet.clone(), *max_substream).await else { + let Some((response_data, encryption_pairs, active_secure_connection_data)) = + (self.on_connect_handler)(packet.clone(), *max_substream).await + else { error!("invalid connection request"); return; }; - connection.active_connection_data = Some(ActiveConnectionData { encryption_pairs, reliable_client_queue: VecDeque::new(), @@ -259,7 +173,7 @@ impl SocketData { reliable_server_counter: 1, server_session_id: packet.header.session_id, active_secure_connection_data, - connection_id: random() + connection_id: random(), }); let mut response_packet = packet.base_response_packet(); @@ -275,17 +189,21 @@ impl SocketData { response_packet.header.session_id = packet.header.session_id; response_packet.header.sequence_id = 1; - response_packet.options.push(ConnectionSignature(Default::default())); + response_packet + .options + .push(ConnectionSignature(Default::default())); //let mut init_seq_id = 0; for option in &packet.options { match option { - MaximumSubstreamId(max_substream) => response_packet.options.push(MaximumSubstreamId(*max_substream)), - SupportedFunctions(funcs) => response_packet.options.push(SupportedFunctions(*funcs)), - ConnectionSignature(sig) => { - connection.server_signature = *sig + MaximumSubstreamId(max_substream) => response_packet + .options + .push(MaximumSubstreamId(*max_substream)), + SupportedFunctions(funcs) => { + response_packet.options.push(SupportedFunctions(*funcs)) } + ConnectionSignature(sig) => connection.server_signature = *sig, PacketOption::InitialSequenceId(_id) => { //init_seq_id = *id; } @@ -305,14 +223,21 @@ impl SocketData { response_packet.set_sizes(); - response_packet.calculate_and_assign_signature(self.access_key, None, Some(connection.server_signature)); + response_packet.calculate_and_assign_signature( + self.access_key, + None, + Some(connection.server_signature), + ); let mut vec = Vec::new(); - response_packet.write_to(&mut vec).expect("somehow failed to convert backet to bytes"); - - self.socket.send_to(&vec, client_address.regular_socket_addr).await.expect("failed to send data back"); - + response_packet + .write_to(&mut vec) + .expect("somehow failed to convert backet to bytes"); + self.socket + .send_to(&vec, client_address.regular_socket_addr) + .await + .expect("failed to send data back"); } DATA => { if (packet.header.types_and_flags.get_flags() & RELIABLE) != 0 { @@ -321,12 +246,16 @@ impl SocketData { return; }; - match active_connection.reliable_client_queue.binary_search_by_key(&packet.header.sequence_id, |p| p.header.sequence_id) { + match active_connection + .reliable_client_queue + .binary_search_by_key(&packet.header.sequence_id, |p| p.header.sequence_id) + { Ok(_) => warn!("recieved packet twice"), - Err(position) => active_connection.reliable_client_queue.insert(position, packet.clone()), + Err(position) => active_connection + .reliable_client_queue + .insert(position, packet.clone()), } - if (packet.header.types_and_flags.get_flags() & NEED_ACK) != 0 { let mut ack = packet.base_acknowledgement_packet(); ack.header.session_id = active_connection.server_session_id; @@ -335,34 +264,51 @@ impl SocketData { let potential_session_key = connection .active_connection_data .as_ref() - .unwrap().active_secure_connection_data + .unwrap() + .active_secure_connection_data .as_ref() .map(|s| s.session_key); - ack.calculate_and_assign_signature(self.access_key, potential_session_key, Some(connection.server_signature)); + ack.calculate_and_assign_signature( + self.access_key, + potential_session_key, + Some(connection.server_signature), + ); let mut vec = Vec::new(); - ack.write_to(&mut vec).expect("somehow failed to convert backet to bytes"); + ack.write_to(&mut vec) + .expect("somehow failed to convert backet to bytes"); - self.socket.send_to(&vec, client_address.regular_socket_addr).await.expect("failed to send data back"); + self.socket + .send_to(&vec, client_address.regular_socket_addr) + .await + .expect("failed to send data back"); } drop(connection); while let Some(mut packet) = { let mut locked = conn.0.lock().await; - let packet = locked.active_connection_data.as_mut().map(|a| - a.reliable_client_queue - .front() - .is_some_and(|v| v.header.sequence_id == a.reliable_client_counter) - .then(|| a.reliable_client_queue.pop_front())).flatten().flatten(); + let packet = locked + .active_connection_data + .as_mut() + .map(|a| { + a.reliable_client_queue + .front() + .is_some_and(|v| { + v.header.sequence_id == a.reliable_client_counter + }) + .then(|| a.reliable_client_queue.pop_front()) + }) + .flatten() + .flatten(); drop(locked); packet } { - if packet.options.iter().any(|v| match v{ + if packet.options.iter().any(|v| match v { PacketOption::FragmentId(f) => *f != 0, _ => false, - }){ + }) { error!("fragmented packets are unsupported right now") } @@ -371,9 +317,16 @@ impl SocketData { let active_connection = locked.active_connection_data.as_mut() .expect("we litterally just recieved a packet which requires the connection to be active, failing this should be impossible"); - active_connection.reliable_client_counter = active_connection.reliable_client_counter.overflowing_add(1).0; + active_connection.reliable_client_counter = active_connection + .reliable_client_counter + .overflowing_add(1) + .0; - let Some(stream) = active_connection.encryption_pairs.get_mut(packet.header.substream_id as usize).map(|e| &mut e.recv) else { + let Some(stream) = active_connection + .encryption_pairs + .get_mut(packet.header.substream_id as usize) + .map(|e| &mut e.recv) + else { return; }; @@ -411,17 +364,25 @@ impl SocketData { ack.set_sizes(); - let potential_session_key = active_connection. - active_secure_connection_data + let potential_session_key = active_connection + .active_secure_connection_data .as_ref() .map(|s| s.session_key); - ack.calculate_and_assign_signature(self.access_key, potential_session_key, Some(*server_signature)); + ack.calculate_and_assign_signature( + self.access_key, + potential_session_key, + Some(*server_signature), + ); let mut vec = Vec::new(); - ack.write_to(&mut vec).expect("somehow failed to convert backet to bytes"); + ack.write_to(&mut vec) + .expect("somehow failed to convert backet to bytes"); - self.socket.send_to(&vec, client_address.regular_socket_addr).await.expect("failed to send data back"); + self.socket + .send_to(&vec, client_address.regular_socket_addr) + .await + .expect("failed to send data back"); } } DISCONNECT => { @@ -436,31 +397,57 @@ impl SocketData { ack.set_sizes(); - let potential_session_key = active_connection.active_secure_connection_data + let potential_session_key = active_connection + .active_secure_connection_data .as_ref() .map(|s| s.session_key); - ack.calculate_and_assign_signature(self.access_key, potential_session_key, Some(connection.server_signature)); + ack.calculate_and_assign_signature( + self.access_key, + potential_session_key, + Some(connection.server_signature), + ); let mut vec = Vec::new(); - ack.write_to(&mut vec).expect("somehow failed to convert backet to bytes"); + ack.write_to(&mut vec) + .expect("somehow failed to convert backet to bytes"); - self.socket.send_to(&vec, client_address.regular_socket_addr).await.expect("failed to send data back"); - self.socket.send_to(&vec, client_address.regular_socket_addr).await.expect("failed to send data back"); - self.socket.send_to(&vec, client_address.regular_socket_addr).await.expect("failed to send data back"); + self.socket + .send_to(&vec, client_address.regular_socket_addr) + .await + .expect("failed to send data back"); + self.socket + .send_to(&vec, client_address.regular_socket_addr) + .await + .expect("failed to send data back"); + self.socket + .send_to(&vec, client_address.regular_socket_addr) + .await + .expect("failed to send data back"); } - _ => error!("unimplemented packet type: {}", packet.header.types_and_flags.get_types()) + _ => error!( + "unimplemented packet type: {}", + packet.header.types_and_flags.get_types() + ), } drop(mutual_exclusion_packet_handeling_mtx) - } -} + }*/ +/* +impl ConnectionData { + pub async fn finish_and_send_packet_to( + &mut self, + socket: &SocketData, + mut packet: PRUDPPacket, + ) { + let mut web = WEB_DATA.lock().await; + web.data.push(( + self.sock_addr.regular_socket_addr, + Outgoing(hex::encode(&packet.payload)), + )); + drop(web); -impl ConnectionData{ - pub async fn finish_and_send_packet_to(&mut self, socket: &SocketData, mut packet: PRUDPPacket){ - - - if (packet.header.types_and_flags.get_flags() & RELIABLE) != 0{ + if (packet.header.types_and_flags.get_flags() & RELIABLE) != 0 { let Some(active_connection) = self.active_connection_data.as_mut() else { error!("tried to send a secure packet to an inactive connection"); return; @@ -469,80 +456,748 @@ impl ConnectionData{ packet.header.sequence_id = active_connection.reliable_server_counter; active_connection.reliable_server_counter += 1; - let Some(encryption) = active_connection.encryption_pairs.get_mut(packet.header.substream_id as usize).map(|e| &mut e.send) else { + let Some(encryption) = active_connection + .encryption_pairs + .get_mut(packet.header.substream_id as usize) + .map(|e| &mut e.send) + else { return; }; encryption.apply_keystream(&mut packet.payload); } - packet.header.session_id = self.active_connection_data.as_ref().map(|v| v.server_session_id).unwrap_or_default(); - - + packet.header.session_id = self + .active_connection_data + .as_ref() + .map(|v| v.server_session_id) + .unwrap_or_default(); packet.header.source_port = socket.virtual_port; packet.header.destination_port = self.sock_addr.virtual_port; packet.set_sizes(); - let potential_session_key = self.active_connection_data + let potential_session_key = self + .active_connection_data .as_ref() - .unwrap().active_secure_connection_data + .unwrap() + .active_secure_connection_data .as_ref() .map(|s| s.session_key); - - packet.calculate_and_assign_signature(socket.access_key, potential_session_key, Some(self.server_signature)); + packet.calculate_and_assign_signature( + socket.access_key, + potential_session_key, + Some(self.server_signature), + ); let mut vec = Vec::new(); - packet.write_to(&mut vec).expect("somehow failed to convert backet to bytes"); + packet + .write_to(&mut vec) + .expect("somehow failed to convert backet to bytes"); - if let Err(e) = socket.socket.send_to(&vec, self.sock_addr.regular_socket_addr).await{ + if let Err(e) = socket + .socket + .send_to(&vec, self.sock_addr.regular_socket_addr) + .await + { error!("unable to send packet to destination: {}", e); } } - - +}*/ + +pub struct NewEncryptionPair { + pub send: E, + pub recv: E, } -#[cfg(test)] -mod test { - use std::io::Cursor; - use std::net::{Ipv4Addr, SocketAddrV4}; - use std::sync::Arc; - use tokio::net::UdpSocket; - use tokio::sync::mpsc::channel; - use crate::prudp::packet::{PRUDPPacket, VirtualPort}; - use crate::prudp::sockaddr::PRUDPSockAddr; - use crate::prudp::socket::SocketData; +pub struct CommonConnection { + pub user_id: u32, + session_id: u8, + pub socket_addr: PRUDPSockAddr, + pub server_port: VirtualPort +} - /*#[tokio::test] - async fn test_connect() { - let packet_1 = [234, 208, 1, 27, 0, 0, 175, 161, 192, 0, 0, 0, 0, 0, 36, 21, 233, 179, 203, 154, 57, 222, 219, 9, 21, 2, 29, 172, 56, 92, 0, 4, 4, 1, 0, 0, 1, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0]; - let packet_2 = [234, 208, 1, 31, 0, 0, 175, 161, 225, 0, 249, 0, 1, 0, 40, 168, 31, 138, 58, 193, 30, 134, 3, 232, 205, 245, 28, 155, 193, 198, 0, 4, 0, 0, 0, 0, 1, 16, 211, 240, 113, 188, 227, 114, 114, 30, 157, 179, 246, 55, 233, 240, 44, 197, 3, 2, 247, 244, 4, 1, 0]; +struct InternalConnection { + common: Arc, + reliable_server_counter: u16, + reliable_client_counter: u16, + // maybe add connection id(need to see if its even needed) + crypto_handler_instance: E, + data_sender: Sender>, + socket: Arc +} - let packet_1 = PRUDPPacket::new(&mut Cursor::new(packet_1)).unwrap(); - let packet_2 = PRUDPPacket::new(&mut Cursor::new(packet_2)).unwrap(); +impl Deref for InternalConnection{ + type Target = CommonConnection; + fn deref(&self) -> &Self::Target { + &self.common + } +} + +impl InternalConnection{ + fn next_server_count(&mut self) -> u16{ + let (val, _) = self.reliable_server_counter.overflowing_add(1); + self.reliable_server_counter = val; + val + } +} + +pub struct ExternalConnection { + sending: SendingConnection, + data_receiver: Receiver>, +} + +#[derive(Clone)] +pub struct SendingConnection{ + common: Arc, + inernal: Weak> +} + +pub struct CommonSocket { + pub virtual_port: VirtualPort, + _phantom_unconstructible: PhantomData<()>, +} + +pub(super) struct InternalSocket { + common: Arc, + socket: Arc, + crypto_handler: T, + // perf note: change the code to use RwLock here instead to avoid connections being able to block one another before the data is sent off. + internal_connections: Arc< + Mutex>>>>, + >, + connection_establishment_data_sender: Mutex>>, + connection_sender: Sender, +} + +pub struct ExternalSocket { + common: Arc, + connection_receiver: Receiver, + internal: Weak, +} + +impl ExternalSocket{ + pub async fn connect(&mut self, addr: PRUDPSockAddr) -> Option{ + let socket = self.internal.upgrade()?; + + socket.connect(addr).await; + + self.connection_receiver.recv().await + } + + pub async fn accept(&mut self) -> Option{ + self.connection_receiver.recv().await + } +} + +impl Deref for ExternalSocket { + type Target = CommonSocket; + fn deref(&self) -> &Self::Target { + &self.common + } +} + +impl Deref for InternalSocket { + type Target = CommonSocket; + fn deref(&self) -> &Self::Target { + &self.common + } +} + +#[async_trait] +pub(super) trait AnyInternalSocket: + Send + Sync + Deref + 'static +{ + async fn recieve_packet(&self, address: PRUDPSockAddr, packet: PRUDPPacket); + async fn connect(&self, address: PRUDPSockAddr) -> Option<()>; +} + +#[async_trait] +pub(super) trait AnyInternalConnection: + Send + Sync + Deref + 'static +{ + async fn send_data_packet(&mut self, data: Vec); +} + +#[async_trait] +impl AnyInternalConnection for InternalConnection{ + async fn send_data_packet(&mut self, data: Vec) { + let mut packet = PRUDPPacket{ + header: PRUDPHeader{ + sequence_id: self.next_server_count(), + substream_id: 0, + session_id: self.session_id, + types_and_flags: TypesFlags::default().types(DATA).flags(RELIABLE | NEED_ACK), + destination_port: self.common.socket_addr.virtual_port, + source_port: self.server_port, + ..Default::default() + }, + payload: data, + options: vec![FragmentId(0)], + ..Default::default() + }; + + self.crypto_handler_instance.encrypt_outgoing(0, &mut packet.payload[..]); + + packet.set_sizes(); + + self.crypto_handler_instance.sign_packet(&mut packet); + + packet.set_sizes(); + + let mut vec = Vec::new(); + + packet + .write_to(&mut vec) + .expect("somehow failed to convert backet to bytes"); + + self.socket + .send_to(&vec, self.socket_addr.regular_socket_addr) + .await + .expect("failed to send data back"); + } +} + +impl InternalSocket { + async fn send_packet_unbuffered(&self, dest: PRUDPSockAddr, mut packet: PRUDPPacket) { + packet.set_sizes(); + + let mut vec = Vec::new(); + + packet + .write_to(&mut vec) + .expect("somehow failed to convert backet to bytes"); + + self.socket + .send_to(&vec, dest.regular_socket_addr) + .await + .expect("failed to send data back"); + } + + async fn handle_syn(&self, address: PRUDPSockAddr, packet: PRUDPPacket) { + info!("got syn"); + + let mut response = packet.base_acknowledgement_packet(); + + let signature = address.calculate_connection_signature(); + + response.options.push(ConnectionSignature(signature)); + + // todo: refactor this to be more readable(low priority cause it doesnt change anything api wise) + for options in &packet.options { + match options { + SupportedFunctions(functions) => response + .options + .push(SupportedFunctions(*functions & 0x04)), + MaximumSubstreamId(max_substream) => response + .options + .push(MaximumSubstreamId(*max_substream)), + _ => { /* ??? */ } + } + } + + response.header.types_and_flags.set_flag(HAS_SIZE | ACK); + + self.crypto_handler.sign_pre_handshake(&mut response); + + self.send_packet_unbuffered(address, response) + .await; + } + + async fn connection_thread( + socket: Arc, + self_port: VirtualPort, + connection: Arc>>, + mut data_recv: Receiver> + ) { + //todo: handle stuff like resending packets if they arent acknowledged in here + while let Some(data) = data_recv.recv().await{ + let mut locked_conn = connection.lock().await; + let packet = PRUDPPacket{ + header: PRUDPHeader{ + sequence_id: locked_conn.next_server_count(), + substream_id: 0, + session_id: locked_conn.session_id, + types_and_flags: TypesFlags::default().types(DATA).flags(RELIABLE | NEED_ACK), + destination_port: locked_conn.common.socket_addr.virtual_port, + source_port: self_port, + ..Default::default() + }, + payload: data, + options: vec![FragmentId(0)], + ..Default::default() + }; + + //packet. - let (send, recv) = channel(100); - let sock = Arc::new(SocketData { - connections: Default::default(), - access_key: "6f599f81", - virtual_port: VirtualPort(0), - socket: Arc::new(UdpSocket::bind(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 10000)).await.unwrap()), - connection_creation_sender: send, + + + + } + } + + async fn create_connection( + &self, + crypto_handler_instance: T::CryptoConnectionInstance, + socket_addr: PRUDPSockAddr, + session_id: u8, + ) { + let common = Arc::new(CommonConnection { + user_id: crypto_handler_instance.get_user_id(), + socket_addr, + session_id, + server_port: self.virtual_port }); - println!("sent: {:?}", packet_1); - sock.process_packet(PRUDPSockAddr { - virtual_port: VirtualPort(0), - regular_socket_addr: SocketAddrV4::new(Ipv4Addr::LOCALHOST, 2469), - }, &packet_1).await; - println!("sent: {:?}", packet_2); - sock.process_packet(PRUDPSockAddr { - virtual_port: VirtualPort(0), - regular_socket_addr: SocketAddrV4::new(Ipv4Addr::LOCALHOST, 2469), - }, &packet_2).await; - }*/ -} \ No newline at end of file + + let (data_sender_from_client, data_receiver_from_client) = channel(16); + + let internal = InternalConnection { + common: common.clone(), + crypto_handler_instance, + reliable_client_counter: 2, + reliable_server_counter: 1, + data_sender: data_sender_from_client, + socket: self.socket.clone() + }; + + let internal = Arc::new(Mutex::new(internal)); + + let dyn_internal: Arc> = internal.clone(); + + let external = ExternalConnection { + sending: SendingConnection{ + common, + inernal: Arc::downgrade(&dyn_internal) + }, + data_receiver: data_receiver_from_client, + + }; + + + + + + let mut connections = self.internal_connections.lock().await; + + connections.insert(socket_addr, internal.clone()); + + drop(connections); + + self.connection_sender + .send(external) + .await + .expect("connection to external socket lost"); + } + + async fn handle_connect(&self, address: PRUDPSockAddr, packet: PRUDPPacket) { + info!("got connect"); + let Some(MaximumSubstreamId(max_substream)) = packet + .options + .iter() + .find(|v| matches!(v, MaximumSubstreamId(_))) + else { + return; + }; + + let remote_signature = address.calculate_connection_signature(); + + let Some(ConnectionSignature(own_signature)) = packet + .options + .iter() + .find(|p| matches!(p, ConnectionSignature(_))) + else { + error!("didnt get connection signature from client"); + return; + }; + + let session_id = packet.header.session_id; + + let (return_data, crypto) = self.crypto_handler.instantiate( + remote_signature, + *own_signature, + &packet.payload, + *max_substream, + ); + + let mut response = packet.base_acknowledgement_packet(); + response.header.types_and_flags.set_flag(HAS_SIZE | ACK); + response.header.session_id = session_id; + response.payload = return_data; + + crypto.sign_connect(&mut response); + + self.create_connection(crypto, address, session_id).await; + + self.send_packet_unbuffered(address, response).await; + } + + async fn handle_data(&self, address: PRUDPSockAddr, mut packet: PRUDPPacket) { + info!("got data"); + + if packet.header.types_and_flags.get_flags() & (NEED_ACK | RELIABLE) != (NEED_ACK | RELIABLE){ + error!("invalid or unimplemented packet flags"); + } + + let connections = self.internal_connections.lock().await; + let Some(conn) = connections.get(&address) else{ + error!("tried to send data on inactive connection!"); + return + }; + let conn = conn.clone(); + drop(connections); + + let mut conn = conn.lock().await; + + conn.crypto_handler_instance.decrypt_incoming(packet.header.substream_id, &mut packet.payload[..]); + + let mut data = Vec::new(); + + mem::swap(&mut data, &mut packet.payload); + + conn.data_sender.send(data).await.expect("socket died"); + + if packet.header.types_and_flags.get_flags() & NEED_ACK == 0{ + return; + } + + let mut response = packet.base_acknowledgement_packet(); + response.header.types_and_flags.set_flag(HAS_SIZE | ACK); + response.header.session_id = conn.session_id; + + conn.crypto_handler_instance.sign_packet(&mut response); + + self.send_packet_unbuffered(address, response).await; + } + + async fn handle_ping(&self, address: PRUDPSockAddr, packet: PRUDPPacket){ + let connections = self.internal_connections.lock().await; + let Some(conn) = connections.get(&address) else{ + error!("tried to send data on inactive connection!"); + return + }; + let conn = conn.clone(); + drop(connections); + + let mut conn = conn.lock().await; + + let mut response = packet.base_acknowledgement_packet(); + response.header.types_and_flags.set_flag(HAS_SIZE | ACK); + response.header.session_id = conn.session_id; + + conn.crypto_handler_instance.sign_packet(&mut response); + + self.send_packet_unbuffered(address, response).await; + } + + async fn handle_disconnect(&self, address: PRUDPSockAddr, packet: PRUDPPacket){ + let connections = self.internal_connections.lock().await; + let Some(conn) = connections.get(&address) else{ + error!("tried to send data on inactive connection!"); + return + }; + let conn = conn.clone(); + drop(connections); + + let mut conn = conn.lock().await; + + let mut response = packet.base_acknowledgement_packet(); + response.header.types_and_flags.set_flag(HAS_SIZE | ACK); + response.header.session_id = conn.session_id; + + conn.crypto_handler_instance.sign_packet(&mut response); + + self.send_packet_unbuffered(address, response.clone()).await; + self.send_packet_unbuffered(address, response.clone()).await; + self.send_packet_unbuffered(address, response).await; + } +} + +#[async_trait] +impl AnyInternalSocket for InternalSocket { + async fn recieve_packet(&self, address: PRUDPSockAddr, packet: PRUDPPacket) { + // todo: handle acks + if (packet.header.types_and_flags.get_flags() & ACK) != 0 { + info!("got ack"); + if packet.header.types_and_flags.get_types() == SYN || + packet.header.types_and_flags.get_types() == CONNECT{ + let sender = self.connection_establishment_data_sender.lock().await; + info!("redirecting ack to active connection establishment code"); + + if let Some(conn) = sender.as_ref(){ + if let Err(e) = conn.send(packet).await { + error!("error whilest sending data to connection establishment: {}", e); + } + } else { + error!("got connection response without the active reciever being present"); + } + } + return; + } + + if (packet.header.types_and_flags.get_flags() & MULTI_ACK) != 0 { + info!("got multi ack"); + return; + } + + match packet.header.types_and_flags.get_types() { + SYN => self.handle_syn(address, packet).await, + CONNECT => self.handle_connect(address, packet).await, + DATA => self.handle_data(address, packet).await, + _ => { + error!( + "unimplemented packet type: {}", + packet.header.types_and_flags.get_types() + ) + } + } + } + + async fn connect(&self, address: PRUDPSockAddr) -> Option<()> { + let (send, mut recv) = channel(10); + + let mut sender = self.connection_establishment_data_sender.lock().await; + *sender = Some(send); + drop(sender); + + let remote_signature = address.calculate_connection_signature(); + + let packet = PRUDPPacket{ + header: PRUDPHeader{ + source_port: self.virtual_port, + destination_port: address.virtual_port, + types_and_flags: TypesFlags::default().types(SYN).flags(NEED_ACK), + ..Default::default() + }, + options: vec![ + SupportedFunctions(0x104), + MaximumSubstreamId(1), + ConnectionSignature(remote_signature) + ], + ..Default::default() + }; + + + + self.send_packet_unbuffered(address, packet).await; + + let Some(syn_ack_packet) = recv.recv().await else{ + error!("what"); + return None; + }; + + let Some(ConnectionSignature(own_signature)) = syn_ack_packet + .options + .iter() + .find(|p| matches!(p, ConnectionSignature(_))) + else { + error!("didnt get connection signature from remote partner"); + return None; + }; + + + + let packet = PRUDPPacket{ + header: PRUDPHeader{ + source_port: self.virtual_port, + destination_port: address.virtual_port, + types_and_flags: TypesFlags::default().types(CONNECT).flags(NEED_ACK), + ..Default::default() + }, + options: vec![ + SupportedFunctions(0x04), + MaximumSubstreamId(1), + ConnectionSignature(remote_signature) + ], + ..Default::default() + }; + + self.send_packet_unbuffered(address, packet).await; + + let Some(connect_ack_packet) = recv.recv().await else{ + error!("what"); + return None; + }; + + let (_, crypt) = self.crypto_handler.instantiate(remote_signature, *own_signature, &[], 1); + + //todo: make this work for secure servers as well + self.create_connection(crypt, address, 0).await; + + Some(()) + } +} + +pub(super) fn new_socket_pair( + virtual_port: VirtualPort, + encryption: T, + socket: Arc, +) -> (Arc>, ExternalSocket) { + let common = Arc::new(CommonSocket { + virtual_port, + _phantom_unconstructible: Default::default(), + }); + + let (connection_send, connection_recv) = channel(16); + + let internal = Arc::new(InternalSocket { + common: common.clone(), + connection_sender: connection_send, + crypto_handler: encryption, + internal_connections: Default::default(), + connection_establishment_data_sender: Default::default(), + socket, + }); + + let dyn_internal: Arc = internal.clone(); + + let external = ExternalSocket { + common, + connection_receiver: connection_recv, + internal: Arc::downgrade(&dyn_internal), + }; + + (internal, external) +} + +pub trait CryptoHandlerConnectionInstance: Send + Sync + 'static { + type Encryption: StreamCipher + Send; + + fn decrypt_incoming(&mut self, substream: u8, data: &mut [u8]); + fn encrypt_outgoing(&mut self, substream: u8, data: &mut [u8]); + + fn get_user_id(&self) -> u32; + fn sign_connect(&self, packet: &mut PRUDPPacket); + fn sign_packet(&self, packet: &mut PRUDPPacket); + fn verify_packet(&self, packet: &PRUDPPacket) -> bool; +} + +pub trait CryptoHandler: Send + Sync + 'static { + type CryptoConnectionInstance: CryptoHandlerConnectionInstance; + + fn instantiate( + &self, + remote_signature: [u8; 16], + own_signature: [u8; 16], + _: &[u8], + substream_count: u8, + ) -> (Vec, Self::CryptoConnectionInstance); + + fn sign_pre_handshake(&self, packet: &mut PRUDPPacket); +} + +impl Deref for ExternalConnection{ + type Target = SendingConnection; + fn deref(&self) -> &Self::Target { + &self.sending + } +} + +impl Deref for SendingConnection{ + type Target = CommonConnection; + fn deref(&self) -> &Self::Target { + &self.common + } +} + +impl ExternalConnection{ + pub async fn recv(&mut self) -> Option>{ + self.data_receiver.recv().await + } + //todo: make this an actual result instead of an option + + pub fn duplicate_sender(&self) -> SendingConnection{ + self.sending.clone() + } +} + +impl SendingConnection{ + pub async fn send(&self, data: Vec) -> Option<()> { + let internal = self.inernal.upgrade()?; + + let mut internal = internal.lock().await; + + internal.send_data_packet(data).await; + Some(()) + } +} + +pub struct Unsecure(pub &'static str); + +pub struct UnsecureInstance { + key: &'static str, + streams: Vec>>, + self_signature: [u8; 16], + remote_signature: [u8; 16], +} + +// my hand was forced to use lazy so that we can guarantee this code +// only runs once and so that i can put it here as a "constant" (for performance and readability) +// since for some reason rust crypto doesn't have any const time key initialization +static DEFAULT_KEY: Lazy> = Lazy::new(|| Key::from(*b"CD&ML")); + +impl CryptoHandler for Unsecure { + type CryptoConnectionInstance = UnsecureInstance; + + fn instantiate( + &self, + remote_signature: [u8; 16], + self_signature: [u8; 16], + _: &[u8], + substream_count: u8, + ) -> (Vec, Self::CryptoConnectionInstance) { + ( + Vec::new(), + UnsecureInstance { + streams: (0..substream_count) + .map(|_| EncryptionPair::init_both(|| Rc4::new(&DEFAULT_KEY))) + .collect(), + key: self.0, + remote_signature, + self_signature, + }, + ) + } + + fn sign_pre_handshake(&self, packet: &mut PRUDPPacket) { + packet.set_sizes(); + packet.calculate_and_assign_signature(self.0, None, None); + } +} + +impl CryptoHandlerConnectionInstance for UnsecureInstance { + type Encryption = Rc4; + + fn decrypt_incoming(&mut self, substream: u8, data: &mut [u8]) { + if let Some(crypt_pair) = self.streams.get_mut(substream as usize){ + crypt_pair.recv.apply_keystream(data); + } + } + + fn encrypt_outgoing(&mut self, substream: u8, data: &mut [u8]) { + if let Some(crypt_pair) = self.streams.get_mut(substream as usize){ + crypt_pair.send.apply_keystream(data); + } + } + + fn get_user_id(&self) -> u32 { + 0 + } + + fn sign_connect(&self, packet: &mut PRUDPPacket) { + packet.set_sizes(); + packet.calculate_and_assign_signature(self.key, None, Some(self.self_signature)); + } + + fn sign_packet(&self, packet: &mut PRUDPPacket) { + packet.set_sizes(); + packet.calculate_and_assign_signature(self.key, None, Some(self.self_signature)); + } + + fn verify_packet(&self, packet: &PRUDPPacket) -> bool { + true + } +} diff --git a/src/rmc/mod.rs b/src/rmc/mod.rs index bf1eb0c..23458f6 100644 --- a/src/rmc/mod.rs +++ b/src/rmc/mod.rs @@ -1,6 +1,7 @@ pub mod message; pub mod structures; pub mod response; +pub mod protocols; diff --git a/src/rmc/protocols/mod.rs b/src/rmc/protocols/mod.rs new file mode 100644 index 0000000..2762de2 --- /dev/null +++ b/src/rmc/protocols/mod.rs @@ -0,0 +1,17 @@ +use std::sync::Arc; +use async_trait::async_trait; +use tokio::sync::Mutex; +use crate::prudp::socket::ExternalConnection; +use crate::rmc::structures::connection_data::ConnectionData; + +pub trait RmcCallable{ + fn rmc_call(protocol_id: u8, method_id: u8, rest: Vec); +} + +struct LocalRmcObjectWrapper(T); +impl LocalRmcObjectWrapper{ + pub fn new(object: T, conn: ExternalConnection) -> Self{ + unimplemented!() + } +} + diff --git a/src/rmc/response.rs b/src/rmc/response.rs index ca02318..bbbfb13 100644 --- a/src/rmc/response.rs +++ b/src/rmc/response.rs @@ -6,8 +6,10 @@ use crate::prudp::packet::{PRUDPPacket}; use crate::prudp::packet::flags::{NEED_ACK, RELIABLE}; use crate::prudp::packet::PacketOption::FragmentId; use crate::prudp::packet::types::DATA; -use crate::prudp::socket::{ConnectionData, SocketData}; +use crate::prudp::socket::ExternalConnection; use crate::rmc::structures::qresult::ERROR_MASK; +use crate::web::DirectionalData::{Incoming, Outgoing}; +use crate::web::WEB_DATA; pub enum RMCResponseResult { Success{ @@ -76,33 +78,8 @@ pub fn generate_response(protocol_id: u8, response: RMCResponseResult) -> io::Re Ok(data_out) } -pub async fn send_response(original_packet: &PRUDPPacket, socket: &SocketData, connection: &mut ConnectionData, rmcresponse: RMCResponse){ - - let ConnectionData{ - active_connection_data, - .. - } = connection; - - let Some(active_connection) = active_connection_data else { - return; - }; - - let mut packet = original_packet.base_response_packet(); - - - packet.header.types_and_flags.set_types(DATA); - packet.header.types_and_flags.set_flag((original_packet.header.types_and_flags.get_flags() & RELIABLE) | NEED_ACK); - - //packet.header.session_id = active_connection.server_session_id; - packet.header.substream_id = 0; - - packet.options.push(FragmentId(0)); - - packet.payload = rmcresponse.to_data(); - - //tokio::time::sleep(Duration::from_millis(500)).await; - - connection.finish_and_send_packet_to(socket, packet).await; +pub async fn send_response(original_packet: &PRUDPPacket, connection: &mut ExternalConnection, rmcresponse: RMCResponse){ + connection.send(rmcresponse.to_data()).await; } //taken from kinnays error list directly diff --git a/src/rmc/structures/mod.rs b/src/rmc/structures/mod.rs index fc4e9d9..667af6e 100644 --- a/src/rmc/structures/mod.rs +++ b/src/rmc/structures/mod.rs @@ -30,6 +30,7 @@ pub mod qbuffer; pub mod primitives; pub mod matchmake; pub mod variant; +mod ranking; pub trait RmcSerialize: Sized{ fn serialize(&self, writer: &mut dyn Write) -> Result<()>; diff --git a/src/rmc/structures/qbuffer.rs b/src/rmc/structures/qbuffer.rs index 09fc8e3..f87c49e 100644 --- a/src/rmc/structures/qbuffer.rs +++ b/src/rmc/structures/qbuffer.rs @@ -1,12 +1,30 @@ -use std::io::Read; +use std::io::{Read, Write}; +use bytemuck::bytes_of; use crate::endianness::{IS_BIG_ENDIAN, ReadExtensions}; -use crate::rmc::structures::Result; -pub fn read(reader: &mut impl Read) -> Result>{ - let size: u16 = reader.read_struct(IS_BIG_ENDIAN)?; +use crate::rmc::structures::{Result, RmcSerialize}; +use crate::rmc::structures::qresult::QResult; - let mut vec = vec![0; size as usize]; - reader.read_exact(&mut vec)?; +#[derive(Debug)] +pub struct QBuffer(pub Vec); - Ok(vec) +impl RmcSerialize for QBuffer{ + fn serialize(&self, writer: &mut dyn Write) -> Result<()> { + let len_u16 = self.0.len() as u16; + + writer.write(bytes_of(&len_u16))?; + writer.write(&self.0)?; + + Ok(()) + } + + fn deserialize(mut reader: &mut dyn Read) -> Result { + let size: u16 = reader.read_struct(IS_BIG_ENDIAN)?; + + let mut vec = vec![0; size as usize]; + + reader.read_exact(&mut vec)?; + + Ok(Self(vec)) + } } \ No newline at end of file diff --git a/src/rmc/structures/ranking.rs b/src/rmc/structures/ranking.rs new file mode 100644 index 0000000..c912d3f --- /dev/null +++ b/src/rmc/structures/ranking.rs @@ -0,0 +1,69 @@ +use bytemuck::{Pod, Zeroable}; +use macros::RmcSerialize; +use crate::rmc::structures::qbuffer::QBuffer; + +#[derive(RmcSerialize, Debug)] +#[rmc_struct(0)] +struct UploadCompetitionData{ + winning_team/*?*/: u32, + splatfest_id/*?*/: u32, + unk_2/*?*/: u32, + unk_3: u32, + team_id_1: u8, + team_id_2: u8, + unk_5: u32, + player_data/*?*/: QBuffer, +} + +#[derive(Copy, Clone, Pod, Zeroable)] +#[repr(C)] +struct UserData{ + name: [u16; 0x10], +} + +#[cfg(test)] +mod test{ + use std::io::Cursor; + use bytemuck::from_bytes; + use tokio::io::AsyncReadExt; + use crate::rmc::structures::ranking::{UploadCompetitionData, UserData}; + use crate::rmc::structures::RmcSerialize; + + #[test] + fn test() { + 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::()]); + + 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()) + } +} \ No newline at end of file diff --git a/src/rmc/structures/string.rs b/src/rmc/structures/string.rs index 712da2c..690e6a1 100644 --- a/src/rmc/structures/string.rs +++ b/src/rmc/structures/string.rs @@ -35,4 +35,5 @@ impl RmcSerialize for &str{ Ok(()) } -} \ No newline at end of file +} + diff --git a/src/web/mod.rs b/src/web/mod.rs new file mode 100644 index 0000000..3461257 --- /dev/null +++ b/src/web/mod.rs @@ -0,0 +1,37 @@ +use std::net::SocketAddrV4; +use once_cell::sync::Lazy; +use rocket::{get, routes, Rocket}; +use rocket::serde::json::Json; +use tokio::task::JoinHandle; +use serde::Serialize; +use tokio::sync::Mutex; + +#[get("/")] +async fn server_data() -> Json { + Json(WEB_DATA.lock().await.clone()) +} + +pub async fn start_web() -> JoinHandle<()>{ + tokio::spawn(async{ + rocket::build() + .mount("/",routes![server_data]) + .launch().await + .expect("unable to start webserver"); + }) +} +#[derive(Serialize, Clone)] +pub enum DirectionalData{ + Incoming(String), + Outgoing(String) +} + +#[derive(Serialize, Default, Clone)] +pub struct WebData{ + pub data: Vec<(SocketAddrV4, DirectionalData)> +} + +pub static WEB_DATA: Lazy> = Lazy::new(|| Mutex::new( + WebData{ + data: Vec::new(), + } +)); \ No newline at end of file