diff --git a/.ci-scripts/make-edition.sh b/.ci-scripts/make-edition.sh index 2b4bb91..f595e5e 100755 --- a/.ci-scripts/make-edition.sh +++ b/.ci-scripts/make-edition.sh @@ -1,15 +1,17 @@ #!/usr/bin/env bash -export EDITION=$1 -source /etc/environment -: "${RNEX_CONTAINER_PLATFORM:=podman}" -for TARGET in node-holder proxy-secure proxy-insecure backend-auth backend-secure; do - $RNEX_CONTAINER_PLATFORM build \ - --network=host \ - --build-arg EDITION="$EDITION" \ - --build-arg DATABASE_URL="$DATABASE_URL" \ - -t "$CI_REGISTRY_IMAGE/$EDITION/$TARGET:$CI_COMMIT_SHORT_SHA" \ - --target="$TARGET" . - - $RNEX_CONTAINER_PLATFORM push "$CI_REGISTRY_IMAGE/$EDITION/$TARGET:$CI_COMMIT_SHORT_SHA" -done \ No newline at end of file +export EDITION=$1 +export BA="--build-arg EDITION=$1" + +podman build $BA -t "$CI_REGISTRY_IMAGE/$EDITION/dev-container:latest" --target=dev-container . +podman push "$CI_REGISTRY_IMAGE/$EDITION/dev-container:latest" +podman build $BA -t "$CI_REGISTRY_IMAGE/$EDITION/node-holder:$CI_COMMIT_SHORT_SHA" --target=node-holder . +podman build $BA -t "$CI_REGISTRY_IMAGE/$EDITION/proxy-secure:$CI_COMMIT_SHORT_SHA" --target=proxy-secure . +podman build $BA -t "$CI_REGISTRY_IMAGE/$EDITION/proxy-insecure:$CI_COMMIT_SHORT_SHA" --target=proxy-insecure . +podman build $BA -t "$CI_REGISTRY_IMAGE/$EDITION/backend-auth:$CI_COMMIT_SHORT_SHA" --target=backend-auth . +podman build $BA -t "$CI_REGISTRY_IMAGE/$EDITION/backend-secure:$CI_COMMIT_SHORT_SHA" --target=backend-secure . +podman push "$CI_REGISTRY_IMAGE/$EDITION/node-holder:$CI_COMMIT_SHORT_SHA" +podman push "$CI_REGISTRY_IMAGE/$EDITION/proxy-secure:$CI_COMMIT_SHORT_SHA" +podman push "$CI_REGISTRY_IMAGE/$EDITION/proxy-insecure:$CI_COMMIT_SHORT_SHA" +podman push "$CI_REGISTRY_IMAGE/$EDITION/backend-auth:$CI_COMMIT_SHORT_SHA" +podman push "$CI_REGISTRY_IMAGE/$EDITION/backend-secure:$CI_COMMIT_SHORT_SHA" diff --git a/.dockerignore b/.dockerignore index ab0f8c4..4e09ffe 100644 --- a/.dockerignore +++ b/.dockerignore @@ -7,6 +7,4 @@ CONTRIBUTING.md README.md .gitignore LICENSE -.devcontainer.json -.ci-scripts/make-edition.sh -.forgejo/workflows/build.yml \ No newline at end of file +.devcontainer.json \ No newline at end of file diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml deleted file mode 100644 index 35e5879..0000000 --- a/.forgejo/workflows/build.yml +++ /dev/null @@ -1,314 +0,0 @@ -name: Build and Test - -on: - push: - branches: ["**"] - pull_request: - -env: - DOCKER_TLS_CERTDIR: /certs - IMAGE_TAG: ${{ github.sha }} - SHORT_SHA: ${{ github.sha }} - -jobs: - mario-tennis: - runs-on: debian-trixie - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Cache container storage - uses: actions/cache@v4 - with: - path: | - /var/lib/containers/storage - /run/containers/storage - ~/.local/share/containers/storage - key: image-cache - - - name: Login to registry - run: docker login -u ${{ secrets.PACKAGE_USER }} -p ${{ secrets.PACKAGE_PWD }} git.spbr.net - - - name: Set short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::6}" >> $GITHUB_ENV - - - name: Build MTUS tetris edition - env: - CI_REGISTRY_IMAGE: git.spbr.net/spacebar/rust-nex - CI_COMMIT_SHORT_SHA: ${{ env.SHORT_SHA }} - run: ./.ci-scripts/make-edition.sh mario-tennis - - wii-sports-club: - runs-on: debian-trixie - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Cache container storage - uses: actions/cache@v4 - with: - path: | - /var/lib/containers/storage - /run/containers/storage - ~/.local/share/containers/storage - key: image-cache - - - name: Login to registry - run: docker login -u ${{ secrets.PACKAGE_USER }} -p ${{ secrets.PACKAGE_PWD }} git.spbr.net - - - name: Set short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::6}" >> $GITHUB_ENV - - - name: Build Wii Sports Club edition - env: - CI_REGISTRY_IMAGE: git.spbr.net/spacebar/rust-nex - CI_COMMIT_SHORT_SHA: ${{ env.SHORT_SHA }} - run: ./.ci-scripts/make-edition.sh wii-sports-club - - puyopuyo: - runs-on: debian-trixie - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Cache container storage - uses: actions/cache@v4 - with: - path: | - /var/lib/containers/storage - /run/containers/storage - ~/.local/share/containers/storage - key: image-cache - - - name: Login to registry - run: docker login -u ${{ secrets.PACKAGE_USER }} -p ${{ secrets.PACKAGE_PWD }} git.spbr.net - - - name: Set short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::6}" >> $GITHUB_ENV - - - name: Build puyo puyo tetris edition - env: - CI_REGISTRY_IMAGE: git.spbr.net/spacebar/rust-nex - CI_COMMIT_SHORT_SHA: ${{ env.SHORT_SHA }} - run: ./.ci-scripts/make-edition.sh puyopuyo - - minecraft-wiiu: - runs-on: debian-trixie - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Cache container storage - uses: actions/cache@v4 - with: - path: | - /var/lib/containers/storage - /run/containers/storage - ~/.local/share/containers/storage - key: image-cache - - - name: Login to registry - run: docker login -u ${{ secrets.PACKAGE_USER }} -p ${{ secrets.PACKAGE_PWD }} git.spbr.net - - - name: Set short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::6}" >> $GITHUB_ENV - - - name: Build Minecraft Wii U edition - env: - CI_REGISTRY_IMAGE: git.spbr.net/spacebar/rust-nex - CI_COMMIT_SHORT_SHA: ${{ env.SHORT_SHA }} - run: ./.ci-scripts/make-edition.sh minecraft-wiiu - - splatoon-testfire: - runs-on: debian-trixie - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Cache container storage - uses: actions/cache@v4 - with: - path: | - /var/lib/containers/storage - /run/containers/storage - ~/.local/share/containers/storage - key: image-cache - - - name: Login to registry - run: docker login -u ${{ secrets.PACKAGE_USER }} -p ${{ secrets.PACKAGE_PWD }} git.spbr.net - - - name: Set short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::6}" >> $GITHUB_ENV - - - name: Build Splatoon Testfire edition - env: - CI_REGISTRY_IMAGE: git.spbr.net/spacebar/rust-nex - CI_COMMIT_SHORT_SHA: ${{ env.SHORT_SHA }} - run: ./.ci-scripts/make-edition.sh splatoon-testfire - - fast-racing-neo: - runs-on: debian-trixie - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Cache container storage - uses: actions/cache@v4 - with: - path: | - /var/lib/containers/storage - /run/containers/storage - ~/.local/share/containers/storage - key: image-cache - - - name: Login to registry - run: docker login -u ${{ secrets.PACKAGE_USER }} -p ${{ secrets.PACKAGE_PWD }} git.spbr.net - - - name: Set short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::6}" >> $GITHUB_ENV - - - name: Build Fast Racing NEO edition - env: - CI_REGISTRY_IMAGE: git.spbr.net/spacebar/rust-nex - CI_COMMIT_SHORT_SHA: ${{ env.SHORT_SHA }} - run: ./.ci-scripts/make-edition.sh fast-racing-neo - - wii-u-chat: - runs-on: debian-trixie - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Cache container storage - uses: actions/cache@v4 - with: - path: | - /var/lib/containers/storage - /run/containers/storage - ~/.local/share/containers/storage - key: image-cache - - - name: Login to registry - run: docker login -u ${{ secrets.PACKAGE_USER }} -p ${{ secrets.PACKAGE_PWD }} git.spbr.net - - - name: Set short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::6}" >> $GITHUB_ENV - - - name: Build Wii U Chat edition - env: - CI_REGISTRY_IMAGE: git.spbr.net/spacebar/rust-nex - CI_COMMIT_SHORT_SHA: ${{ env.SHORT_SHA }} - run: ./.ci-scripts/make-edition.sh wii-u-chat - - splatoon: - runs-on: debian-trixie - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Cache container storage - uses: actions/cache@v4 - with: - path: | - /var/lib/containers/storage - /run/containers/storage - ~/.local/share/containers/storage - key: image-cache - - - name: Login to registry - run: docker login -u ${{ secrets.PACKAGE_USER }} -p ${{ secrets.PACKAGE_PWD }} git.spbr.net - - - name: Set short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::6}" >> $GITHUB_ENV - - - name: Build Splatoon edition - env: - CI_REGISTRY_IMAGE: git.spbr.net/spacebar/rust-nex - CI_COMMIT_SHORT_SHA: ${{ env.SHORT_SHA }} - run: ./.ci-scripts/make-edition.sh splatoon - - friends: - runs-on: debian-trixie - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Cache container storage - uses: actions/cache@v4 - with: - path: | - /var/lib/containers/storage - /run/containers/storage - ~/.local/share/containers/storage - key: image-cache - - - name: Set short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::6}" >> $GITHUB_ENV - - - name: Login to registry - run: podman login -u ${{ secrets.PACKAGE_USER }} -p ${{ secrets.PACKAGE_PWD }} git.spbr.net - - - name: Build Friends edition - env: - CI_REGISTRY_IMAGE: git.spbr.net/spacebar/rust-nex - CI_COMMIT_SHORT_SHA: ${{ env.SHORT_SHA }} - DATABASE_URL: ${{ secrets.DATABASE_FRIENDS }} - run: ./.ci-scripts/make-edition.sh friends - - super-mario-maker: - runs-on: debian-trixie - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Cache container storage - uses: actions/cache@v4 - with: - path: | - /var/lib/containers/storage - /run/containers/storage - ~/.local/share/containers/storage - key: image-cache - - - name: Set short SHA - run: echo "SHORT_SHA=${GITHUB_SHA::6}" >> $GITHUB_ENV - - - name: Login to registry - run: podman login -u ${{ secrets.PACKAGE_USER }} -p ${{ secrets.PACKAGE_PWD }} git.spbr.net - - - name: Build Super Mario Maker edition - env: - CI_REGISTRY_IMAGE: git.spbr.net/spacebar/rust-nex - CI_COMMIT_SHORT_SHA: ${{ env.SHORT_SHA }} - DATABASE_URL: ${{ secrets.DATABASE_SMM }} - run: ./.ci-scripts/make-edition.sh super-mario-maker diff --git a/.gitignore b/.gitignore index 2a7a556..ea0ae4a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,4 @@ target .idea .env log -reports -.zed +reports \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7b9a013..fad0b25 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,11 +1,5 @@ default: image: quay.io/podman/stable - cache: - key: image-cache - paths: - - /var/lib/containers/storage - - /run/containers/storage - - .local/share/containers/storage before_script: - git submodule update --init - podman login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY @@ -24,7 +18,3 @@ splatoon: friends: stage: build_and_test script: ./.ci-scripts/make-edition.sh friends - -super-mario-maker: - stage: build_and_test - script: ./.ci-scripts/make-edition.sh super-mario-maker diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 908e9e4..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "rust-analyzer.cargo.features": [ - "friends" - ] -} \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 186e31d..fe55a2d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + [[package]] name = "adler2" version = "2.0.1" @@ -9,10 +18,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] -name = "allocator-api2" -version = "0.2.21" +name = "android-tzdata" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" [[package]] name = "android_system_properties" @@ -25,36 +34,21 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.102" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "async-trait" -version = "0.1.89" +version = "0.1.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.104", ] -[[package]] -name = "atoi" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" -dependencies = [ - "num-traits", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - [[package]] name = "autocfg" version = "1.5.0" @@ -62,495 +56,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] -name = "aws-config" -version = "1.8.16" +name = "backtrace" +version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f156acdd2cf55f5aa53ee416c4ac851cf1222694506c0b1f78c85695e9ca9d" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-sdk-sso", - "aws-sdk-ssooidc", - "aws-sdk-sts", - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-json", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-types", - "bytes", - "fastrand", - "hex", - "http 1.4.0", - "sha1 0.10.6", - "time", - "tokio", - "tracing", - "url", - "zeroize", + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", ] -[[package]] -name = "aws-credential-types" -version = "1.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f20799b373a1be121fe3005fba0c2090af9411573878f224df44b42727fcaf7" -dependencies = [ - "aws-smithy-async", - "aws-smithy-runtime-api", - "aws-smithy-types", - "zeroize", -] - -[[package]] -name = "aws-lc-rs" -version = "1.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec6fb3fe69024a75fa7e1bfb48aa6cf59706a101658ea01bfd33b2b248a038f" -dependencies = [ - "aws-lc-sys", - "zeroize", -] - -[[package]] -name = "aws-lc-sys" -version = "0.40.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f50037ee5e1e41e7b8f9d161680a725bd1626cb6f8c7e901f91f942850852fe7" -dependencies = [ - "cc", - "cmake", - "dunce", - "fs_extra", -] - -[[package]] -name = "aws-runtime" -version = "1.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dcd93c82209ac7413532388067dce79be5a8780c1786e5fae3df22e4dee2864" -dependencies = [ - "aws-credential-types", - "aws-sigv4", - "aws-smithy-async", - "aws-smithy-eventstream", - "aws-smithy-http", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-types", - "bytes", - "bytes-utils", - "fastrand", - "http 0.2.12", - "http 1.4.0", - "http-body 0.4.6", - "http-body 1.0.1", - "percent-encoding", - "pin-project-lite", - "tracing", - "uuid", -] - -[[package]] -name = "aws-sdk-s3" -version = "1.131.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe1b8c5282bf859170836045296b3cd710b7573aceb909498366bb508a41058e" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-sigv4", - "aws-smithy-async", - "aws-smithy-checksums", - "aws-smithy-eventstream", - "aws-smithy-http", - "aws-smithy-json", - "aws-smithy-observability", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-smithy-xml", - "aws-types", - "bytes", - "fastrand", - "hex", - "hmac 0.13.0", - "http 0.2.12", - "http 1.4.0", - "http-body 1.0.1", - "lru", - "percent-encoding", - "regex-lite", - "sha2 0.11.0", - "tracing", - "url", -] - -[[package]] -name = "aws-sdk-sso" -version = "1.98.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d69c77aafa20460c68b6b3213c84f6423b6e76dbf89accd3e1789a686ffd9489" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-json", - "aws-smithy-observability", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-types", - "bytes", - "fastrand", - "http 0.2.12", - "http 1.4.0", - "regex-lite", - "tracing", -] - -[[package]] -name = "aws-sdk-ssooidc" -version = "1.100.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c7e7b09346d5ca22a2a08267555843a6a0127fb20d8964cb6ecfb8fdb190225" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-json", - "aws-smithy-observability", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-types", - "bytes", - "fastrand", - "http 0.2.12", - "http 1.4.0", - "regex-lite", - "tracing", -] - -[[package]] -name = "aws-sdk-sts" -version = "1.103.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2249b81a2e73a8027c41c378463a81ec39b8510f184f2caab87de912af0f49b" -dependencies = [ - "aws-credential-types", - "aws-runtime", - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-json", - "aws-smithy-observability", - "aws-smithy-query", - "aws-smithy-runtime", - "aws-smithy-runtime-api", - "aws-smithy-types", - "aws-smithy-xml", - "aws-types", - "fastrand", - "http 0.2.12", - "http 1.4.0", - "regex-lite", - "tracing", -] - -[[package]] -name = "aws-sigv4" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68dc0b907359b120170613b5c09ccc61304eac3998ff6274b97d93ee6490115a" -dependencies = [ - "aws-credential-types", - "aws-smithy-eventstream", - "aws-smithy-http", - "aws-smithy-runtime-api", - "aws-smithy-types", - "bytes", - "crypto-bigint 0.5.5", - "form_urlencoded", - "hex", - "hmac 0.13.0", - "http 0.2.12", - "http 1.4.0", - "p256", - "percent-encoding", - "ring", - "sha2 0.11.0", - "subtle", - "time", - "tracing", - "zeroize", -] - -[[package]] -name = "aws-smithy-async" -version = "1.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffcaf626bdda484571968400c326a244598634dc75fd451325a54ad1a59acfc" -dependencies = [ - "futures-util", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "aws-smithy-checksums" -version = "0.64.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10efbbcec1e044b81600e2fc562a391951d291152d95b482d5b7e7132299d762" -dependencies = [ - "aws-smithy-http", - "aws-smithy-types", - "bytes", - "crc-fast", - "hex", - "http 1.4.0", - "http-body 1.0.1", - "http-body-util", - "md-5 0.11.0", - "pin-project-lite", - "sha1 0.11.0", - "sha2 0.11.0", - "tracing", -] - -[[package]] -name = "aws-smithy-eventstream" -version = "0.60.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faf09d74e5e32f76b8762da505a3cd59303e367a664ca67295387baa8c1d7548" -dependencies = [ - "aws-smithy-types", - "bytes", - "crc32fast", -] - -[[package]] -name = "aws-smithy-http" -version = "0.63.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1ab2dc1c2c3749ead27180d333c42f11be8b0e934058fb4b2258ee8dbe5231" -dependencies = [ - "aws-smithy-eventstream", - "aws-smithy-runtime-api", - "aws-smithy-types", - "bytes", - "bytes-utils", - "futures-core", - "futures-util", - "http 1.4.0", - "http-body 1.0.1", - "http-body-util", - "percent-encoding", - "pin-project-lite", - "pin-utils", - "tracing", -] - -[[package]] -name = "aws-smithy-http-client" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a2f165a7feee6f263028b899d0a181987f4fa7179a6411a32a439fba7c5f769" -dependencies = [ - "aws-smithy-async", - "aws-smithy-runtime-api", - "aws-smithy-types", - "h2 0.3.27", - "h2 0.4.13", - "http 0.2.12", - "http 1.4.0", - "http-body 0.4.6", - "hyper 0.14.32", - "hyper 1.9.0", - "hyper-rustls 0.24.2", - "hyper-rustls 0.27.9", - "hyper-util", - "pin-project-lite", - "rustls 0.21.12", - "rustls 0.23.40", - "rustls-native-certs", - "rustls-pki-types", - "tokio", - "tokio-rustls 0.26.4", - "tower", - "tracing", -] - -[[package]] -name = "aws-smithy-json" -version = "0.62.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9648b0bb82a2eedd844052c6ad2a1a822d1f8e3adee5fbf668366717e428856a" -dependencies = [ - "aws-smithy-types", -] - -[[package]] -name = "aws-smithy-observability" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06c2315d173edbf1920da8ba3a7189695827002e4c0fc961973ab1c54abca9c" -dependencies = [ - "aws-smithy-runtime-api", -] - -[[package]] -name = "aws-smithy-query" -version = "0.60.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a56d79744fb3edb5d722ef79d86081e121d3b9422cb209eb03aea6aa4f21ebd" -dependencies = [ - "aws-smithy-types", - "urlencoding", -] - -[[package]] -name = "aws-smithy-runtime" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0504b1ab12debb5959e5165ee5fe97dd387e7aa7ea6a477bfd7635dfe769a4f5" -dependencies = [ - "aws-smithy-async", - "aws-smithy-http", - "aws-smithy-http-client", - "aws-smithy-observability", - "aws-smithy-runtime-api", - "aws-smithy-types", - "bytes", - "fastrand", - "http 0.2.12", - "http 1.4.0", - "http-body 0.4.6", - "http-body 1.0.1", - "http-body-util", - "pin-project-lite", - "pin-utils", - "tokio", - "tracing", -] - -[[package]] -name = "aws-smithy-runtime-api" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71a13df6ada0aafbf21a73bdfcdf9324cfa9df77d96b8446045be3cde61b42e" -dependencies = [ - "aws-smithy-async", - "aws-smithy-runtime-api-macros", - "aws-smithy-types", - "bytes", - "http 0.2.12", - "http 1.4.0", - "pin-project-lite", - "tokio", - "tracing", - "zeroize", -] - -[[package]] -name = "aws-smithy-runtime-api-macros" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d7396fd9500589e62e460e987ecb671bad374934e55ec3b5f498cc7a8a8a7b7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "aws-smithy-types" -version = "1.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d73dbfbaa8e4bc57b9045137680b958d274823509a360abfd8e1d514d40c95c" -dependencies = [ - "base64-simd", - "bytes", - "bytes-utils", - "futures-core", - "http 0.2.12", - "http 1.4.0", - "http-body 0.4.6", - "http-body 1.0.1", - "http-body-util", - "itoa", - "num-integer", - "pin-project-lite", - "pin-utils", - "ryu", - "serde", - "time", - "tokio", - "tokio-util", -] - -[[package]] -name = "aws-smithy-xml" -version = "0.60.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce02add1aa3677d022f8adf81dcbe3046a95f17a1b1e8979c145cd21d3d22b3" -dependencies = [ - "xmlparser", -] - -[[package]] -name = "aws-types" -version = "1.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4bbcaa9304ea40902d3d5f42a0428d1bd895a2b0f6999436fb279ffddc58ac" -dependencies = [ - "aws-credential-types", - "aws-smithy-async", - "aws-smithy-runtime-api", - "aws-smithy-types", - "rustc_version", - "tracing", -] - -[[package]] -name = "base16ct" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" - [[package]] name = "base64" version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "base64-simd" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" -dependencies = [ - "outref", - "vsimd", -] - -[[package]] -name = "base64ct" -version = "1.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" - [[package]] name = "bitflags" -version = "2.11.1" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" -dependencies = [ - "serde_core", -] +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "block-buffer" @@ -561,87 +91,60 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block-buffer" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" -dependencies = [ - "hybrid-array", -] - [[package]] name = "bumpalo" -version = "3.20.2" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytemuck" -version = "1.25.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" +checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.10.2" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +checksum = "441473f2b4b0459a68628c744bc61d23e730fb00128b841d30fa4bb3972257e4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.104", ] -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - [[package]] name = "bytes" -version = "1.11.1" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" - -[[package]] -name = "bytes-utils" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dafe3a8757b027e2be6e4e5601ed563c55989fcf1546e933c66c8eb3a058d35" -dependencies = [ - "bytes", - "either", -] +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.2.61" +version = "1.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" +checksum = "c3a42d84bb6b69d3a8b3eaacf0d88f179e1929695e1ad012b6cf64d9caaa5fd2" dependencies = [ - "find-msvc-tools", - "jobserver", - "libc", "shlex", ] [[package]] name = "cfg-if" -version = "1.0.4" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "chrono" -version = "0.4.44" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" dependencies = [ + "android-tzdata", "iana-time-zone", "js-sys", "num-traits", @@ -655,136 +158,16 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "crypto-common 0.1.7", + "crypto-common", "inout", ] -[[package]] -name = "cmake" -version = "0.1.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" -dependencies = [ - "cc", -] - -[[package]] -name = "cmov" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f88a43d011fc4a6876cb7344703e297c71dda42494fee094d5f7c76bf13f746" - -[[package]] -name = "concurrent-queue" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - -[[package]] -name = "const-oid" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" - -[[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 = "cookie_store" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b2c103cf610ec6cae3da84a766285b42fd16aad564758459e6ecf128c75206" -dependencies = [ - "cookie", - "document-features", - "idna", - "indexmap", - "log", - "serde", - "serde_derive", - "serde_json", - "time", - "url", -] - -[[package]] -name = "core-foundation" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - -[[package]] -name = "cpufeatures" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" -dependencies = [ - "libc", -] - -[[package]] -name = "crc" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853" - -[[package]] -name = "crc-fast" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd92aca2c6001b1bf5ba0ff84ee74ec8501b52bbef0cac80bf25a6c1d87a83d" -dependencies = [ - "crc", - "digest 0.10.7", - "rustversion", - "spin 0.10.0", -] - [[package]] name = "crc32fast" version = "1.5.0" @@ -794,103 +177,21 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crossbeam-queue" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crypto-bigint" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-bigint" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "crypto-common" -version = "0.1.7" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", "typenum", ] -[[package]] -name = "crypto-common" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" -dependencies = [ - "hybrid-array", -] - -[[package]] -name = "ctutils" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" -dependencies = [ - "cmov", -] - -[[package]] -name = "data-encoding" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" - -[[package]] -name = "der" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" -dependencies = [ - "const-oid 0.9.6", - "zeroize", -] - -[[package]] -name = "der" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" -dependencies = [ - "const-oid 0.9.6", - "pem-rfc7468", - "zeroize", -] - [[package]] name = "deranged" -version = "0.5.8" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" dependencies = [ "powerfmt", ] @@ -901,316 +202,33 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.4", - "const-oid 0.9.6", - "crypto-common 0.1.7", + "block-buffer", + "crypto-common", "subtle", ] -[[package]] -name = "digest" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" -dependencies = [ - "block-buffer 0.12.0", - "const-oid 0.10.2", - "crypto-common 0.2.1", - "ctutils", -] - -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "document-features" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" -dependencies = [ - "litrs", -] - [[package]] name = "dotenv" version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" -[[package]] -name = "dotenvy" -version = "0.15.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" - -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - -[[package]] -name = "ecdsa" -version = "0.14.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" -dependencies = [ - "der 0.6.1", - "elliptic-curve", - "rfc6979", - "signature 1.6.4", -] - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" -dependencies = [ - "serde", -] - -[[package]] -name = "elliptic-curve" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" -dependencies = [ - "base16ct", - "crypto-bigint 0.4.9", - "der 0.6.1", - "digest 0.10.7", - "ff", - "generic-array", - "group", - "pkcs8 0.9.0", - "rand_core 0.6.4", - "sec1", - "subtle", - "zeroize", -] - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "errno" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" -dependencies = [ - "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "etcetera" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" -dependencies = [ - "cfg-if", - "home", - "windows-sys 0.48.0", -] - -[[package]] -name = "event-listener" -version = "5.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "fastrand" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" - -[[package]] -name = "ff" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "find-msvc-tools" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" - [[package]] name = "flate2" -version = "1.1.9" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", "miniz_oxide", ] -[[package]] -name = "flume" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" -dependencies = [ - "futures-core", - "futures-sink", - "spin 0.9.8", -] - [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - -[[package]] -name = "foldhash" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" - -[[package]] -name = "form_urlencoded" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - -[[package]] -name = "futures" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" - -[[package]] -name = "futures-executor" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-intrusive" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" -dependencies = [ - "futures-core", - "lock_api", - "parking_lot", -] - -[[package]] -name = "futures-io" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" - -[[package]] -name = "futures-macro" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "futures-sink" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" - -[[package]] -name = "futures-task" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" - -[[package]] -name = "futures-util" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "slab", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -1223,9 +241,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.17" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", @@ -1233,108 +251,10 @@ dependencies = [ ] [[package]] -name = "getrandom" -version = "0.3.4" +name = "gimli" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasip2", -] - -[[package]] -name = "group" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" -dependencies = [ - "ff", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "h2" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "h2" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http 1.4.0", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash 0.1.5", -] - -[[package]] -name = "hashbrown" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash 0.2.0", -] - -[[package]] -name = "hashbrown" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" - -[[package]] -name = "hashlink" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" -dependencies = [ - "hashbrown 0.15.5", -] - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "hex" @@ -1342,222 +262,37 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "hkdf" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" -dependencies = [ - "hmac 0.12.1", -] - [[package]] name = "hmac" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "hmac" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" -dependencies = [ - "digest 0.11.3", -] - -[[package]] -name = "home" -version = "0.5.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" -dependencies = [ - "windows-sys 0.61.2", + "digest", ] [[package]] name = "http" -version = "0.2.12" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ "bytes", "fnv", "itoa", ] -[[package]] -name = "http" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" -dependencies = [ - "bytes", - "itoa", -] - -[[package]] -name = "http-body" -version = "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http 1.4.0", -] - -[[package]] -name = "http-body-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" -dependencies = [ - "bytes", - "futures-core", - "http 1.4.0", - "http-body 1.0.1", - "pin-project-lite", -] - [[package]] name = "httparse" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hybrid-array" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d46837a0ed51fe95bd3b05de33cd64a1ee88fc797477ca48446872504507c5" -dependencies = [ - "typenum", -] - -[[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.27", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.5.10", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" -dependencies = [ - "atomic-waker", - "bytes", - "futures-channel", - "futures-core", - "h2 0.4.13", - "http 1.4.0", - "http-body 1.0.1", - "httparse", - "itoa", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" -dependencies = [ - "futures-util", - "http 0.2.12", - "hyper 0.14.32", - "log", - "rustls 0.21.12", - "tokio", - "tokio-rustls 0.24.1", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" -dependencies = [ - "http 1.4.0", - "hyper 1.9.0", - "hyper-util", - "rustls 0.23.40", - "rustls-native-certs", - "tokio", - "tokio-rustls 0.26.4", - "tower-service", -] - -[[package]] -name = "hyper-util" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" -dependencies = [ - "base64", - "bytes", - "futures-channel", - "futures-util", - "http 1.4.0", - "http-body 1.0.1", - "hyper 1.9.0", - "ipnet", - "libc", - "percent-encoding", - "pin-project-lite", - "socket2 0.6.3", - "tokio", - "tower-service", - "tracing", -] - [[package]] name = "iana-time-zone" -version = "0.1.65" +version = "0.1.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1577,119 +312,6 @@ dependencies = [ "cc", ] -[[package]] -name = "icu_collections" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" -dependencies = [ - "displaydoc", - "potential_utf", - "utf8_iter", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locale_core" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_normalizer" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" -dependencies = [ - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" - -[[package]] -name = "icu_properties" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" -dependencies = [ - "icu_collections", - "icu_locale_core", - "icu_properties_data", - "icu_provider", - "zerotrie", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" - -[[package]] -name = "icu_provider" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" -dependencies = [ - "displaydoc", - "icu_locale_core", - "writeable", - "yoke", - "zerofrom", - "zerotrie", - "zerovec", -] - -[[package]] -name = "idna" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - -[[package]] -name = "indexmap" -version = "2.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" -dependencies = [ - "equivalent", - "hashbrown 0.17.0", -] - [[package]] name = "inout" version = "0.1.4" @@ -1700,35 +322,28 @@ dependencies = [ ] [[package]] -name = "ipnet" -version = "2.12.0" +name = "io-uring" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" - -[[package]] -name = "itoa" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" - -[[package]] -name = "jobserver" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" dependencies = [ - "getrandom 0.3.4", + "bitflags", + "cfg-if", "libc", ] [[package]] -name = "js-sys" -version = "0.3.97" +name = "itoa" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1840c94c045fbcf8ba2812c95db44499f7c64910a912551aaaa541decebcacf" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ - "cfg-if", - "futures-util", "once_cell", "wasm-bindgen", ] @@ -1739,84 +354,27 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -dependencies = [ - "spin 0.9.8", -] - [[package]] name = "libc" -version = "0.2.186" +version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" - -[[package]] -name = "libm" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" - -[[package]] -name = "libredox" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" -dependencies = [ - "bitflags", - "libc", - "plain", - "redox_syscall 0.7.4", -] - -[[package]] -name = "libsqlite3-sys" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" -dependencies = [ - "pkg-config", - "vcpkg", -] - -[[package]] -name = "litemap" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" - -[[package]] -name = "litrs" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "lock_api" -version = "0.4.14" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ + "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.29" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" - -[[package]] -name = "lru" -version = "0.16.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39" -dependencies = [ - "hashbrown 0.16.1", -] +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "macros" @@ -1824,13 +382,13 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.104", ] [[package]] name = "macros" version = "0.1.1" -source = "git+https://github.com/RusticMaple/VByteMacros#e2f31bded8c5591e847ba03faf79ae0351e43e69" +source = "git+https://github.com/DJMrTV/VByteMacros#e2f31bded8c5591e847ba03faf79ae0351e43e69" dependencies = [ "proc-macro2", "quote", @@ -1844,24 +402,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ "cfg-if", - "digest 0.10.7", -] - -[[package]] -name = "md-5" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69b6441f590336821bb897fb28fc622898ccceb1d6cea3fde5ea86b090c4de98" -dependencies = [ - "cfg-if", - "digest 0.11.3", + "digest", ] [[package]] name = "memchr" -version = "2.8.0" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "miniz_oxide" @@ -1875,56 +423,20 @@ dependencies = [ [[package]] name = "mio" -version = "1.2.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", "wasi", - "windows-sys 0.61.2", -] - -[[package]] -name = "num-bigint-dig" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" -dependencies = [ - "lazy_static", - "libm", - "num-integer", - "num-iter", - "num-traits", - "rand 0.8.6", - "smallvec", - "zeroize", + "windows-sys 0.59.0", ] [[package]] name = "num-conv" -version = "0.2.1" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-traits" @@ -1933,7 +445,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", - "libm", ] [[package]] @@ -1946,45 +457,25 @@ dependencies = [ ] [[package]] -name = "once_cell" -version = "1.21.4" +name = "object" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" - -[[package]] -name = "openssl-probe" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" - -[[package]] -name = "outref" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" - -[[package]] -name = "p256" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ - "ecdsa", - "elliptic-curve", - "sha2 0.10.9", + "memchr", ] [[package]] -name = "parking" -version = "2.2.1" +name = "once_cell" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "parking_lot" -version = "0.12.5" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ "lock_api", "parking_lot_core", @@ -1992,15 +483,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.12" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.18", + "redox_syscall", "smallvec", - "windows-link", + "windows-targets", ] [[package]] @@ -2009,84 +500,17 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "pem-rfc7468" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" -dependencies = [ - "base64ct", -] - [[package]] name = "percent-encoding" -version = "2.3.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project-lite" -version = "0.2.17" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkcs1" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" -dependencies = [ - "der 0.7.10", - "pkcs8 0.10.2", - "spki 0.7.3", -] - -[[package]] -name = "pkcs8" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" -dependencies = [ - "der 0.6.1", - "spki 0.6.0", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der 0.7.10", - "spki 0.7.3", -] - -[[package]] -name = "pkg-config" -version = "0.3.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" - -[[package]] -name = "plain" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" - -[[package]] -name = "potential_utf" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" -dependencies = [ - "zerovec", -] +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "powerfmt" @@ -2105,80 +529,23 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.106" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] -[[package]] -name = "proxy" -version = "0.1.0" -dependencies = [ - "cfg-if", - "log", - "proxy-common", - "prudplite", - "prudpv0", - "prudpv1", - "rnex-core", - "tokio", -] - -[[package]] -name = "proxy-common" -version = "0.1.0" -dependencies = [ - "hex", - "log", - "rnex-core", - "thiserror", - "tokio", -] - -[[package]] -name = "prudplite" -version = "0.1.0" -dependencies = [ - "bytemuck", - "futures-util", - "log", - "proxy-common", - "rnex-core", - "tokio", - "tokio-tungstenite", - "v-byte-helpers", -] - -[[package]] -name = "prudpv0" -version = "0.1.0" -dependencies = [ - "bytemuck", - "cfg-if", - "hmac 0.12.1", - "log", - "md-5 0.10.6", - "proxy-common", - "rc4", - "rnex-core", - "tokio", - "typenum", -] - [[package]] name = "prudpv1" version = "0.1.0" dependencies = [ "async-trait", "bytemuck", - "cfg-if", - "hmac 0.12.1", + "hmac", "log", - "md-5 0.10.6", + "md-5", "once_cell", - "proxy-common", "rc4", "rnex-core", "thiserror", @@ -2189,38 +556,22 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.45" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - [[package]] name = "rand" -version = "0.8.6" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" -dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.5", + "rand_chacha", + "rand_core", ] [[package]] @@ -2230,17 +581,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core 0.9.5", + "rand_core", ] [[package]] @@ -2249,16 +590,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.17", -] - -[[package]] -name = "rand_core" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" -dependencies = [ - "getrandom 0.3.4", + "getrandom", ] [[package]] @@ -2272,39 +604,13 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.18" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ "bitflags", ] -[[package]] -name = "redox_syscall" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a" -dependencies = [ - "bitflags", -] - -[[package]] -name = "regex-lite" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973" - -[[package]] -name = "rfc6979" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" -dependencies = [ - "crypto-bigint 0.4.9", - "hmac 0.12.1", - "zeroize", -] - [[package]] name = "ring" version = "0.17.14" @@ -2313,7 +619,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.17", + "getrandom", "libc", "untrusted", "windows-sys 0.52.0", @@ -2324,132 +630,63 @@ name = "rnex-core" version = "0.1.1" dependencies = [ "anyhow", - "aws-config", - "aws-sdk-s3", - "base64", "bytemuck", - "cfg-if", "chrono", "dotenv", - "futures", "hex", - "hmac 0.12.1", + "hmac", "json", "log", "macros 0.0.0", - "md-5 0.10.6", + "md-5", "once_cell", "paste", - "rand 0.8.6", + "rand", "rc4", - "serde", - "serde_json", - "sha2 0.10.9", "simplelog", - "sqlx", "thiserror", "tokio", "typenum", "ureq", - "urlencoding", "v-byte-helpers", ] [[package]] -name = "rsa" -version = "0.9.10" +name = "rustc-demangle" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" -dependencies = [ - "const-oid 0.9.6", - "digest 0.10.7", - "num-bigint-dig", - "num-integer", - "num-traits", - "pkcs1", - "pkcs8 0.10.2", - "rand_core 0.6.4", - "signature 2.2.0", - "spki 0.7.3", - "subtle", - "zeroize", -] - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" [[package]] name = "rustls" -version = "0.21.12" +version = "0.23.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" dependencies = [ - "log", - "ring", - "rustls-webpki 0.101.7", - "sct", -] - -[[package]] -name = "rustls" -version = "0.23.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" -dependencies = [ - "aws-lc-rs", "log", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.103.13", + "rustls-webpki", "subtle", "zeroize", ] -[[package]] -name = "rustls-native-certs" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" -dependencies = [ - "openssl-probe", - "rustls-pki-types", - "schannel", - "security-framework", -] - [[package]] name = "rustls-pki-types" -version = "1.14.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" dependencies = [ "zeroize", ] [[package]] name = "rustls-webpki" -version = "0.101.7" +version = "0.103.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "rustls-webpki" -version = "0.103.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" -dependencies = [ - "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -2457,24 +694,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.22" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" - -[[package]] -name = "ryu" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" - -[[package]] -name = "schannel" -version = "0.1.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" -dependencies = [ - "windows-sys 0.61.2", -] +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "scopeguard" @@ -2482,156 +704,24 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "sec1" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" -dependencies = [ - "base16ct", - "der 0.6.1", - "generic-array", - "pkcs8 0.9.0", - "subtle", - "zeroize", -] - -[[package]] -name = "security-framework" -version = "3.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" - [[package]] name = "serde" -version = "1.0.228" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde_core" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.228" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", -] - -[[package]] -name = "serde_json" -version = "1.0.149" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" -dependencies = [ - "itoa", - "memchr", - "serde", - "serde_core", - "zmij", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "digest 0.10.7", -] - -[[package]] -name = "sha1" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214" -dependencies = [ - "cfg-if", - "cpufeatures 0.3.0", - "digest 0.11.3", -] - -[[package]] -name = "sha2" -version = "0.10.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" -dependencies = [ - "cfg-if", - "cpufeatures 0.3.0", - "digest 0.11.3", + "syn 2.0.104", ] [[package]] @@ -2642,39 +732,18 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.8" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" dependencies = [ - "errno", "libc", ] -[[package]] -name = "signature" -version = "1.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" -dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", -] - -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", -] - [[package]] name = "simd-adler32" -version = "0.3.9" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "simplelog" @@ -2689,285 +758,24 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.12" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" +checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" [[package]] name = "smallvec" version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" -dependencies = [ - "serde", -] [[package]] name = "socket2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "socket2" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" -dependencies = [ - "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "lock_api", -] - -[[package]] -name = "spin" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" - -[[package]] -name = "spki" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" dependencies = [ - "base64ct", - "der 0.6.1", -] - -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der 0.7.10", -] - -[[package]] -name = "sqlx" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc" -dependencies = [ - "sqlx-core", - "sqlx-macros", - "sqlx-mysql", - "sqlx-postgres", - "sqlx-sqlite", -] - -[[package]] -name = "sqlx-core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6" -dependencies = [ - "base64", - "bytes", - "chrono", - "crc", - "crossbeam-queue", - "either", - "event-listener", - "futures-core", - "futures-intrusive", - "futures-io", - "futures-util", - "hashbrown 0.15.5", - "hashlink", - "indexmap", - "log", - "memchr", - "once_cell", - "percent-encoding", - "serde", - "serde_json", - "sha2 0.10.9", - "smallvec", - "thiserror", - "time", - "tokio", - "tokio-stream", - "tracing", - "url", -] - -[[package]] -name = "sqlx-macros" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d" -dependencies = [ - "proc-macro2", - "quote", - "sqlx-core", - "sqlx-macros-core", - "syn 2.0.117", -] - -[[package]] -name = "sqlx-macros-core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19a9c1841124ac5a61741f96e1d9e2ec77424bf323962dd894bdb93f37d5219b" -dependencies = [ - "dotenvy", - "either", - "heck", - "hex", - "once_cell", - "proc-macro2", - "quote", - "serde", - "serde_json", - "sha2 0.10.9", - "sqlx-core", - "sqlx-mysql", - "sqlx-postgres", - "sqlx-sqlite", - "syn 2.0.117", - "tokio", - "url", -] - -[[package]] -name = "sqlx-mysql" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" -dependencies = [ - "atoi", - "base64", - "bitflags", - "byteorder", - "bytes", - "chrono", - "crc", - "digest 0.10.7", - "dotenvy", - "either", - "futures-channel", - "futures-core", - "futures-io", - "futures-util", - "generic-array", - "hex", - "hkdf", - "hmac 0.12.1", - "itoa", - "log", - "md-5 0.10.6", - "memchr", - "once_cell", - "percent-encoding", - "rand 0.8.6", - "rsa", - "serde", - "sha1 0.10.6", - "sha2 0.10.9", - "smallvec", - "sqlx-core", - "stringprep", - "thiserror", - "time", - "tracing", - "whoami", -] - -[[package]] -name = "sqlx-postgres" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" -dependencies = [ - "atoi", - "base64", - "bitflags", - "byteorder", - "chrono", - "crc", - "dotenvy", - "etcetera", - "futures-channel", - "futures-core", - "futures-util", - "hex", - "hkdf", - "hmac 0.12.1", - "home", - "itoa", - "log", - "md-5 0.10.6", - "memchr", - "once_cell", - "rand 0.8.6", - "serde", - "serde_json", - "sha2 0.10.9", - "smallvec", - "sqlx-core", - "stringprep", - "thiserror", - "time", - "tracing", - "whoami", -] - -[[package]] -name = "sqlx-sqlite" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea" -dependencies = [ - "atoi", - "chrono", - "flume", - "futures-channel", - "futures-core", - "futures-executor", - "futures-intrusive", - "futures-util", - "libsqlite3-sys", - "log", - "percent-encoding", - "serde", - "serde_urlencoded", - "sqlx-core", - "thiserror", - "time", - "tracing", - "url", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" - -[[package]] -name = "stringprep" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" -dependencies = [ - "unicode-bidi", - "unicode-normalization", - "unicode-properties", + "libc", + "windows-sys 0.59.0", ] [[package]] @@ -2989,26 +797,15 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.117" +version = "2.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "synstructure" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "termcolor" version = "1.4.1" @@ -3020,29 +817,29 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.18" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.18" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.104", ] [[package]] name = "time" -version = "0.3.47" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", "itoa", @@ -3050,251 +847,69 @@ dependencies = [ "num-conv", "num_threads", "powerfmt", - "serde_core", + "serde", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.8" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" +checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" [[package]] name = "time-macros" -version = "0.2.27" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" dependencies = [ "num-conv", "time-core", ] -[[package]] -name = "tinystr" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" -dependencies = [ - "displaydoc", - "zerovec", -] - -[[package]] -name = "tinyvec" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" -version = "1.52.1" +version = "1.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" +checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" dependencies = [ + "backtrace", "bytes", + "io-uring", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.6.3", + "slab", + "socket2", "tokio-macros", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] name = "tokio-macros" -version = "2.7.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", -] - -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls 0.21.12", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" -dependencies = [ - "rustls 0.23.40", - "tokio", -] - -[[package]] -name = "tokio-stream" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-tungstenite" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857" -dependencies = [ - "futures-util", - "log", - "rustls 0.23.40", - "rustls-native-certs", - "rustls-pki-types", - "tokio", - "tokio-rustls 0.26.4", - "tungstenite", -] - -[[package]] -name = "tokio-util" -version = "0.7.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tower" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" -dependencies = [ - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - -[[package]] -name = "tracing" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" -dependencies = [ - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "tracing-core" -version = "0.1.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" -dependencies = [ - "once_cell", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "tungstenite" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442" -dependencies = [ - "bytes", - "data-encoding", - "http 1.4.0", - "httparse", - "log", - "rand 0.9.4", - "rustls 0.23.40", - "rustls-pki-types", - "sha1 0.10.6", - "thiserror", - "utf-8", + "syn 2.0.104", ] [[package]] name = "typenum" -version = "1.20.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" - -[[package]] -name = "unicode-bidi" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "unicode-ident" -version = "1.0.24" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" - -[[package]] -name = "unicode-normalization" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-properties" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "untrusted" @@ -3304,157 +919,91 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "3.3.0" +version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea7109cdcd5864d4eeb1b58a1648dc9bf520360d7af16ec26d0a9354bafcfc0" +checksum = "d39cb1dbab692d82a977c0392ffac19e188bd9186a9f32806f0aaa859d75585a" dependencies = [ "base64", - "cookie_store", "flate2", "log", "percent-encoding", - "rustls 0.23.40", + "rustls", "rustls-pki-types", - "serde", - "serde_json", "ureq-proto", - "utf8-zero", + "utf-8", "webpki-roots", ] [[package]] name = "ureq-proto" -version = "0.6.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e994ba84b0bd1b1b0cf92878b7ef898a5c1760108fe7b6010327e274917a808c" +checksum = "60b4531c118335662134346048ddb0e54cc86bd7e81866757873055f0e38f5d2" dependencies = [ "base64", - "http 1.4.0", + "http", "httparse", "log", ] -[[package]] -name = "url" -version = "2.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - -[[package]] -name = "urlencoding" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" - [[package]] name = "utf-8" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[package]] -name = "utf8-zero" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8c0a043c9540bae7c578c88f91dda8bd82e59ae27c21baca69c8b191aaf5a6e" - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - -[[package]] -name = "uuid" -version = "1.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - [[package]] name = "v-byte-helpers" version = "0.1.1" -source = "git+https://github.com/RusticMaple/VByteMacros#e2f31bded8c5591e847ba03faf79ae0351e43e69" +source = "git+https://github.com/DJMrTV/VByteMacros#e2f31bded8c5591e847ba03faf79ae0351e43e69" dependencies = [ "bytemuck", "macros 0.1.1", ] -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "vsimd" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" -[[package]] -name = "wasip2" -version = "1.0.3+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" -dependencies = [ - "wit-bindgen", -] - -[[package]] -name = "wasite" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" - [[package]] name = "wasm-bindgen" -version = "0.2.120" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df52b6d9b87e0c74c9edfa1eb2d9bf85e5d63515474513aa50fa181b3c4f5db1" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.104", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.120" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b1041f495fb322e64aca85f5756b2172e35cd459376e67f2a6c9dffcedb103" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3462,59 +1011,49 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.120" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dcd0ff20416988a18ac686d4d4d0f6aae9ebf08a389ff5d29012b05af2a1b41" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ - "bumpalo", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.104", + "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.120" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49757b3c82ebf16c57d69365a142940b384176c24df52a087fb748e2085359ea" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" dependencies = [ "unicode-ident", ] [[package]] name = "webpki-roots" -version = "1.0.7" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" +checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" dependencies = [ "rustls-pki-types", ] -[[package]] -name = "whoami" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" -dependencies = [ - "libredox", - "wasite", -] - [[package]] name = "winapi-util" -version = "0.1.11" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] name = "windows-core" -version = "0.62.2" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", @@ -3525,90 +1064,66 @@ dependencies = [ [[package]] name = "windows-implement" -version = "0.60.2" +version = "0.60.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.104", ] [[package]] name = "windows-interface" -version = "0.59.3" +version = "0.59.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.104", ] [[package]] name = "windows-link" -version = "0.2.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" [[package]] name = "windows-result" -version = "0.4.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" -version = "0.5.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ "windows-link", ] -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] name = "windows-sys" -version = "0.61.2" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-link", -] - -[[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", + "windows-targets", ] [[package]] @@ -3617,46 +1132,28 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", "windows_i686_gnullvm", - "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", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[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" @@ -3669,177 +1166,52 @@ 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 = "wit-bindgen" -version = "0.57.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" - -[[package]] -name = "writeable" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" - -[[package]] -name = "xmlparser" -version = "0.13.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" - -[[package]] -name = "yoke" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" -dependencies = [ - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", - "synstructure", -] - [[package]] name = "zerocopy" -version = "0.8.48" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.48" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", -] - -[[package]] -name = "zerofrom" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", - "synstructure", + "syn 2.0.104", ] [[package]] name = "zeroize" -version = "1.8.2" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" - -[[package]] -name = "zerotrie" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", -] - -[[package]] -name = "zerovec" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "zmij" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/Cargo.toml b/Cargo.toml index 046a20f..9c63a93 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,5 @@ resolver = "3" members = [ "macros", "rnex-core", - "prudpv1", - "prudpv0" -, "proxy", "proxy-common", "prudplite"] + "prudpv1" +] \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 44e7ace..2baa33b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,57 +1,46 @@ -# syntax=docker/dockerfile:1 -FROM rust:alpine AS chef -RUN apk add --no-cache musl-dev lld g++ make -RUN cargo install cargo-chef +FROM rust:alpine AS build-container + +RUN apk add --no-cache protobuf-dev git musl-dev lld openssl-dev openssl-libs-static yq bash + +FROM build-container AS builder + WORKDIR /app -FROM chef AS planner COPY . . -RUN cargo chef prepare --recipe-path recipe.json -FROM chef AS builder -RUN apk add --no-cache protobuf-dev git openssl-dev openssl-libs-static bash yq - -COPY --from=planner /app/recipe.json recipe.json ARG EDITION -ARG DATABASE_URL -RUN --mount=type=cache,target=/usr/local/cargo/registry \ - --mount=type=cache,target=/app/target \ - cargo chef cook --release --recipe-path recipe.json --target x86_64-unknown-linux-musl && \ - cargo chef cook --tests --target x86_64-unknown-linux-musl --recipe-path recipe.json - -COPY . . -RUN --mount=type=cache,target=/usr/local/cargo/registry \ - --mount=type=cache,target=/app/target \ - ./test-edition.sh && ./build-edition.sh && \ - mkdir -p /app/dist && \ - cp /app/target/x86_64-unknown-linux-musl/release/edge_node_holder_server /app/dist/ && \ - cp /app/target/x86_64-unknown-linux-musl/release/proxy_insecure /app/dist/ && \ - cp /app/target/x86_64-unknown-linux-musl/release/proxy_secure /app/dist/ && \ - cp /app/target/x86_64-unknown-linux-musl/release/backend_server_insecure /app/dist/ && \ - cp /app/target/x86_64-unknown-linux-musl/release/backend_server_secure /app/dist/ +RUN git submodule update --init --recursive +RUN ./test-edition.sh +RUN ./build-edition.sh FROM scratch AS node-holder -COPY --from=builder /app/dist/edge_node_holder_server /edge_node_holder_server +COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/edge_node_holder_server /edge_node_holder_server ENTRYPOINT ["/edge_node_holder_server"] -FROM scratch AS proxy-insecure -COPY --from=builder /app/dist/proxy_insecure /proxy_insecure + +FROM alpine:latest AS proxy-insecure +COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/proxy_insecure /proxy_insecure +RUN apk add --no-cache ca-certificates +RUN update-ca-certificates ENTRYPOINT ["/proxy_insecure"] -FROM scratch AS proxy-secure -COPY --from=builder /app/dist/proxy_secure /proxy_secure +FROM alpine:latest AS proxy-secure +COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/proxy_secure /proxy_secure +RUN apk add --no-cache ca-certificates +RUN update-ca-certificates ENTRYPOINT ["/proxy_secure"] - + + FROM scratch AS backend-auth -COPY --from=builder /app/dist/backend_server_insecure /backend_server_insecure +COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/backend_server_insecure /backend_server_insecure ENTRYPOINT ["/backend_server_insecure"] FROM scratch AS backend-secure -COPY --from=builder /app/dist/backend_server_secure /backend_server_secure +COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/backend_server_secure /backend_server_secure ENTRYPOINT ["/backend_server_secure"] -FROM chef AS dev-container -RUN apk add --no-cache openjdk21-jdk gcompat git bash protobuf-dev -COPY --from=builder /app/dist/* /usr/local/bin/ \ No newline at end of file +# make sure the final output container is the dev container so that we can use it from the devcontainer.json +FROM build-container AS dev-container +RUN apk add openjdk21-jdk gcompat diff --git a/README.md b/README.md index 5e64ee4..c5f1ada 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,20 @@ -# Rust NEX monorepo - -This repo contains the code for all game servers using RNEX. +# Splatoon NEX Server in Rust ## Credits: -- Pretendo team for their reverse engineering efforts +- Pretendo team for the rest of the Servers and Reverse engineering efforts - Kinnay for his huge work on reversing nex servers and documentation(https://github.com/Kinnay/NintendoClients/) - Splatfestival testing team for helping us test our messes of code -- The SPFN team(RusticMaple, BloxerHD, Ceantix, RedBinder0526) +- The SPFN team(Bloxer, Ceantix and RusticMaple) -This NEX implementation was not created to rival Pretendo, we don't want any bad blood between anyone. +This nex implementation was not created and is not intended to compete with pretendo, +we wholeheartedly support pretendo. This project would never have been possible without their reverse engineering efforts. -As such if you want to respect the Authors wishes, do not use it if you mean any harm to Pretendo. (harm falls under e.g. using this software while also sabotaging pretendo) If you do show intent to harm them you will be blocked from ever contributing and will be refused support. +As such if you want to respect the Authors wishes(Maple(Me) is pretty much the sole author of Rust-Nex), do not +use it if you mean any harm to pretendo. If you do show intent to harm them you will be blocked from ever contributing +and will be refused support, as such please also refrain from asking for support if you have been blocked by pretendo. -We felt like this needed to be said as there are far too many Pretendo copycats who blatantly copy their code and use their reversal efforts with no credits in sight in an attempt to harm them for some grudge or stupid reason. -We feel that by working together and not against each other we can reach a better and healthier future for the community, health of developers and numerous more reasons. + +I felt like this needed to be said as there are far too many pretendo copycats who blatantly copy their code and use +their reversal efforts with no credits in sight in an attempt to harm them for some grudge or stupid reason. +I feel that by working together and not against each other we can reach a better and healthier future for the community, +health of developers and numerous more reasons. diff --git a/build-edition.sh b/build-edition.sh index 6898acf..7b1cfc0 100755 --- a/build-edition.sh +++ b/build-edition.sh @@ -1,15 +1,11 @@ #!/usr/bin/env bash - -set -euo pipefail - if [ -z ${EDITION+x} ]; then EDITION=$1 fi # comma seperated list of features for the specified version source ./buildscripts/common.sh -echo building $EDITION echo FEATURES: echo $EDITION_FEATURES -OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include/openssl OPENSSL_STATIC=1 RUSTFLAGS="-C relocation-model=static -C linker=ld.lld" cargo build --release --features "$EDITION_FEATURES" --target x86_64-unknown-linux-musl +OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include/openssl OPENSSL_STATIC=1 RUSTFLAGS="-C relocation-model=static -C linker=ld.lld" cargo build --release --features "$EDITION_FEATURES" --target x86_64-unknown-linux-musl \ No newline at end of file diff --git a/buildscripts/common.sh b/buildscripts/common.sh index e4b346c..27fd8cd 100755 --- a/buildscripts/common.sh +++ b/buildscripts/common.sh @@ -1,14 +1,9 @@ #!/usr/bin/env bash - -set -euo pipefail - TMP_FEATURES_TRAILINGCOMMA=$(yq ea ".$EDITION.features" editions.yaml | sed 's/- //g' | tr '\n' ',') -echo "tmpfeatures: $TMP_FEATURES_TRAILINGCOMMA" export EDITION_FEATURES=${TMP_FEATURES_TRAILINGCOMMA::-1} SETTINGS=$(yq ea ".$EDITION.settings" editions.yaml | yq 'keys[]') IFS=$'\n' while IFS=$'\n' read -r KEY; do VAL=$(yq ea ".$EDITION.settings.$KEY" editions.yaml) declare "$KEY=$VAL" - export $KEY -done <<< "$SETTINGS" +done <<< "$SETTINGS" \ No newline at end of file diff --git a/buildscripts/pre-commit b/buildscripts/pre-commit deleted file mode 100755 index 26c6064..0000000 --- a/buildscripts/pre-commit +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -echo "running cargo check..." - -./check-all.sh -STATUS=$? - -if [ $STATUS -ne 0 ]; then - echo "cargo check failed, aborting" - exit 1 -fi - -echo "cargo check passed" -exit 0 diff --git a/check-all.sh b/check-all.sh deleted file mode 100755 index 1494e10..0000000 --- a/check-all.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -EDITIONS=$(yq ea "." editions.yaml | yq 'keys[]') -IFS=$'\n' -while IFS=$'\n' read -r EDITION; do - if [[ $(yq ea ".$EDITION.include-in-checkall" editions.yaml) == "true" ]] - then - export EDITION - ./check-edition.sh $EDITION - fi -done <<< "$EDITIONS" diff --git a/check-edition.sh b/check-edition.sh deleted file mode 100755 index c734770..0000000 --- a/check-edition.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash - - -set -euo pipefail - -if [ -z ${EDITION+x} ]; then - export EDITION=$1 -fi - -# comma seperated list of features for the specified version -source ./buildscripts/common.sh -echo CHECKING $EDITION -echo FEATURES: -echo $EDITION_FEATURES - -cargo check --features "$EDITION_FEATURES" diff --git a/editions.yaml b/editions.yaml index fb635e8..033c77e 100644 --- a/editions.yaml +++ b/editions.yaml @@ -1,117 +1,9 @@ -wii-sports-club: - include-in-checkall: true - features: - - prudpv1 - - third-notif-param - - v3-8-15 - settings: - AUTH_REPORT_VERSION: "branch:origin/project/appsp build:3_4_24_4_0" - RNEX_VIRTUAL_PORT_INSECURE: "1:10" - RNEX_VIRTUAL_PORT_SECURE: "1:10" - RNEX_DEFAULT_PORT: 10000 - RNEX_ACCESS_KEY: "4d324052" -puyopuyo: - include-in-checkall: true - features: - - prudpv1 - - third-notif-param - - v3-8-15 - settings: - AUTH_REPORT_VERSION: "branch:origin/release/ngs/3.5.x.1000 build:3_5_16_1000_0" - RNEX_VIRTUAL_PORT_INSECURE: "1:10" - RNEX_VIRTUAL_PORT_SECURE: "1:10" - RNEX_DEFAULT_PORT: 10000 - RNEX_ACCESS_KEY: "4eb0ca36" -minecraft-wiiu: - include-in-checkall: true - features: - - prudpv1 - - third-notif-param - - v3-10-22 - settings: - AUTH_REPORT_VERSION: "branch:origin/release/ngs/3.10.x.200x build:3_10_22_2006_0" - RNEX_VIRTUAL_PORT_INSECURE: "1:10" - RNEX_VIRTUAL_PORT_SECURE: "1:10" - RNEX_DEFAULT_PORT: 13000 - RNEX_ACCESS_KEY: "f1b61c8e" -mario-tennis: - include-in-checkall: true - features: - - prudpv1 - - third-notif-param - - v3-8-15 - settings: - AUTH_REPORT_VERSION: "branch:origin/release/ngs/3.9.x.200x build:3_9_19_2005_0" - RNEX_VIRTUAL_PORT_INSECURE: "1:10" - RNEX_VIRTUAL_PORT_SECURE: "1:10" - RNEX_DEFAULT_PORT: 10000 - RNEX_ACCESS_KEY: "c69b92a0" -wii-u-chat: - include-in-checkall: true - features: - - prudpv1 - - third-notif-param - - v3-3-2 - settings: - AUTH_REPORT_VERSION: "branch:origin/project/wup-agmj build:3_8_15_2004_0" - RNEX_VIRTUAL_PORT_INSECURE: "1:10" - RNEX_VIRTUAL_PORT_SECURE: "1:10" - RNEX_DEFAULT_PORT: 10000 - RNEX_ACCESS_KEY: "e7a47214" -fast-racing-neo: - include-in-checkall: true - features: - - prudpv1 - - v3-8-15 - settings: - AUTH_REPORT_VERSION: "branch:origin/release/ngs/3.9.x.200x build:3_9_19_2005_0" - RNEX_VIRTUAL_PORT_INSECURE: "1:10" - RNEX_VIRTUAL_PORT_SECURE: "1:10" - RNEX_DEFAULT_PORT: 10000 - RNEX_ACCESS_KEY: "811aa39f" splatoon: - include-in-checkall: true features: - - prudpv1 - - v3-8-15 - - splatoon + - rmc_struct_header settings: AUTH_REPORT_VERSION: "branch:origin/project/wup-agmj build:3_8_15_2004_0" - RNEX_VIRTUAL_PORT_INSECURE: "1:10" - RNEX_VIRTUAL_PORT_SECURE: "1:10" - RNEX_DEFAULT_PORT: 6000 - RNEX_ACCESS_KEY: "6f599f81" -splatoon-testfire: - include-in-checkall: true - features: - - prudpv1 - - v3-8-15 - - splatoon - settings: - AUTH_REPORT_VERSION: "branch:origin/project/wup-agmj build:3_8_15_2004_0" - RNEX_VIRTUAL_PORT_INSECURE: "1:10" - RNEX_VIRTUAL_PORT_SECURE: "1:10" - RNEX_DEFAULT_PORT: 10000 - RNEX_ACCESS_KEY: "da693ee5" friends: - include-in-checkall: false features: - friends - settings: - AUTH_REPORT_VERSION: "branch:origin/feature/45925_FixAutoReconnect build:3_10_11_2006_0" - RNEX_VIRTUAL_PORT_INSECURE: "1:10" - RNEX_VIRTUAL_PORT_SECURE: "1:10" - RNEX_DEFAULT_PORT: 6000 - RNEX_ACCESS_KEY: "ridfebb9" -super-mario-maker: - include-in-checkall: false - features: - - prudpv1 - - v3-8-15 - - datastore - settings: - AUTH_REPORT_VERSION: "branch:origin/project/wup-ama build:3_8_29_3022_0" - RNEX_VIRTUAL_PORT_INSECURE: "1:10" - RNEX_VIRTUAL_PORT_SECURE: "1:10" - RNEX_DEFAULT_PORT: 6000 - RNEX_ACCESS_KEY: "9f2b4678" + settings: {} diff --git a/flake.lock b/flake.lock deleted file mode 100644 index 7826732..0000000 --- a/flake.lock +++ /dev/null @@ -1,61 +0,0 @@ -{ - "nodes": { - "flake-parts": { - "inputs": { - "nixpkgs-lib": "nixpkgs-lib" - }, - "locked": { - "lastModified": 1767609335, - "narHash": "sha256-feveD98mQpptwrAEggBQKJTYbvwwglSbOv53uCfH9PY=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "250481aafeb741edfe23d29195671c19b36b6dca", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1767640445, - "narHash": "sha256-UWYqmD7JFBEDBHWYcqE6s6c77pWdcU/i+bwD6XxMb8A=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "9f0c42f8bc7151b8e7e5840fb3bd454ad850d8c5", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs-lib": { - "locked": { - "lastModified": 1765674936, - "narHash": "sha256-k00uTP4JNfmejrCLJOwdObYC9jHRrr/5M/a/8L2EIdo=", - "owner": "nix-community", - "repo": "nixpkgs.lib", - "rev": "2075416fcb47225d9b68ac469a5c4801a9c4dd85", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "nixpkgs.lib", - "type": "github" - } - }, - "root": { - "inputs": { - "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/flake.nix b/flake.nix deleted file mode 100644 index 0863018..0000000 --- a/flake.nix +++ /dev/null @@ -1,28 +0,0 @@ -{ - description = "rust nex server"; - - inputs = { - nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; - flake-parts.url = "github:hercules-ci/flake-parts"; - }; - - outputs = - inputs@{ - self, - nixpkgs, - flake-parts, - }: - flake-parts.lib.mkFlake { inherit inputs; } { - systems = [ - "x86_64-linux" - "aarch64-linux" - "x86_64-darwin" - "aarch64-darwin" - ]; - perSystem = - { pkgs, lib, ... }: - rec { - devShells.default = import ./shell.nix { inherit pkgs; }; - }; - }; -} diff --git a/macros/Cargo.toml b/macros/Cargo.toml index f748300..dca135c 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "macros" version = "0.0.0" -authors = ["RusticMaple "] +authors = ["DJMrTV "] description = "A `cargo generate` template for quick-starting a procedural macro crate" keywords = ["template", "proc_macro", "procmacro"] edition = "2018" @@ -14,3 +14,4 @@ doctest = false quote = "1.0.38" proc-macro2 = "1.0.93" syn = { version = "2.0.98", features = ["full"] } + diff --git a/macros/src/lib.rs b/macros/src/lib.rs index d0172c2..d088561 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -1,76 +1,418 @@ -#![allow(dead_code)] mod protos; -mod rmc_struct; -mod util; extern crate proc_macro; -use crate::protos::{ProtoInputParams, RmcProtocolData}; -use crate::rmc_struct::{rmc_serialize_enum, rmc_serialize_struct}; +use crate::protos::{ProtoMethodData, RmcProtocolData}; use proc_macro::TokenStream; -use proc_macro2::Ident; -use quote::quote; +use proc_macro2::{Ident, Literal, Span}; +use quote::{quote, TokenStreamExt}; +use syn::parse::{Parse, ParseStream}; +use syn::punctuated::Punctuated; use syn::spanned::Spanned; -use syn::{parse_macro_input, Data, DeriveInput, Lit, LitStr}; +use syn::{ + parse_macro_input, Attribute, Data, DataStruct, DeriveInput, Fields, FnArg, LitInt, Pat, Token, + TraitItem, +}; + +struct ProtoInputParams { + proto_num: LitInt, + properties: Option<(Token![,], Punctuated)>, +} + +impl Parse for ProtoInputParams { + fn parse(input: ParseStream) -> syn::Result { + let proto_num = input.parse()?; + + if let Some(seperator) = input.parse()? { + let mut punctuated = Punctuated::new(); + loop { + punctuated.push_value(input.parse()?); + if let Some(punct) = input.parse()? { + punctuated.push_punct(punct); + } else { + return Ok(Self { + proto_num, + properties: Some((seperator, punctuated)), + }); + } + } + } else { + Ok(Self { + proto_num, + properties: None, + }) + } + } +} + +fn gen_serialize_data_struct( + s: DataStruct, + struct_attr: Option<&Attribute>, +) -> (proc_macro2::TokenStream, proc_macro2::TokenStream, proc_macro2::TokenStream) { + let serialize_base_content = { + let mut serialize_content = quote! {}; + + for f in &s.fields { + if f.attrs.iter().any(|a| { + a.path().segments.len() == 1 + && a.path() + .segments + .first() + .is_some_and(|p| p.ident.to_string() == "extends") + }) { + continue; + } + let ident = f.ident.as_ref().unwrap(); + + serialize_content.append_all(quote! { + rnex_core::rmc::structures::RmcSerialize::serialize(&self.#ident, writer)?; + }) + } + + quote! { + #serialize_content + + Ok(()) + } + }; + + let struct_ctor = { + let mut structure_content = quote! {}; + for f in &s.fields { + let ident = f.ident.as_ref().unwrap(); + + structure_content.append_all(quote! {#ident, }); + } + + quote! { + Ok(Self{ + #structure_content + }) + } + }; + + let deserialize_base_content = { + let mut deserialize_content = quote! {}; + + for f in &s.fields { + if f.attrs.iter().any(|a| { + a.path().segments.len() == 1 + && a.path() + .segments + .first() + .is_some_and(|p| p.ident.to_string() == "extends") + }) { + continue; + } + + let ident = f.ident.as_ref().unwrap(); + let ty = &f.ty; + + deserialize_content.append_all(quote! { + let #ident = <#ty> :: deserialize(reader)?; + }) + } + + quote! { + #deserialize_content + #struct_ctor + } + }; + + let write_size = { + let mut size_content = quote! { 0 }; + + for f in &s.fields { + + + let ident = f.ident.as_ref().unwrap(); + + size_content.append_all(quote! { + + rnex_core::rmc::structures::RmcSerialize::serialize_write_size(&self.#ident)? + }) + } + + size_content + }; + let write_size = if let Some(_) = struct_attr { + quote!{ #write_size + if rnex_core::config::FEATURE_HAS_STRUCT_HEADER{ 5 } else { 0 } } + } else { + write_size + }; + + + // generate base with extends stuff + + let serialize_base_content = if let Some(attr) = struct_attr { + let version: Literal = attr.parse_args().expect("has to be a literal"); + + let pre_inner = if let Some(f) = s.fields.iter().find(|f| { + f.attrs.iter().any(|a| { + a.path().segments.len() == 1 + && a.path() + .segments + .first() + .is_some_and(|p| p.ident.to_string() == "extends") + }) + }) { + let ident = f.ident.as_ref().unwrap(); + quote! { + self.#ident.serialize(writer)?; + } + } else { + quote! {} + }; + + quote! { + #pre_inner + rnex_core::rmc::structures::rmc_struct::write_struct( + writer, + #version, + rnex_core::rmc::structures::helpers::len_of_write( + |writer|{ + #serialize_base_content + } + ), + |writer|{ + #serialize_base_content + } + )?; + + Ok(()) + } + } else { + serialize_base_content + }; + + let deserialize_base_content = if let Some(attr) = struct_attr { + let version: Literal = attr.parse_args().expect("has to be a literal"); + + let pre_inner = if let Some(f) = s.fields.iter().find(|f| { + f.attrs.iter().any(|a| { + a.path().segments.len() == 1 + && a.path() + .segments + .first() + .is_some_and(|p| p.ident.to_string() == "extends") + }) + }) { + let ident = f.ident.as_ref().unwrap(); + let ty = &f.ty; + quote! { + let #ident = <#ty> :: deserialize(reader)?; + } + } else { + quote! {} + }; + + quote! { + #pre_inner + Ok(rnex_core::rmc::structures::rmc_struct::read_struct(reader, #version, move |mut reader|{ + #deserialize_base_content + })?) + } + } else { + deserialize_base_content + }; + + let write_size = quote!{ + fn serialize_write_size(&self) -> rnex_core::rmc::structures::Result{ + Ok(#write_size) + } + }; + + (serialize_base_content, deserialize_base_content, write_size) +} #[proc_macro_derive(RmcSerialize, attributes(extends, rmc_struct))] pub fn rmc_serialize(input: TokenStream) -> TokenStream { let derive_input = parse_macro_input!(input as DeriveInput); - let (serialize, deserialize, write_size, version) = match &derive_input.data { - Data::Struct(s) => rmc_serialize_struct(s, &derive_input), - Data::Enum(e) => rmc_serialize_enum(e, &derive_input), + let struct_attr = derive_input.attrs.iter().find(|a| { + a.path().segments.len() == 1 + && a.path() + .segments + .first() + .is_some_and(|p| p.ident.to_string() == "rmc_struct") + }); + let repr_attr = derive_input.attrs.iter().find(|a| { + a.path().segments.len() == 1 + && a.path() + .segments + .first() + .is_some_and(|p| p.ident.to_string() == "repr") + }); + + /*let Data::Struct(s) = derive_input.data else { + panic!("rmc struct type MUST be a struct"); + };*/ + + let (serialize_base_content, deserialize_base_content, write_size) = match derive_input.data { + Data::Struct(s) => gen_serialize_data_struct(s, struct_attr), + Data::Enum(e) => { + let Some(repr_attr) = repr_attr else { + panic!("missing repr attribute"); + }; + + let ty: Ident = repr_attr.parse_args().unwrap(); + + let mut inner_match_de = quote! {}; + let mut inner_match_se = quote! {}; + //let mut inner_match_len = quote!{}; + + for variant in e.variants { + let Some((_, val)) = variant.discriminant else { + panic!("missing discriminant"); + }; + + let field_data_de = match &variant.fields { + Fields::Named(v) => { + let mut base = quote! {}; + for field in v.named.iter() { + let ty = &field.ty; + let name = &field.ident; + + base.append_all(quote!{ + #name: <#ty as rnex_core::rmc::structures::RmcSerialize>::deserialize(reader)?, + }); + } + + quote! {{#base}} + } + Fields::Unnamed(n) => { + let mut base = quote! {}; + + for field in n.unnamed.iter() { + let ty = &field.ty; + + base.append_all(quote!{ + <#ty as rnex_core::rmc::structures::RmcSerialize>::deserialize(reader)?, + }); + } + + quote! {(#base)} + } + Fields::Unit => { + quote! {} + } + }; + + let mut se_with_fields = quote! { + <#ty as rnex_core::rmc::structures::RmcSerialize>::serialize(&#val, writer)?; + }; + + match &variant.fields { + Fields::Named(v) => { + for field in v.named.iter() { + let ty = &field.ty; + let name = &field.ident; + + se_with_fields.append_all(quote!{ + <#ty as rnex_core::rmc::structures::RmcSerialize>::serialize(#name ,writer)?; + }); + } + } + Fields::Unnamed(n) => { + for (i, field) in n.unnamed.iter().enumerate() { + let ty = &field.ty; + + let ident = Ident::new(&format!("val_{}", i), Span::call_site()); + + se_with_fields.append_all(quote!{ + <#ty as rnex_core::rmc::structures::RmcSerialize>::serialize(#ident, writer)?; + }); + } + } + Fields::Unit => {} + }; + + let field_match_se = match &variant.fields { + Fields::Named(v) => { + let mut base = quote! {}; + + for field in v.named.iter() { + let name = &field.ident; + + base.append_all(quote! { + #name, + }); + } + + quote! {{#base}} + } + Fields::Unnamed(n) => { + let mut base = quote! {}; + + for (i, _field) in n.unnamed.iter().enumerate() { + let ident = Ident::new(&format!("val_{}", i), Span::call_site()); + + base.append_all(quote! { + #ident, + }); + } + + quote! {(#base)} + } + Fields::Unit => { + quote! {} + } + }; + + let name = variant.ident; + + inner_match_de.append_all(quote! { + #val => Self::#name #field_data_de, + }); + + inner_match_se.append_all(quote! { + Self::#name #field_match_se => { + #se_with_fields + }, + }); + } + + let serialize_base_content = quote! { + match self{ + #inner_match_se + }; + + + + Ok(()) + }; + + let deserialize_base_content = quote! { + let val: Self = match <#ty as rnex_core::rmc::structures::RmcSerialize>::deserialize(reader)?{ + #inner_match_de + v => return Err(rnex_core::rmc::structures::Error::UnexpectedValue(v as _)) + }; + + Ok(val) + }; + + (serialize_base_content, deserialize_base_content, quote!{}) + } Data::Union(_) => { - unimplemented!("serialize a union is not allowed"); + unimplemented!() } }; // generate base data - let str_name = Lit::Str(LitStr::new( - &derive_input.ident.to_string(), - derive_input.ident.span(), - )); let ident = derive_input.ident; - let write_size = if let Some(v) = write_size { - quote! { - fn serialize_write_size(&self) -> rnex_core::rmc::structures::Result{ - #v - } - } - } else { - quote! {} - }; - - let version = if let Some(v) = version { - quote! { - fn version() -> Option{ - #v - } - } - } else { - quote! {} - }; - let tokens = quote! { impl rnex_core::rmc::structures::RmcSerialize for #ident{ #[inline(always)] fn serialize(&self, writer: &mut impl ::std::io::Write) -> rnex_core::rmc::structures::Result<()>{ - #serialize + #serialize_base_content } #[inline(always)] fn deserialize(reader: &mut impl ::std::io::Read) -> rnex_core::rmc::structures::Result{ - #deserialize + #deserialize_base_content } #write_size - - #version - - fn name() -> &'static str{ - #str_name - } } }; @@ -104,9 +446,71 @@ pub fn rmc_serialize(input: TokenStream) -> TokenStream { #[proc_macro_attribute] pub fn rmc_proto(attr: TokenStream, input: TokenStream) -> TokenStream { let params = parse_macro_input!(attr as ProtoInputParams); + + let ProtoInputParams { + proto_num, + properties, + } = params; + + let no_return_data = + properties.is_some_and(|p| p.1.iter().any(|i| i.to_string() == "NoReturn")); + let input = parse_macro_input!(input as syn::ItemTrait); - let raw_data = RmcProtocolData::new(params, &input); + // gigantic ass struct initializer (to summarize this gets all of the data) + let raw_data = RmcProtocolData { + has_returns: !no_return_data, + name: input.ident.clone(), + id: proto_num, + methods: input + .items + .iter() + .filter_map(|v| match v { + TraitItem::Fn(v) => Some(v), + _ => None, + }) + .map(|func| { + let Some(attr) = func.attrs.iter().find(|a| { + a.path() + .segments + .last() + .is_some_and(|s| s.ident.to_string() == "method_id") + }) else { + panic!("every function inside of an rmc protocol must have a method id"); + }; + + let Ok(id): Result = attr.parse_args() else { + panic!("todo: put a propper error message here"); + }; + + let funcs = func + .sig + .inputs + .iter() + .skip(1) + .map(|f| { + let FnArg::Typed(t) = f else { + panic!("what"); + }; + let Pat::Ident(i) = &*t.pat else { + panic!( + "unable to handle non identifier patterns as parameter bindings" + ); + }; + + (i.ident.clone(), t.ty.as_ref().clone()) + }) + .collect(); + + ProtoMethodData { + id, + name: func.sig.ident.clone(), + parameters: funcs, + ret_val: func.sig.output.clone(), + } + }) + .collect(), + }; quote! { #input diff --git a/macros/src/protos.rs b/macros/src/protos.rs index 3171598..7dd7bf1 100644 --- a/macros/src/protos.rs +++ b/macros/src/protos.rs @@ -1,280 +1,131 @@ use proc_macro2::{Ident, Span, TokenStream}; use quote::{quote, ToTokens}; -use syn::{ - parse::{Parse, ParseStream}, - punctuated::Punctuated, - Attribute, FnArg, ItemTrait, LitInt, LitStr, Meta, Pat, ReturnType, Token, TraitItem, Type, -}; +use syn::{LitInt, LitStr, ReturnType, Type}; +use syn::token::{Brace, Paren, Semi}; -use crate::util::fold_tokenable; - -pub struct ProtoInputParams { - proto_num: LitInt, - properties: Option<(Token![,], Punctuated)>, -} - -impl Parse for ProtoInputParams { - fn parse(input: ParseStream) -> syn::Result { - let proto_num = input.parse()?; - - if let Some(seperator) = input.parse()? { - let mut punctuated = Punctuated::new(); - loop { - punctuated.push_value(input.parse()?); - if let Some(punct) = input.parse()? { - punctuated.push_punct(punct); - } else { - return Ok(Self { - proto_num, - properties: Some((seperator, punctuated)), - }); - } - } - } else { - Ok(Self { - proto_num, - properties: None, - }) - } - } -} -pub struct ProtoMethodData { +pub struct ProtoMethodData{ pub id: LitInt, pub name: Ident, - pub attributes: Vec, - pub parameters: Vec<(Ident, Type, Vec)>, + pub parameters: Vec<(Ident, Type)>, pub ret_val: ReturnType, } + /// This is a representation of the code generated by `rmc_proto` it serves to split the logic of /// acquiring data from the actual generation to tidy up the process into first getting then /// generating. /// /// Use the [`ToTokens`] trait to generate the actual code. -pub struct RmcProtocolData { +pub struct RmcProtocolData{ pub has_returns: bool, pub id: LitInt, pub name: Ident, - pub methods: Vec, + pub methods: Vec } -impl RmcProtocolData { - pub fn new(params: ProtoInputParams, input: &ItemTrait) -> Self { - let ProtoInputParams { - proto_num, - properties, - } = params; - - let no_return_data = - properties.is_some_and(|p| p.1.iter().any(|i| i.to_string() == "NoReturn")); - - // gigantic ass struct initializer (to summarize this gets all of the data) - RmcProtocolData { - has_returns: !no_return_data, - name: input.ident.clone(), - id: proto_num, - methods: input - .items - .iter() - .filter_map(|v| match v { - TraitItem::Fn(v) => Some(v), - _ => None, - }) - .map(|func| { - let Some(attr) = func.attrs.iter().find(|a| { - a.path() - .segments - .last() - .is_some_and(|s| s.ident.to_string() == "method_id") - }) else { - panic!("every function inside of an rmc protocol must have a method id"); - }; - - let Ok(id): Result = attr.parse_args() else { - panic!("todo: put a propper error message here"); - }; - - let funcs = func - .sig - .inputs - .iter() - .skip(1) - .map(|f| { - let FnArg::Typed(t) = f else { - panic!("what"); - }; - let Pat::Ident(i) = &*t.pat else { - panic!( - "unable to handle non identifier patterns as parameter bindings" - ); - }; - - (i.ident.clone(), t.ty.as_ref().clone(), t.attrs.clone()) - }) - .collect(); - - ProtoMethodData { - id, - name: func.sig.ident.clone(), - parameters: funcs, - ret_val: func.sig.output.clone(), - attributes: func - .attrs - .iter() - .filter(|a| match &a.meta { - Meta::NameValue(v) => { - if let Some(i) = v.path.get_ident() { - i.to_string() != "doc" - } else { - true - } - } - Meta::List(l) => { - if let Some(seg) = l.path.segments.last() { - seg.ident.to_string() != "method_id" - } else { - true - } - } - _ => true, - }) - .cloned() - .collect(), - } - }) - .collect(), - } - } - - fn generate_raw_trait(&self) -> TokenStream { - let Self { +impl RmcProtocolData{ + fn generate_raw_trait(&self, tokens: &mut TokenStream){ + let Self{ has_returns, name, id, - methods, + methods } = self; - let generate_raw_method = |method: &ProtoMethodData| -> TokenStream { - let ProtoMethodData { - name, - parameters, - attributes, - .. - } = method; - let attribs = fold_tokenable(attributes.iter()); + // this gives us the name which the identifier of the corresponding Raw trait + let raw_name = Ident::new(&format!("Raw{}", name), name.span()); - let raw_name = Ident::new(&format!("raw_{}", name), name.span()); - let optional_return = if self.has_returns { - quote! { - -> ::core::result::Result, ::rnex_core::rmc::response::ErrorCode> - } - } else { - quote! {} - } - .into_token_stream(); + // boilerplate tokens which all raw traits need + quote!{ + #[doc(hidden)] + #[allow(unused_must_use)] + pub trait #raw_name: #name + }.to_tokens(tokens); - let deser_params = - fold_tokenable(parameters.iter().map(|(param_name, param_type, attribs)| { - let error_msg = LitStr::new( - &format!("an error occurred whilest deserializing {}", param_name), - Span::call_site(), - ); - let return_from_deser_error = if self.has_returns { - quote! { - return Err(::rnex_core::rmc::response::ErrorCode::Core_InvalidArgument); - } - } else { - quote! { - return; - } - }; - let attribs = fold_tokenable(attribs.iter()); - quote! { - #attribs - let Ok(#param_name) = - <#param_type as rnex_core::rmc::structures::RmcSerialize>::deserialize( - &mut cursor - ) else{ - log::error!(#error_msg); - #return_from_deser_error - }; - } - })); - - let call_params = fold_tokenable(parameters.iter().map(|(param_name, _, attribs)| { - let attribs = fold_tokenable(attribs.iter()); - quote! { - #attribs - #param_name, - } - })); - - let optional_method_return = if *has_returns { - quote! { - let retval = retval?; - let mut vec = Vec::new(); - rnex_core::rmc::structures::RmcSerialize::serialize(&retval, &mut vec).ok(); - Ok(vec) - } - } else { - quote! {} - }; - - quote! { - #[inline(always)] - #attribs - async fn #raw_name (&self, data: ::std::vec::Vec) #optional_return{ - let mut cursor = ::std::io::Cursor::new(data); - #deser_params - let retval = self.#name(#call_params).await; - #optional_method_return - } - - } - }; - - let generate_rmc_call_proto = || { - let method_entries = fold_tokenable(methods.iter().map(|m| { + // generate the body of the raw protocol trait + Brace::default().surround(tokens, |tokens|{ + //generate each raw method + for method in methods{ let ProtoMethodData { - id, name, - attributes, + parameters, .. - } = m; + } = method; - let attribs = fold_tokenable(attributes.iter()); let raw_name = Ident::new(&format!("raw_{}", name), name.span()); + quote!{ + #[inline(always)] + async fn #raw_name + }.to_tokens(tokens); - quote! { - #attribs - #id => self.#raw_name(data).await, + Paren::default().surround(tokens, |tokens|{ + quote!{ &self, data: ::std::vec::Vec }.to_tokens(tokens); + }); + + if self.has_returns { + quote! { + -> ::core::result::Result, ErrorCode> + }.to_tokens(tokens); } - })); - let optional_notimpl_return = if self.has_returns { - quote! { - Err(rnex_core::rmc::response::ErrorCode::Core_NotImplemented) - } - } else { - quote! {} - }; + Brace::default().surround(tokens, |tokens|{ + quote! { let mut cursor = ::std::io::Cursor::new(data); }.to_tokens(tokens); - let optional_result_sendback = if *has_returns { - quote! { - rnex_core::rmc::response::send_result( - remote_response_connection, - ret, - #id, - method_id, - call_id, - ).await - } - } else { - quote! {} - }; + for (param_name, param_type) in parameters{ + quote!{ + let Ok(#param_name) = + <#param_type as rnex_core::rmc::structures::RmcSerialize>::deserialize( + &mut cursor + ) else + }.to_tokens(tokens); - quote! { + let error_msg = LitStr::new(&format!("an error occurred whilest deserializing {}", param_name), Span::call_site()); + + if self.has_returns { + quote! { + { + log::error!(#error_msg); + return Err(rnex_core::rmc::response::ErrorCode::Core_InvalidArgument); + }; + }.to_tokens(tokens) + } else { + quote! { + { + log::error!(#error_msg); + return; + }; + }.to_tokens(tokens) + } + + } + + quote!{ + let retval = self.#name + }.to_tokens(tokens); + + Paren::default().surround(tokens, |tokens|{ + for (paren_name, _) in parameters{ + quote!{#paren_name,}.to_tokens(tokens); + } + }); + + quote!{ + .await; + }.to_tokens(tokens); + + if *has_returns{ + quote!{ + let retval = retval?; + let mut vec = Vec::new(); + rnex_core::rmc::structures::RmcSerialize::serialize(&retval, &mut vec).ok(); + Ok(vec) + }.to_tokens(tokens); + } + }) + } + + quote!{ #[inline(always)] async fn rmc_call_proto( &self, @@ -282,38 +133,70 @@ impl RmcProtocolData { method_id: u32, call_id: u32, data: Vec, - ){ - let ret = match method_id{ - #method_entries - v => { + ) + }.to_tokens(tokens); + + Brace::default().surround(tokens, |tokens|{ + quote! { + let ret = match method_id + }.to_tokens(tokens); + + Brace::default().surround(tokens, |tokens|{ + for method in methods{ + let ProtoMethodData{ + id, + name, + .. + } = method; + + let raw_name = Ident::new(&format!("raw_{}", name), name.span()); + + + quote!{ + #id => self.#raw_name(data).await, + }.to_tokens(tokens); + } + quote!{ + v => + }.to_tokens(tokens); + + + + Brace::default().surround(tokens, |tokens|{ + quote!{ log::error!("(protocol {})unimplemented method id called on protocol: {}", #id, v); - #optional_notimpl_return + }.to_tokens(tokens); + if self.has_returns { + quote! { + Err(rnex_core::rmc::response::ErrorCode::Core_NotImplemented) + }.to_tokens(tokens); } - }; - #optional_result_sendback + }); + + }); + + Semi::default().to_tokens(tokens); + + if *has_returns{ + quote!{ + rnex_core::rmc::response::send_result( + remote_response_connection, + ret, + #id, + method_id, + call_id, + ).await + }.to_tokens(tokens); } - } - }; + }); + }); - // this gives us the name which the identifier of the corresponding Raw trait - let raw_name = Ident::new(&format!("Raw{}", name), name.span()); - let proto_raw_methods = fold_tokenable(self.methods.iter().map(|m| generate_raw_method(m))); - let rmc_call_proto = generate_rmc_call_proto(); - - // boilerplate tokens which all raw traits need - quote! { - #[doc(hidden)] - #[allow(unused_must_use)] - pub trait #raw_name: #name{ - #proto_raw_methods - #rmc_call_proto - } + quote!{ impl #raw_name for T{} - } - .to_token_stream() + }.to_tokens(tokens); } - fn generate_raw_remote_trait(&self) -> TokenStream { + fn generate_raw_remote_trait(&self, tokens: &mut TokenStream) { let Self { has_returns, name, @@ -324,111 +207,127 @@ impl RmcProtocolData { // this gives us the name which the identifier of the corresponding Raw trait let remote_name = Ident::new(&format!("Remote{}", name), name.span()); - let generate_remote_method = |m: &ProtoMethodData| -> TokenStream { - let ProtoMethodData { - name, - parameters, - ret_val, - attributes, - id: method_id, - } = m; - let params = fold_tokenable(parameters.iter().map(|(ident, ty, attr)| { - let attrs = fold_tokenable(attr.iter()); - quote! { #attrs #ident: #ty, } - })); - let optional_questionmark_operator = if self.has_returns { - quote! { - ? - } - } else { - quote! {} - }; - - let param_serialize = fold_tokenable(parameters.iter().map(|(name, ty, attrs)|{ - let attrs = fold_tokenable(attrs.iter()); - quote!{ - #attrs - rnex_core::result::ResultExtension::display_err_or_some( - <#ty as rnex_core::rmc::structures::RmcSerialize>::serialize( - &#name, - &mut cursor - ) - ).ok_or(rnex_core::rmc::response::ErrorCode::Core_InvalidArgument)#optional_questionmark_operator ; - } - })); - - let make_call = if *has_returns { - quote! { - rnex_core::result::ResultExtension::display_err_or_some( - rmc_conn.make_raw_call(&message).await - ).ok_or(rnex_core::rmc::response::ErrorCode::Core_Exception) - } - } else { - quote! { - rnex_core::result::ResultExtension::display_err_or_some( - rmc_conn.make_raw_call_no_response(&message).await - ); - } - }; - - let attribs = fold_tokenable(attributes.iter()); - - quote! { - #attribs - async fn #name(&self, #params) #ret_val{ - let mut send_data = ::std::vec::Vec::new(); - let mut cursor = ::std::io::Cursor::new(&mut send_data); - #param_serialize - - let call_id = rand::random(); - - let message = rnex_core::rmc::message::RMCMessage{ - call_id, - method_id: #method_id, - protocol_id: #proto_id, - rest_of_data: send_data - }; - - let rmc_conn = ::get_connection(self); - - #make_call - } - } - }; - - let remote_methods = fold_tokenable(methods.iter().map(|m| generate_remote_method(m))); - - quote! { + // boilerplate tokens which all raw traits need + quote!{ #[doc(hidden)] #[allow(unused_must_use)] - pub trait #remote_name: rnex_core::rmc::protocols::HasRmcConnection{ - #remote_methods + pub trait #remote_name: rnex_core::rmc::protocols::HasRmcConnection + }.to_tokens(tokens); + + // generate the body of the raw protocol trait + Brace::default().surround(tokens, |tokens|{ + //generate each raw method + for method in methods{ + let ProtoMethodData { + name, + parameters, + ret_val, + id: method_id, + .. + } = method; + + quote!{ + async fn #name + }.to_tokens(tokens); + + Paren::default().surround(tokens, |tokens|{ + quote!{ &self, }.to_tokens(tokens); + for (param_ident, param_type) in parameters{ + quote!{ #param_ident: #param_type, }.to_tokens(tokens); + } + }); + + quote!{ + #ret_val + }.to_tokens(tokens); + + Brace::default().surround(tokens, |tokens|{ + quote! { + let mut send_data = Vec::new(); + let mut cursor = ::std::io::Cursor::new(&mut send_data); + }.to_tokens(tokens); + + for (param_name, param_type) in parameters{ + quote!{ + rnex_core::result::ResultExtension::display_err_or_some( + <#param_type as rnex_core::rmc::structures::RmcSerialize>::serialize( + &#param_name, + &mut cursor + ) + ).ok_or(rnex_core::rmc::response::ErrorCode::Core_InvalidArgument) + }.to_tokens(tokens); + if self.has_returns { + quote! { + ?; + }.to_tokens(tokens) + } else { + quote! { + ; + }.to_tokens(tokens) + } + } + + quote!{ + let call_id = rand::random(); + + let message = rnex_core::rmc::message::RMCMessage{ + call_id, + method_id: #method_id, + protocol_id: #proto_id, + rest_of_data: send_data + }; + + let rmc_conn = ::get_connection(self); + }.to_tokens(tokens); + + if *has_returns{ + quote!{ + rnex_core::result::ResultExtension::display_err_or_some( + rmc_conn.make_raw_call(&message).await + ).ok_or(rnex_core::rmc::response::ErrorCode::Core_Exception) + }.to_tokens(tokens); + } else { + quote!{ + rnex_core::result::ResultExtension::display_err_or_some( + rmc_conn.make_raw_call_no_response(&message).await + ); + }.to_tokens(tokens); + } + + }) } - } + }); + + } - fn generate_raw_info(&self) -> TokenStream { - let Self { name, id, .. } = self; + fn generate_raw_info(&self, tokens: &mut TokenStream){ + let Self{ + name, + id, + .. + } = self; let raw_info_name = Ident::new(&format!("Raw{}Info", name), Span::call_site()); - quote! { + + quote!{ #[doc(hidden)] pub struct #raw_info_name; impl #raw_info_name { pub const PROTOCOL_ID: u16 = #id; } - } + }.to_tokens(tokens); } } -impl ToTokens for RmcProtocolData { +impl ToTokens for RmcProtocolData{ fn to_tokens(&self, tokens: &mut TokenStream) { - self.generate_raw_trait().to_tokens(tokens); - self.generate_raw_info().to_tokens(tokens); - self.generate_raw_remote_trait().to_tokens(tokens); + self.generate_raw_trait(tokens); + self.generate_raw_info(tokens); + self.generate_raw_remote_trait(tokens); } -} +} \ No newline at end of file diff --git a/macros/src/rmc_struct.rs b/macros/src/rmc_struct.rs deleted file mode 100644 index 66f9515..0000000 --- a/macros/src/rmc_struct.rs +++ /dev/null @@ -1,426 +0,0 @@ -use proc_macro2::{Literal, Span, TokenStream}; -use quote::quote; -use syn::{ - bracketed, parse::Parse, punctuated::Punctuated, token::Bracket, DataEnum, DataStruct, - DeriveInput, Field, Fields, Ident, Meta, Token, Variant, -}; - -use crate::util::fold_tokenable; - -struct RmcStructAttrVersion { - bracket: Bracket, - delim: Token![,], - feature_name: Literal, - struct_version: Literal, -} - -struct RmcStructAttr { - base_ver: Literal, - versions: Option<(Token![,], Punctuated)>, -} - -impl Parse for RmcStructAttr { - fn parse(input: syn::parse::ParseStream) -> syn::Result { - let base_ver = input.parse()?; - - if let Some(seperator) = input.parse()? { - let mut punctuated = Punctuated::new(); - loop { - punctuated.push_value(input.parse()?); - if let Some(punct) = input.parse()? { - punctuated.push_punct(punct); - } else { - return Ok(Self { - base_ver, - versions: Some((seperator, punctuated)), - }); - } - } - } else { - Ok(Self { - base_ver, - versions: None, - }) - } - } -} - -impl RmcStructAttr { - fn versions(&self) -> impl Iterator { - self.versions.iter().flat_map(|v| v.1.iter()) - } -} - -impl Parse for RmcStructAttrVersion { - fn parse(input: syn::parse::ParseStream) -> syn::Result { - let content; - let bracket = bracketed!(content in input); - let (feature_name, delim, struct_version) = - content.call(|s| Ok((s.parse()?, s.parse()?, s.parse()?)))?; - - Ok(Self { - bracket, - delim, - feature_name, - struct_version, - }) - } -} - -pub fn generate_write_size_struct( - s: &DataStruct, - with_potential_header: bool, -) -> proc_macro2::TokenStream { - // this is fine and works because of a quirk where the sizes of the structs dont change - // if we ignore wether or not a struct extends the other struct or has it as a field - - let base_size = fold_tokenable(s.fields.iter().map(|f| { - let ident = f.ident.as_ref().unwrap(); - let attrs = fold_tokenable(f.attrs.iter().filter(|a| { - if let Some(i) = a.meta.path().get_ident() { - i.to_string() != "extends" - } else { - true - } - })); - quote! { - #attrs - sum += rnex_core::rmc::structures::RmcSerialize::serialize_write_size(&self.#ident)?; - } - })); - let optional_struct_header_calc = if with_potential_header { - quote! { sum += (if rnex_core::config::FEATURE_HAS_STRUCT_HEADER{ 5 } else { 0 }); } - } else { - quote! {} - }; - quote! { - let mut sum = 0; - #base_size - #optional_struct_header_calc - Ok(sum) - } -} -pub fn generate_serialize_struct( - extended_struct: Option<&Field>, - elems: &[&Field], - with_header: bool, -) -> proc_macro2::TokenStream { - fn gen_elem_serialize(f: &Field) -> TokenStream { - let ident = f.ident.as_ref().unwrap(); - let attrs = fold_tokenable(f.attrs.iter().filter(|a| { - if let Some(i) = a.meta.path().get_ident() { - i.to_string() != "extends" - } else { - true - } - })); - quote! { - #attrs - rnex_core::rmc::structures::RmcSerialize::serialize(&self.#ident, writer)?; - } - } - let optional_extended_struct = if let Some(f) = extended_struct { - gen_elem_serialize(f) - } else { - quote! {} - }; - let elems = fold_tokenable(elems.iter().map(|e| gen_elem_serialize(e))); - let ser_body = if with_header { - quote! { - rnex_core::rmc::structures::rmc_struct::write_struct( - writer, - Self::version().unwrap(), - rnex_core::rmc::structures::helpers::len_of_write( - |writer|{ - #elems - Ok(()) - } - ), - |writer|{ - #elems - Ok(()) - } - )?; - } - } else { - elems - }; - - quote! { - #optional_extended_struct - #ser_body - Ok(()) - } -} -pub fn generate_deserialize_struct( - s: &DataStruct, - extended_struct: Option<&Field>, - elems: &[&Field], - with_header: bool, -) -> proc_macro2::TokenStream { - fn gen_elem_serialize(f: &Field) -> TokenStream { - let ident = f.ident.as_ref().unwrap(); - let ty = &f.ty; - let attrs = fold_tokenable(f.attrs.iter().filter(|a| { - if let Some(i) = a.meta.path().get_ident() { - i.to_string() != "extends" - } else { - true - } - })); - quote! { - #attrs - let #ident: #ty = rnex_core::rmc::structures::RmcSerialize::deserialize(reader)?; - } - } - let optional_extended_struct = if let Some(f) = extended_struct { - gen_elem_serialize(f) - } else { - quote! {} - }; - let elems = fold_tokenable(elems.iter().map(|e| gen_elem_serialize(e))); - let struct_ctor_content = fold_tokenable(s.fields.iter().map(|f| { - let ident = f.ident.as_ref().unwrap(); - let attrs = fold_tokenable(f.attrs.iter().filter(|a| { - if let Some(i) = a.meta.path().get_ident() { - i.to_string() != "extends" - } else { - true - } - })); - quote! { #attrs #ident, } - })); - let de_body_inner = quote! { - #elems - Ok(Self{ - #struct_ctor_content - }) - }; - let de_body = if with_header { - quote! { - Ok(rnex_core::rmc::structures::rmc_struct::read_struct(reader, Self::version().unwrap(), move |mut reader|{ - #de_body_inner - })?) - } - } else { - de_body_inner - }; - - quote! { - #optional_extended_struct - #de_body - } -} - -fn generate_struct_version(attr: Option<&RmcStructAttr>) -> proc_macro2::TokenStream { - if let Some(attr) = attr { - let base_ver = &attr.base_ver; - let if_else_chain = fold_tokenable(attr.versions().map(|v| { - let version_val = &v.struct_version; - let feature = &v.feature_name; - quote! { - if cfg!(feature = #feature){ - #version_val - } else - } - })); - - quote! { - Some(#if_else_chain { - #base_ver - }) - } - } else { - quote! { None } - } -} - -pub fn rmc_serialize_struct( - s: &DataStruct, - derive_input: &DeriveInput, -) -> ( - proc_macro2::TokenStream, - proc_macro2::TokenStream, - Option, - Option, -) { - let struct_attr = derive_input.attrs.iter().find(|a| { - a.path().segments.len() == 1 - && a.path() - .segments - .first() - .is_some_and(|p| p.ident.to_string() == "rmc_struct") - && matches!(a.meta, Meta::List(_)) - }); - - let struct_attr: Option = struct_attr.map(|a| a.parse_args().unwrap()); - let struct_attr = struct_attr.as_ref(); - - let extended_struct = s.fields.iter().find(|f| { - f.attrs.iter().any(|a| { - a.path().segments.len() == 1 - && a.path() - .segments - .first() - .is_some_and(|p| p.ident.to_string() == "extends") - }) - }); - let elements: Vec<_> = s - .fields - .iter() - .filter(|f| { - !f.attrs.iter().any(|a| { - a.path().segments.len() == 1 - && a.path() - .segments - .first() - .is_some_and(|p| p.ident.to_string() == "extends") - }) - }) - .collect(); - let elements = &elements[..]; - - let serialize = generate_serialize_struct(extended_struct, elements, struct_attr.is_some()); - let deserialize = - generate_deserialize_struct(s, extended_struct, elements, struct_attr.is_some()); - let write_size = generate_write_size_struct(s, struct_attr.is_some()); - let version = generate_struct_version(struct_attr); - - (serialize, deserialize, Some(write_size), Some(version)) -} - -fn field_to_ident(field: &Field, idx: usize) -> Ident { - if let Some(i) = &field.ident { - i.clone() - } else { - Ident::new(&format!("field_{}", idx), Span::call_site()) - } -} - -fn variant_to_pattern_and_fields(variant: &Variant) -> (proc_macro2::TokenStream, Vec) { - match &variant.fields { - Fields::Named(n) => { - let inner = n - .named - .iter() - .map(|f| { - let attrs = fold_tokenable(f.attrs.iter()); - let ident = f.ident.as_ref().unwrap(); - - quote! { #attrs #ident } - }) - .reduce(|a, b| quote! {#a, #b}); - - (quote! {{#inner}}, n.named.iter().cloned().collect()) - } - Fields::Unnamed(n) => { - let inner = n - .unnamed - .iter() - .enumerate() - .map(|(i, f)| { - let attrs = fold_tokenable(f.attrs.iter()); - let name = field_to_ident(f, i); - - quote! { #attrs #name } - }) - .reduce(|a, b| quote! {#a, #b}); - - (quote! {(#inner)}, n.unnamed.iter().cloned().collect()) - } - Fields::Unit => (quote! {}, vec![]), - } -} - -pub fn rmc_generate_serialize_enum( - enum_data: &DataEnum, - repr_ty: &Ident, -) -> proc_macro2::TokenStream { - let match_content = fold_tokenable(enum_data.variants.iter().map(|v|{ - let ident = &v.ident; - let descriminant = &v.discriminant.as_ref().expect("every variant must have a descriminant to be a valid rmc struct").1; - let (pattern, fields) = variant_to_pattern_and_fields(v); - let inner = fold_tokenable(fields.iter().enumerate().map(|(i, f)|{ - let ty = &f.ty; - let name = field_to_ident(&f, i); - quote! {<#ty as rnex_core::rmc::structures::RmcSerialize>::serialize(#name, writer)?;} - })); - quote!{ - Self::#ident #pattern => { - <#repr_ty as rnex_core::rmc::structures::RmcSerialize>::serialize(&#descriminant, writer)?; - #inner - } - } - })); - quote! { - match self{ - #match_content - } - Ok(()) - } -} -pub fn rmc_generate_deserialize_enum( - enum_data: &DataEnum, - repr_ty: &Ident, -) -> proc_macro2::TokenStream { - let match_content = fold_tokenable(enum_data.variants.iter().map(|v| { - let ident = &v.ident; - let descriminant = &v - .discriminant - .as_ref() - .expect("every variant must have a descriminant to be a valid rmc struct") - .1; - let (pattern, fields) = variant_to_pattern_and_fields(v); - let inner = fold_tokenable(fields.iter().enumerate().map(|(i, f)| { - let ty = &f.ty; - let name = field_to_ident(&f, i); - quote! {let #name = <#ty as rnex_core::rmc::structures::RmcSerialize>::deserialize(reader)?;} - })); - quote! { - #descriminant => { - #inner - - Self::#ident #pattern - } - } - })); - - quote! { - let discriminant = <#repr_ty as rnex_core::rmc::structures::RmcSerialize>::deserialize(reader)?; - - Ok(match discriminant{ - #match_content - v => { - return Err(rnex_core::rmc::structures::Error::UnexpectedValue(v as u64)) - } - }) - } -} - -pub fn rmc_serialize_enum( - enum_data: &DataEnum, - derive_input: &DeriveInput, -) -> ( - proc_macro2::TokenStream, - proc_macro2::TokenStream, - Option, - Option, -) { - let repr_attr = derive_input.attrs.iter().find(|a| { - a.path().segments.len() == 1 - && a.path() - .segments - .first() - .is_some_and(|p| p.ident.to_string() == "repr") - }); - let Some(repr_attr) = repr_attr else { - panic!("missing repr attribute"); - }; - - let ty: Ident = repr_attr.parse_args().unwrap(); - - let serialize = rmc_generate_serialize_enum(&enum_data, &ty); - let deserialize = rmc_generate_deserialize_enum(&enum_data, &ty); - - (serialize, deserialize, None, None) -} diff --git a/macros/src/util.rs b/macros/src/util.rs deleted file mode 100644 index 133f650..0000000 --- a/macros/src/util.rs +++ /dev/null @@ -1,10 +0,0 @@ -use proc_macro2::TokenStream; -use quote::ToTokens; - -// todo: return a wrapper struct implementing ToTokens over the iterator instead as to avoid unnescesary allocations with the token stream -pub fn fold_tokenable(list: impl Iterator) -> TokenStream { - list.fold(TokenStream::new(), |mut s, i| { - i.to_tokens(&mut s); - s - }) -} diff --git a/proxy-common/Cargo.toml b/proxy-common/Cargo.toml deleted file mode 100644 index bd13ffa..0000000 --- a/proxy-common/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "proxy-common" -version = "0.1.0" -edition = "2024" - -[dependencies] -thiserror = "2.0.12" -rnex-core = { path = "../rnex-core", version = "0.1.1" } -tokio = { version = "1.47.0", features = ["full"] } -log = "0.4.25" -hex = "0.4.3" diff --git a/proxy-common/src/lib.rs b/proxy-common/src/lib.rs deleted file mode 100644 index f614de1..0000000 --- a/proxy-common/src/lib.rs +++ /dev/null @@ -1,218 +0,0 @@ -use log::{error, info}; -use rnex_core::{ - PID, - executables::common::try_get_ip, - prudp::{socket_addr::PRUDPSockAddr, virtual_port::VirtualPort}, - reggie::{RemoteEdgeNodeHolder, UnitPacketWrite}, - rmc::{ - protocols::{ - RemoteDisconnectable, RmcCallable, RmcConnection, RmcPureRemoteObject, - new_rmc_gateway_connection, - }, - structures::RmcSerialize, - }, - rnex_proxy_common::ConnectionInitData, - util::{SendingBufferConnection, SplittableBufferConnection}, -}; -use std::{ - env::{self, VarError}, - error, - net::{AddrParseError, Ipv4Addr, SocketAddr, SocketAddrV4}, - ops::Deref, - panic, - str::FromStr, - sync::{Arc, LazyLock}, -}; -use thiserror::Error; -use tokio::net::TcpStream; - -const RNEX_DEFAULT_PORT: u16 = match u16::from_str_radix(env!("RNEX_DEFAULT_PORT"), 10) { - Ok(v) => v, - Err(_) => panic!("unable to get default port from env"), -}; - -pub const RNEX_ACCESS_KEY: &'static str = env!("RNEX_ACCESS_KEY"); - -#[derive(Error, Debug)] -pub enum Error { - #[error("error getting environment variable \"{0}\": {1}")] - UnableToGetEnv(&'static str, VarError), - #[error("error parsing ip address environment variable \"{0}\": {1}")] - AddrParse(&'static str, AddrParseError), - #[error( - "error error getting public ip address: \n\tattempted to read from env var \"SERVER_IP_PUBLIC\" and got: {0} \n\tattempted to request from internet and failed with: {1}" - )] - PubAddrGetErr(Box, Box), -} -impl Into for (&'static str, AddrParseError) { - fn into(self) -> Error { - Error::AddrParse(self.0, self.1) - } -} - -pub struct ProxyStartupParam { - pub forward_destination: SocketAddr, - pub edge_node_holder: SocketAddr, - pub self_public: SocketAddrV4, - pub self_private: SocketAddrV4, - pub virtual_port: VirtualPort, -} - -fn try_get_env(name: &'static str) -> Result -where - (&'static str, T::Err): Into, -{ - T::from_str(&env::var(name).map_err(|e| Error::UnableToGetEnv(name, e))?) - .map_err(|e| (name, e).into()) -} - -pub enum ProxyType { - Insecure, - Secure, -} -const VIRTUAL_PORT_INSECURE: LazyLock = - LazyLock::new(|| VirtualPort::parse(env!("RNEX_VIRTUAL_PORT_INSECURE")).unwrap()); -const VIRTUAL_PORT_SECURE: LazyLock = - LazyLock::new(|| VirtualPort::parse(env!("RNEX_VIRTUAL_PORT_SECURE")).unwrap()); -impl ProxyStartupParam { - #[inline(always)] - pub fn new(prox_ty: ProxyType) -> Result { - let port = RNEX_DEFAULT_PORT - + match prox_ty { - ProxyType::Insecure => 0, - ProxyType::Secure => 1, - }; - let self_private = try_get_env("SERVER_IP_PRIVATE") - .unwrap_or(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, port)); - let self_public: SocketAddrV4 = match try_get_env("SERVER_IP_PUBLIC") { - Ok(v) => v, - Err(e) => try_get_ip() - .map(|v| SocketAddrV4::new(v, self_private.port())) - .map_err(move |v| Error::PubAddrGetErr(Box::new(e), v))?, - }; - - Ok(Self { - forward_destination: try_get_env("FORWARD_DESTINATION")?, - edge_node_holder: try_get_env("EDGE_NODE_HOLDER")?, - self_private, - self_public, - virtual_port: match prox_ty { - ProxyType::Insecure => *VIRTUAL_PORT_INSECURE, - ProxyType::Secure => *VIRTUAL_PORT_SECURE, - }, - }) - } -} - -struct OnRemoteDrop(T, Option); -impl Deref for OnRemoteDrop { - type Target = T; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -// if we had something like a thread safe OnceConsume (basically the opposite of OnceLock) -// we could make C be an FnOnce -impl - OnRemoteDrop -{ - pub fn new(conn: RmcConnection, drop_func: C) -> Self { - Self(T::new(conn), Some(drop_func)) - } - - #[allow(dead_code)] - pub async fn disconnect(&self) { - self.0.disconnect().await; - } -} - -impl RmcCallable - for OnRemoteDrop -{ - fn rmc_call( - &self, - _responder: &SendingBufferConnection, - _protocol_id: u16, - _method_id: u32, - _call_id: u32, - _rest: Vec, - ) -> impl Future + Send { - // maybe respond with not implemented or something - async {} - } -} - -impl Drop for OnRemoteDrop { - fn drop(&mut self) { - self.1.take().unwrap()(); - } -} - -pub async fn setup_edge_node_connection( - param: &ProxyStartupParam, - shutdown_callback: impl FnOnce() + Send + Sync + 'static, -) { - let conn = tokio::net::TcpStream::connect(¶m.edge_node_holder) - .await - .unwrap(); - - let conn: SplittableBufferConnection = conn.into(); - - conn.send( - rnex_core::reggie::EdgeNodeHolderConnectOption::Register(param.self_public) - .to_data() - .unwrap(), - ) - .await; - - println!("{:?}", param.self_public); - //leave the inner object floating so that it gets destroyed once we disconnect - new_rmc_gateway_connection(conn, move |r| { - Arc::new(OnRemoteDrop::::new( - r, - shutdown_callback, - )) - }); -} - -pub async fn new_backend_connection( - param: &ProxyStartupParam, - addr: PRUDPSockAddr, - pid: PID, -) -> Option { - info!("attempting to connect to: {}", param.forward_destination); - let mut stream = match TcpStream::connect(param.forward_destination).await { - Ok(v) => v, - Err(e) => { - error!("unable to establish connection to backend: {}", e); - return None; - } - }; - - let data = ConnectionInitData { - prudpsock_addr: addr, - pid: pid, - } - .to_data() - .unwrap(); - - if let Err(e) = stream.send_buffer(&data).await { - error!("unable to send establishment data to backend: {}", e); - return None; - }; - - Some(stream.into()) -} - -#[cfg(test)] -mod test { - use crate::{VIRTUAL_PORT_INSECURE, VIRTUAL_PORT_SECURE}; - - #[test] - fn test_virtual_port_correct() { - println!("{:?}", VIRTUAL_PORT_INSECURE); - println!("{:?}", VIRTUAL_PORT_SECURE); - } -} diff --git a/proxy/Cargo.toml b/proxy/Cargo.toml deleted file mode 100644 index 98e8b2b..0000000 --- a/proxy/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -name = "proxy" -version = "0.1.0" -edition = "2024" - -[dependencies] -tokio = { version = "1.47.0", features = ["full"] } -prudpv0 = { path = "../prudpv0", optional = true } -prudpv1 = { path = "../prudpv1", optional = true } -prudplite = { path = "../prudplite", optional = true } -proxy-common = { path = "../proxy-common" } -cfg-if = "1.0.4" -rnex-core = { path = "../rnex-core", version = "0.1.1" } -log = "0.4.25" - -[features] -prudpv0 = ["dep:prudpv0"] -prudpv1 = ["dep:prudpv1"] -prudplite = ["dep:prudplite"] -friends = ["prudpv0", "prudpv0/friends"] -splatoon = ["prudpv1"] - - -[[bin]] -name = "proxy_insecure" -path = "src/insecure.rs" - -[[bin]] -name = "proxy_secure" -path = "src/secure.rs" diff --git a/proxy/src/insecure.rs b/proxy/src/insecure.rs deleted file mode 100644 index 1451a64..0000000 --- a/proxy/src/insecure.rs +++ /dev/null @@ -1,15 +0,0 @@ -use proxy::edge_node_dc_callback; -use proxy_common::{ProxyStartupParam, setup_edge_node_connection}; -use rnex_core::common::setup; - -#[tokio::main] -async fn main() { - setup(); - - let param = ProxyStartupParam::new(proxy_common::ProxyType::Insecure) - .expect("unable to get startup parameters"); - - setup_edge_node_connection(¶m, edge_node_dc_callback).await; - - proxy::start_insecure(param).await; -} diff --git a/proxy/src/lib.rs b/proxy/src/lib.rs deleted file mode 100644 index ea5b02c..0000000 --- a/proxy/src/lib.rs +++ /dev/null @@ -1,21 +0,0 @@ -use std::process::abort; - -use cfg_if::cfg_if; -use log::error; - -cfg_if! { - if #[cfg(feature = "prudpv0")]{ - pub use prudpv0::*; - } else if #[cfg(feature = "prudpv1")] { - pub use prudpv1::*; - } else if #[cfg(feature = "prudplite")]{ - pub use prudplite::*; - } else { - compile_error!("no proxy type has been set"); - } -} - -pub fn edge_node_dc_callback() { - error!("disconnected from node holder, aborting!"); - abort() -} diff --git a/proxy/src/secure.rs b/proxy/src/secure.rs deleted file mode 100644 index 6d42c87..0000000 --- a/proxy/src/secure.rs +++ /dev/null @@ -1,14 +0,0 @@ -use proxy::edge_node_dc_callback; -use proxy_common::{ProxyStartupParam, setup_edge_node_connection}; -use rnex_core::common::setup; - -#[tokio::main] -async fn main() { - setup(); - - let param = ProxyStartupParam::new(proxy_common::ProxyType::Secure) - .expect("unable to get startup parameters"); - - setup_edge_node_connection(¶m, edge_node_dc_callback).await; - proxy::start_secure(param).await; -} diff --git a/prudplite/Cargo.toml b/prudplite/Cargo.toml deleted file mode 100644 index 902b1a7..0000000 --- a/prudplite/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "prudplite" -version = "0.1.0" -edition = "2024" - -[features] -nx = [] -v4-3-11 = [] - -[dependencies] -rnex-core = { path = "../rnex-core", version = "0.1.1" } -tokio = { version = "1.47.0", features = ["full"] } -bytemuck = { version = "1.23.1", features = ["derive"] } -proxy-common = {path = "../proxy-common"} -tokio-tungstenite = {version = "0.28.0", features = ["rustls", "rustls-tls-native-roots"]} -log = "0.4.25" -futures-util = "0.3.31" -v-byte-helpers = { git = "https://github.com/RusticMaple/VByteMacros", version = "0.1.1" } diff --git a/prudplite/src/crypto/insecure.rs b/prudplite/src/crypto/insecure.rs deleted file mode 100644 index a1beaf2..0000000 --- a/prudplite/src/crypto/insecure.rs +++ /dev/null @@ -1,14 +0,0 @@ -use rnex_core::PID; - -use crate::crypto::Crypto; - -pub struct Insecure; - -impl Crypto for Insecure { - fn new_connection(&self, _data: &[u8]) -> Option<(PID, Vec)> { - Some((100, vec![])) - } - fn new() -> Self { - Self - } -} diff --git a/prudplite/src/crypto/mod.rs b/prudplite/src/crypto/mod.rs deleted file mode 100644 index 38d8091..0000000 --- a/prudplite/src/crypto/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -use rnex_core::PID; - -pub mod insecure; -pub mod secure; - -pub trait Crypto: 'static + Send + Sync { - fn new_connection(&self, data: &[u8]) -> Option<(PID, Vec)>; - fn new() -> Self; -} diff --git a/prudplite/src/crypto/secure.rs b/prudplite/src/crypto/secure.rs deleted file mode 100644 index 4aff759..0000000 --- a/prudplite/src/crypto/secure.rs +++ /dev/null @@ -1,27 +0,0 @@ -use rnex_core::{ - PID, executables::common::SECURE_SERVER_ACCOUNT, nex::account::Account, - prudp::ticket::read_secure_connection_data, rmc::structures::RmcSerialize, -}; - -use crate::crypto::Crypto; - -pub struct Secure(&'static Account); - -impl Crypto for Secure { - fn new_connection(&self, data: &[u8]) -> Option<(PID, Vec)> { - let (_, pid, check_value) = read_secure_connection_data(data, &self.0)?; - - let check_value_response = check_value + 1; - - let data = bytemuck::bytes_of(&check_value_response); - - let mut response = Vec::new(); - - data.serialize(&mut response).ok()?; - - Some((pid, response)) - } - fn new() -> Self { - Self(&SECURE_SERVER_ACCOUNT) - } -} diff --git a/prudplite/src/executable.rs b/prudplite/src/executable.rs deleted file mode 100644 index b4d8a0e..0000000 --- a/prudplite/src/executable.rs +++ /dev/null @@ -1,45 +0,0 @@ -use futures_util::{SinkExt, StreamExt}; -use rnex_core::prudp::types_flags::{TypesFlags, flags::NEED_ACK, types::SYN}; -use tokio_tungstenite::tungstenite::{Message, client::IntoClientRequest, http::header}; - -use crate::packet::{LiteHeader, LitePacket, PacketSpecificData, StreamTypes, create_packet_from}; - -mod packet; - -const KEY: &str = "4eb18d39"; - -const URL: &str = "wss://g2DF33D01-lp1.s.n.srv.nintendo.net"; -#[tokio::main] -async fn main() { - let login = URL.into_client_request().unwrap(); - let (mut stream, response) = tokio_tungstenite::connect_async(login).await.unwrap(); - - println!("response: {:?}", response); - - let packet = create_packet_from( - LiteHeader { - stream_types: StreamTypes::new(10, 10), - source_port: 1, - destination_port: 1, - fragment_id: 0, - types_flags: TypesFlags::default().types(SYN).flags(NEED_ACK), - sequence_id: 0, - ..Default::default() - }, - &[PacketSpecificData::SupportedFunctions(0x8)], - &[], - ); - - println!("sending ack"); - stream.send(Message::Binary(packet.into())).await.unwrap(); - println!("waiting for response"); - let packet = stream.next().await.unwrap(); - let Message::Binary(packet) = packet.unwrap() else { - panic!() - }; - let packet = LitePacket::new(packet); - - let header = packet.header().unwrap(); - - println!("{:?}", header); -} diff --git a/prudplite/src/lib.rs b/prudplite/src/lib.rs deleted file mode 100644 index 0df7b2e..0000000 --- a/prudplite/src/lib.rs +++ /dev/null @@ -1,316 +0,0 @@ -pub mod crypto; -mod packet; - -use std::{collections::HashMap, net::SocketAddr, sync::Arc}; - -use crate::{ - crypto::{Crypto, insecure::Insecure, secure::Secure}, - packet::{LiteHeader, LitePacket, PacketSpecificData, StreamTypes, create_packet_from}, -}; -use futures_util::{SinkExt, StreamExt}; -use log::{error, info, warn}; -use proxy_common::{ProxyStartupParam, new_backend_connection}; -use rnex_core::{ - PID, - prudp::{ - socket_addr::PRUDPSockAddr, - types_flags::{ - TypesFlags, - flags::{ACK, NEED_ACK, RELIABLE}, - types::{CONNECT, DATA, DISCONNECT, PING, SYN}, - }, - virtual_port::VirtualPort, - }, - util::SplittableBufferConnection, -}; -use tokio::net::{TcpListener, TcpStream}; -use tokio_tungstenite::{ - WebSocketStream, - tungstenite::{Bytes, Message}, -}; - -struct ConnectionState { - param: Arc, - active: bool, - websocket: WebSocketStream, - #[allow(dead_code)] - pid: PID, - backend_conn: SplittableBufferConnection, - addr: PRUDPSockAddr, - incoming_reliable: HashMap>, - client_reliable_counter: u16, - #[allow(dead_code)] - server_reliable_counter: u16, -} - -impl ConnectionState { - pub async fn handle_incoming_prudp(&mut self, packet: LitePacket, sorted: bool) { - let Some(header) = packet.header() else { - warn!("invalid data on connection"); - return; - }; - - if (header.types_flags.get_flags() & NEED_ACK) != 0 { - let data = create_packet_from( - LiteHeader { - stream_types: StreamTypes::new( - self.param.virtual_port.get_stream_type(), - self.addr.virtual_port.get_stream_type(), - ), - source_port: self.param.virtual_port.get_port_number(), - destination_port: self.addr.virtual_port.get_port_number(), - fragment_id: header.fragment_id, - types_flags: TypesFlags::default() - .types(header.types_flags.get_types()) - .flags(ACK), - sequence_id: header.sequence_id, - ..Default::default() - }, - &[], - &[], - ); - let data: Bytes = data.into(); - if header.types_flags.get_types() == DISCONNECT { - self.websocket - .send(Message::Binary(data.clone())) - .await - .ok(); - self.websocket - .send(Message::Binary(data.clone())) - .await - .ok(); - } - self.websocket.send(Message::Binary(data)).await.ok(); - } - - if (header.types_flags.get_flags() & ACK) != 0 { - // we can just safely ignore acks, we ARE sending over tcp after all already guarantees that our packets will arrive - // we can however not guarantee the order of incoming client packets so we should still take care of that - // (the client might be doing some funny things which we dont know of) - return; - } - - if (header.types_flags.get_flags() & RELIABLE != 0) & !sorted { - self.incoming_reliable.insert(header.sequence_id, packet); - if self.incoming_reliable.len() > 5 { - self.active = false; - warn!("client is spamming out of order reliable packets, throwing out"); - } - return; - } - - match header.types_flags.get_types() { - DATA => { - if header.fragment_id != 0 { - warn!("fragmented packets arent yet supported"); - return; - } - - let Some(payload) = packet.payload() else { - return; - }; - self.backend_conn.send(payload.into()).await; - } - PING => {} - v => { - info!("unimplemented packet type: {}", v); - } - } - } - #[allow(dead_code)] - pub async fn process_reliable(&mut self) { - while let Some(v) = self.incoming_reliable.remove(&self.client_reliable_counter) { - self.handle_incoming_prudp(v, true).await; - self.client_reliable_counter += 1; - } - } - pub async fn handle_connection(&mut self) { - while self.active { - tokio::select! { - v = self.websocket.next() => { - match v { - Some(Ok(Message::Binary(v))) => { - self.handle_incoming_prudp(LitePacket::new(v), false).await; - } - _ => { - info!("client disconnected or errored out"); - return; - } - } - } - _ = self.backend_conn.recv() => { - - } - } - } - } -} - -pub async fn websocket_thread_unconnected( - param: Arc, - crypto: Arc, - conn: TcpStream, - addr: SocketAddr, -) { - let mut websocket = match tokio_tungstenite::accept_async(conn).await { - Ok(v) => v, - Err(e) => { - error!("error accepting websocket connection: {}", e); - return; - } - }; - - while let Some(Ok(v)) = websocket.next().await { - match v { - Message::Binary(b) => { - let packet = LitePacket::new(b); - - let Some(header) = packet.header() else { - error!("got malformed message, disconnecting"); - return; - }; - - match header.types_flags.get_types() { - SYN => { - let Some(supported) = packet.packet_specific_iter() else { - error!("got malformed message, disconnecting"); - return; - }; - - let Some(PacketSpecificData::SupportedFunctions(s)) = supported - .into_iter() - .find(|v| matches!(v, PacketSpecificData::SupportedFunctions(_))) - else { - error!("got malformed message, disconnecting"); - return; - }; - - let data = create_packet_from( - LiteHeader { - destination_port: header.source_port, - source_port: param.virtual_port.get_port_number(), - stream_types: StreamTypes::new( - param.virtual_port.get_stream_type(), - header.stream_types.source(), - ), - fragment_id: 0, - sequence_id: 0, - types_flags: TypesFlags::default().types(SYN).flags(ACK), - ..Default::default() - }, - &[ - PacketSpecificData::SupportedFunctions(s & 0xFF), - PacketSpecificData::ConnectionSignature([0; 16]), - ], - &[], - ); - websocket.send(Message::Binary(data.into())).await.ok(); - } - CONNECT => { - let Some(supported) = packet.packet_specific_iter() else { - error!("got malformed message, disconnecting"); - return; - }; - - let Some(PacketSpecificData::SupportedFunctions(s)) = supported - .into_iter() - .find(|v| matches!(v, PacketSpecificData::SupportedFunctions(_))) - else { - error!("got malformed message, disconnecting"); - return; - }; - - let Some(data) = packet.payload() else { - error!("got malformed message, disconnecting"); - return; - }; - - let Some((pid, data)) = crypto.new_connection(data) else { - error!("invalid login data"); - return; - }; - - let data = create_packet_from( - LiteHeader { - destination_port: header.source_port, - source_port: param.virtual_port.get_port_number(), - stream_types: StreamTypes::new( - param.virtual_port.get_stream_type(), - header.stream_types.source(), - ), - fragment_id: 0, - sequence_id: 0, - types_flags: TypesFlags::default().types(CONNECT).flags(ACK), - ..Default::default() - }, - &[ - PacketSpecificData::SupportedFunctions(s & 0xFF), - PacketSpecificData::ConnectionSignature([0; 16]), - ], - &data, - ); - websocket.send(Message::Binary(data.into())).await.ok(); - - let addr = PRUDPSockAddr::new( - addr, - VirtualPort::new(header.source_port, header.stream_types.source()), - ); - let Some(backend_conn) = new_backend_connection(¶m, addr, pid).await - else { - error!("unable to connect to backend"); - return; - }; - let mut connection = ConnectionState { - active: true, - addr, - pid, - backend_conn, - client_reliable_counter: 2, - server_reliable_counter: 1, - param, - incoming_reliable: HashMap::new(), - websocket, - }; - - connection.handle_connection().await; - break; - } - v => { - error!( - "invalid packet type for unconnected client {}, disconnecting", - v, - ); - } - } - } - v => { - error!("non binary message({:?}) , disconnecting", v); - return; - } - } - } -} - -pub async fn start_proxy(param: ProxyStartupParam) { - let param = Arc::new(param); - let crypto = Arc::new(C::new()); - let listener = TcpListener::bind(param.self_private) - .await - .expect("unable to bind to port"); - - while let Ok((connection, addr)) = listener.accept().await { - let param = param.clone(); - let crypto = crypto.clone(); - tokio::spawn(websocket_thread_unconnected( - param, crypto, connection, addr, - )); - } -} - -pub async fn start_secure(param: ProxyStartupParam) { - start_proxy::(param).await; -} - -pub async fn start_insecure(param: ProxyStartupParam) { - start_proxy::(param).await; -} diff --git a/prudplite/src/packet.rs b/prudplite/src/packet.rs deleted file mode 100644 index e75750b..0000000 --- a/prudplite/src/packet.rs +++ /dev/null @@ -1,222 +0,0 @@ -use std::{ - fmt::Debug, - io::{self, Cursor, Read, Write}, -}; - -use bytemuck::{Pod, Zeroable, bytes_of_mut}; -use rnex_core::prudp::types_flags::TypesFlags; -use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions}; - -#[derive(Pod, Zeroable, Copy, Clone, Default, Debug)] -#[repr(C)] -pub struct LiteHeader { - pub magic: u8, - pub packet_specific_length: u8, - pub payload_size: u16, - pub stream_types: StreamTypes, - pub source_port: u8, - pub destination_port: u8, - pub fragment_id: u8, - pub types_flags: TypesFlags, - pub sequence_id: u16, -} - -pub enum PacketSpecificData { - SupportedFunctions(u32), - ConnectionSignature([u8; 16]), - LiteSignature([u8; 16]), -} - -impl PacketSpecificData { - fn consume(reader: &mut impl Read) -> io::Result { - let mut option_id = 0u8; - reader.read_exact(bytes_of_mut(&mut option_id))?; - let mut size = 0u8; - reader.read_exact(bytes_of_mut(&mut size))?; - - match option_id { - 0 => { - if size != 4 { - Err(io::Error::other( - "invalid option size for supported functions", - )) - } else { - Ok(Self::SupportedFunctions(reader.read_le_u32()?)) - } - } - 1 => { - if size != 16 { - Err(io::Error::other( - "invalid option size for connection signature", - )) - } else { - Ok(Self::ConnectionSignature( - reader.read_struct(IS_BIG_ENDIAN)?, - )) - } - } - 0x80 => { - if size != 16 { - Err(io::Error::other("invalid option size for lite signature")) - } else { - Ok(Self::LiteSignature(reader.read_struct(IS_BIG_ENDIAN)?)) - } - } - _ => Err(io::Error::other("invalid option id")), - } - } - - fn write_size(&self) -> usize { - 2 + match self { - PacketSpecificData::SupportedFunctions(_) => 4, - Self::ConnectionSignature(_) => 16, - Self::LiteSignature(_) => 16, - } - } - - fn write_self(&self, writer: &mut impl Write) -> io::Result<()> { - match self { - PacketSpecificData::SupportedFunctions(v) => { - writer.write_all(&[0, 4])?; - writer.write_all(&v.to_le_bytes())?; - } - Self::ConnectionSignature(v) => { - writer.write_all(&[1, 16])?; - writer.write_all(&v[..])?; - } - Self::LiteSignature(v) => { - writer.write_all(&[0x80, 16])?; - writer.write_all(&v[..])?; - } - } - - Ok(()) - } -} - -pub struct LitePacket>(T); - -pub struct PacketSpecificIter<'a>(Cursor<&'a [u8]>); - -impl<'a> Iterator for PacketSpecificIter<'a> { - type Item = PacketSpecificData; - - fn next(&mut self) -> Option { - PacketSpecificData::consume(&mut self.0).ok() - } -} - -impl> LitePacket { - pub fn new(inner: T) -> Self { - Self(inner) - } - - pub fn header(&self) -> Option<&LiteHeader> { - bytemuck::try_from_bytes(self.0.as_ref().get(..size_of::())?).ok() - } - pub fn header_mut(&mut self) -> Option<&mut LiteHeader> - where - T: AsMut<[u8]>, - { - bytemuck::try_from_bytes_mut(self.0.as_mut().get_mut(..size_of::())?).ok() - } - - pub fn payload(&self) -> Option<&[u8]> { - let header = self.header()?; - self.0 - .as_ref() - .get(size_of::() + header.packet_specific_length as usize..) - } - - pub fn payload_mut(&mut self) -> Option<&mut [u8]> - where - T: AsMut<[u8]>, - { - let len = self.header()?.packet_specific_length; - self.0 - .as_mut() - .get_mut(size_of::() + len as usize..) - } - - pub fn packet_specific_raw(&self) -> Option<&[u8]> { - let header = self.header()?; - self.0.as_ref().get( - size_of::() - ..size_of::() + header.packet_specific_length as usize, - ) - } - pub fn packet_specific_raw_mut(&mut self) -> Option<&mut [u8]> - where - T: AsMut<[u8]>, - { - let len = self.header()?.packet_specific_length; - self.0 - .as_mut() - .get_mut(size_of::()..size_of::() + len as usize) - } - - pub fn packet_specific_iter<'a>(&'a self) -> Option> { - self.packet_specific_raw() - .map(Cursor::new) - .map(PacketSpecificIter) - } -} - -pub fn create_packet_from( - header: LiteHeader, - specific_data: &[PacketSpecificData], - data: &[u8], -) -> Vec { - let specific_size: usize = specific_data.iter().map(|v| v.write_size()).sum(); - let mut packet = LitePacket::new(vec![ - 0u8; - size_of::() + specific_size + data.len() - ]); - - *packet.header_mut().expect("packet malformed in creation") = LiteHeader { - magic: 0x80, - packet_specific_length: specific_size as u8, - payload_size: data.len() as u16, - ..header - }; - - let mut cursor = Cursor::new( - packet - .packet_specific_raw_mut() - .expect("packet malformed in creation"), - ); - - for specific in specific_data { - specific.write_self(&mut cursor).unwrap(); - } - - packet - .payload_mut() - .expect("packet malformed in creation") - .copy_from_slice(data); - - packet.0 -} - -#[derive(Pod, Zeroable, Copy, Clone, Default)] -#[repr(transparent)] -pub struct StreamTypes(u8); - -impl Debug for StreamTypes { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "({},{})", self.source(), self.destination()) - } -} - -impl StreamTypes { - pub fn new(source_stream: u8, dest_stream: u8) -> Self { - Self((source_stream & 0xF << 4) & dest_stream & 0xF) - } - - pub fn source(&self) -> u8 { - self.0 >> 4 - } - pub fn destination(&self) -> u8 { - self.0 & 0xF - } -} diff --git a/prudpv0/Cargo.toml b/prudpv0/Cargo.toml deleted file mode 100644 index 447436d..0000000 --- a/prudpv0/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "prudpv0" -version = "0.1.0" -edition = "2024" - -[dependencies] -rnex-core = { path = "../rnex-core", version = "0.1.1" } -tokio = { version = "1.47.0", features = ["full"] } -bytemuck = { version = "1.23.1", features = ["derive"] } -typenum = "1.18.0" -rc4 = "0.1.0" -log = "0.4.25" -cfg-if = "1.0.4" -proxy-common = {path = "../proxy-common"} -hmac = "0.12.1" -md-5 = "^0.10.6" - -[features] -prudpv0 = [] -friends = ["prudpv0"] diff --git a/prudpv0/src/crypto/common_crypto.rs b/prudpv0/src/crypto/common_crypto.rs deleted file mode 100644 index 7196638..0000000 --- a/prudpv0/src/crypto/common_crypto.rs +++ /dev/null @@ -1,54 +0,0 @@ -trait IterExtra: Iterator { - fn sum_wrapping_u8(&mut self) -> u8 - where - Self::Item: Into; - - fn sum_wrapping_u32(&mut self) -> u32 - where - Self::Item: Into; -} - -impl IterExtra for T { - fn sum_wrapping_u8(&mut self) -> u8 - where - Self::Item: Into, - { - let mut sum = 0u8; - for v in self { - let val: u8 = v.into(); - sum = sum.wrapping_add(val); - } - sum - } - fn sum_wrapping_u32(&mut self) -> u32 - where - Self::Item: Into, - { - let mut sum = 0u32; - for v in self { - let val: u32 = v.into(); - sum = sum.wrapping_add(val); - } - sum - } -} - -#[inline(always)] -pub fn common_checksum(access_key: &str, data: &[u8]) -> u8 { - let leftover = data.len() % 4; - let word_sum = bytemuck::cast_slice::<_, u32>(&data[..data.len() - leftover]) - .iter() - .copied() - .sum_wrapping_u32(); - - let checksum = access_key.as_bytes().iter().copied().sum_wrapping_u8(); - let checksum = checksum.wrapping_add( - (&data[data.len() - leftover..]) - .iter() - .copied() - .sum_wrapping_u8(), - ); - let checksum = checksum.wrapping_add(word_sum.to_ne_bytes().into_iter().sum_wrapping_u8()); - - checksum -} diff --git a/prudpv0/src/crypto/friends_common.rs b/prudpv0/src/crypto/friends_common.rs deleted file mode 100644 index a8f1629..0000000 --- a/prudpv0/src/crypto/friends_common.rs +++ /dev/null @@ -1,6 +0,0 @@ -use hmac::Hmac; -use md5::Md5; -use proxy_common::RNEX_ACCESS_KEY; - -pub const ACCESS_KEY: &str = RNEX_ACCESS_KEY; -pub type HmacMd5 = Hmac; diff --git a/prudpv0/src/crypto/friends_insecure.rs b/prudpv0/src/crypto/friends_insecure.rs deleted file mode 100644 index ead738a..0000000 --- a/prudpv0/src/crypto/friends_insecure.rs +++ /dev/null @@ -1,79 +0,0 @@ -use std::io::Write; - -use hmac::Mac; -use md5::{Digest, Md5}; -use rc4::{KeyInit, Rc4, StreamCipher}; -use rnex_core::prudp::{ - encryption::{DEFAULT_KEY, EncryptionPair}, - types_flags::{TypesFlags, types::DATA}, -}; -use typenum::U5; - -use crate::crypto::{ - Crypto, CryptoInstance, - common_crypto::common_checksum, - friends_common::{ACCESS_KEY, HmacMd5}, -}; - -pub struct InsecureInstance { - pair: EncryptionPair>, - self_signat: [u8; 4], - #[allow(dead_code)] - remote_signat: [u8; 4], -} - -impl CryptoInstance for InsecureInstance { - fn decrypt_incoming(&mut self, data: &mut [u8]) { - self.pair.recv.apply_keystream(data); - } - fn encrypt_outgoing(&mut self, data: &mut [u8]) { - self.pair.send.apply_keystream(data); - } - fn get_user_id(&self) -> u32 { - 0 - } - fn generate_signature(&self, types_flags: TypesFlags, data: &[u8]) -> [u8; 4] { - if types_flags.get_types() == DATA { - if data.len() == 0 { - [0x78, 0x56, 0x34, 0x12] - } else { - let mut hash = Md5::new(); - hash.write(ACCESS_KEY.as_bytes()).unwrap(); - let mut hmac = ::new_from_slice(&hash.finalize().as_slice()) - .expect("unable to create hmac md5"); - hmac.update(data); - hmac.finalize().into_bytes()[0..4].try_into().unwrap() - } - } else { - self.self_signat - } - } -} - -pub struct Insecure(); - -impl Crypto for Insecure { - type Instance = InsecureInstance; - fn new() -> Self { - Self() - } - fn calculate_checksum(&self, data: &[u8]) -> u8 { - common_checksum(ACCESS_KEY, data) - } - - fn instantiate( - &self, - _packet_data: &[u8], - self_signat: [u8; 4], - remote_signat: [u8; 4], - ) -> Option<(Self::Instance, Vec)> { - Some(( - InsecureInstance { - pair: EncryptionPair::init_both(|| Rc4::new(&DEFAULT_KEY)), - self_signat, - remote_signat, - }, - vec![], - )) - } -} diff --git a/prudpv0/src/crypto/friends_secure.rs b/prudpv0/src/crypto/friends_secure.rs deleted file mode 100644 index 14bdf7c..0000000 --- a/prudpv0/src/crypto/friends_secure.rs +++ /dev/null @@ -1,97 +0,0 @@ -use hmac::Mac; -use md5::{Digest, Md5}; -use rc4::{KeyInit, Rc4, StreamCipher}; -use rnex_core::{ - executables::common::SECURE_SERVER_ACCOUNT, - nex::account::Account, - prudp::{ - encryption::EncryptionPair, - ticket::read_secure_connection_data, - types_flags::{TypesFlags, types::DATA}, - }, - rmc::structures::RmcSerialize, -}; -use std::io::Write; -use typenum::U16; - -use crate::crypto::{ - Crypto, CryptoInstance, - common_crypto::common_checksum, - friends_common::{ACCESS_KEY, HmacMd5}, -}; - -pub struct SecureInstance { - pair: EncryptionPair>, - uid: u32, - self_signat: [u8; 4], - #[allow(dead_code)] - remote_signat: [u8; 4], -} - -impl CryptoInstance for SecureInstance { - fn decrypt_incoming(&mut self, data: &mut [u8]) { - self.pair.recv.apply_keystream(data); - } - fn encrypt_outgoing(&mut self, data: &mut [u8]) { - self.pair.send.apply_keystream(data); - } - fn get_user_id(&self) -> u32 { - self.uid - } - fn generate_signature(&self, types_flags: TypesFlags, data: &[u8]) -> [u8; 4] { - if types_flags.get_types() == DATA { - if data.len() == 0 { - [0x78, 0x56, 0x34, 0x12] - } else { - let mut hash = Md5::new(); - hash.write(ACCESS_KEY.as_bytes()).unwrap(); - let mut hmac = ::new_from_slice(&hash.finalize().as_slice()) - .expect("unable to create hmac md5"); - hmac.update(data); - hmac.finalize().into_bytes()[0..4].try_into().unwrap() - } - } else { - self.self_signat - } - } -} - -pub struct Secure(&'static Account); - -impl Crypto for Secure { - type Instance = SecureInstance; - fn new() -> Self { - Self(&SECURE_SERVER_ACCOUNT) - } - fn calculate_checksum(&self, data: &[u8]) -> u8 { - common_checksum(ACCESS_KEY, data) - } - fn instantiate( - &self, - data: &[u8], - self_signat: [u8; 4], - remote_signat: [u8; 4], - ) -> Option<(Self::Instance, Vec)> { - let (session_key, pid, check_value) = read_secure_connection_data(data, &self.0)?; - - let check_value_response = check_value + 1; - - let data = bytemuck::bytes_of(&check_value_response); - - let mut response = Vec::new(); - - data.serialize(&mut response).ok()?; - - Some(( - SecureInstance { - pair: EncryptionPair::init_both(|| { - Rc4::new_from_slice(&session_key).expect("unable to initialize rc4 stream") - }), - self_signat, - remote_signat, - uid: pid, - }, - response, - )) - } -} diff --git a/prudpv0/src/crypto/insecure.rs b/prudpv0/src/crypto/insecure.rs deleted file mode 100644 index 5d3dff3..0000000 --- a/prudpv0/src/crypto/insecure.rs +++ /dev/null @@ -1,9 +0,0 @@ -use crate::crypto::Crypto; - -pub struct Insecure(); - -impl Crypto for Insecure { - fn calculate_checksum(&self, data: &[u8]) -> u8 { - todo!() - } -} diff --git a/prudpv0/src/crypto/mod.rs b/prudpv0/src/crypto/mod.rs deleted file mode 100644 index f4806f6..0000000 --- a/prudpv0/src/crypto/mod.rs +++ /dev/null @@ -1,38 +0,0 @@ -use cfg_if::cfg_if; -use rnex_core::prudp::types_flags::TypesFlags; - -mod common_crypto; - -pub trait CryptoInstance: Send + 'static { - fn decrypt_incoming(&mut self, data: &mut [u8]); - fn encrypt_outgoing(&mut self, data: &mut [u8]); - fn generate_signature(&self, types_flags: TypesFlags, data: &[u8]) -> [u8; 4]; - fn get_user_id(&self) -> u32; -} - -pub trait Crypto: Send + Sync + 'static { - type Instance: CryptoInstance; - fn new() -> Self; - fn calculate_checksum(&self, data: &[u8]) -> u8; - fn instantiate( - &self, - data: &[u8], - self_signat: [u8; 4], - remote_signat: [u8; 4], - ) -> Option<(Self::Instance, Vec)>; -} - -cfg_if! { - if #[cfg(feature = "friends")]{ - pub mod friends_common; - pub mod friends_insecure; - pub use friends_insecure::*; - pub mod friends_secure; - pub use friends_secure::*; - } else { - pub mod secure; - pub use secure::*; - pub mod insecure; - pub use insecure::*; - } -} diff --git a/prudpv0/src/crypto/secure.rs b/prudpv0/src/crypto/secure.rs deleted file mode 100644 index 435986e..0000000 --- a/prudpv0/src/crypto/secure.rs +++ /dev/null @@ -1,9 +0,0 @@ -use crate::crypto::Crypto; - -pub struct Secure(); - -impl Crypto for Secure { - fn calculate_checksum(&self, data: &[u8]) -> u8 { - todo!() - } -} diff --git a/prudpv0/src/lib.rs b/prudpv0/src/lib.rs deleted file mode 100644 index 86afe42..0000000 --- a/prudpv0/src/lib.rs +++ /dev/null @@ -1,50 +0,0 @@ -use cfg_if::cfg_if; -cfg_if! { - if #[cfg(feature = "prudpv0")] { - use log::info; - use proxy_common::ProxyStartupParam; - use std::env; - use std::net::SocketAddrV4; - use std::sync::{Arc, LazyLock}; - - use crate::crypto::{Crypto, Insecure, Secure}; - use crate::server::Server; - - mod crypto; - mod packet; - mod server; - - pub static EDGE_NODE_HOLDER: LazyLock = LazyLock::new(|| { - env::var("EDGE_NODE_HOLDER") - .ok() - .and_then(|s| s.parse().ok()) - .expect("EDGE_NODE_HOLDER not set") - }); - - pub static FORWARD_DESTINATION: LazyLock = LazyLock::new(|| { - env::var("FORWARD_DESTINATION") - .ok() - .and_then(|s| s.parse().ok()) - .expect("FORWARD_DESTINATION not set") - }); - //same as with prudpv1 this is responsible for handeling the different cryptography - //implementations, e.g. secure and insecure(this also includes special cases like friends) - - async fn start_proxy(param: ProxyStartupParam) { - info!("binding to socket"); - - let server: Arc> = Arc::new(Server::new(param).await); - - info!("waiting on packets"); - server.run_task().await; - } - - pub async fn start_secure(param: ProxyStartupParam) { - start_proxy::(param).await; - } - - pub async fn start_insecure(param: ProxyStartupParam) { - start_proxy::(param).await; - } - } -} diff --git a/prudpv0/src/packet.rs b/prudpv0/src/packet.rs deleted file mode 100644 index b78102f..0000000 --- a/prudpv0/src/packet.rs +++ /dev/null @@ -1,405 +0,0 @@ -use bytemuck::{Pod, Zeroable, try_from_bytes, try_from_bytes_mut}; -use log::{info, warn}; -use rnex_core::prudp::{ - types_flags::{ - TypesFlags, - flags::HAS_SIZE, - types::{CONNECT, DATA, DISCONNECT, PING, SYN}, - }, - virtual_port::VirtualPort, -}; - -use crate::crypto::{Crypto, CryptoInstance}; - -#[repr(C, packed)] -#[derive(Clone, Copy, Pod, Zeroable, Debug)] -pub struct PRUDPV0Header { - pub source: VirtualPort, - pub destination: VirtualPort, - pub type_flags: TypesFlags, - pub session_id: u8, - pub packet_signature: [u8; 4], - pub sequence_id: u16, -} -#[repr(transparent)] -pub struct PRUDPV0Packet>(pub T); - -impl> PRUDPV0Packet { - #[inline(always)] - pub fn get_packet_specific_size(&self) -> Option { - Some(get_types_flags_size_from_types_flags( - self.header()?.type_flags, - )) - } - - #[inline(always)] - pub fn header(&self) -> Option<&PRUDPV0Header> { - try_from_bytes(self.0.as_ref().get(..size_of::())?).ok() - } - #[inline(always)] - pub fn header_mut(&mut self) -> Option<&mut PRUDPV0Header> - where - T: AsMut<[u8]>, - { - try_from_bytes_mut(self.0.as_mut().get_mut(..size_of::())?).ok() - } - - #[inline(always)] - pub fn connection_signature(&self) -> Option<&[u8; 4]> { - let offset = size_of::(); - Some(self.0.as_ref().get(offset..offset + 4)?.try_into().ok()?) - } - #[inline(always)] - pub fn connection_signature_mut(&mut self) -> Option<&mut [u8; 4]> - where - T: AsMut<[u8]>, - { - let offset = size_of::(); - Some( - self.0 - .as_mut() - .get_mut(offset..offset + 4)? - .try_into() - .ok()?, - ) - } - #[inline(always)] - pub fn size_mut(&mut self) -> Option<&mut [u8]> - where - T: AsMut<[u8]>, - { - if self.header()?.type_flags.get_flags() & HAS_SIZE == 0 { - return None; - } - let offset = size_of::() + get_type_specific_size(self.header()?.type_flags); - Some(self.0.as_mut().get_mut(offset..offset + 2)?) - } - - #[inline(always)] - pub fn fragment_id_mut(&mut self) -> Option<&mut u8> - where - T: AsMut<[u8]>, - { - if self.header()?.type_flags.get_types() != DATA { - return None; - } - let offset = size_of::(); - Some(self.0.as_mut().get_mut(offset)?) - } - - #[inline(always)] - pub fn fragment_id(&self) -> Option<&u8> { - if self.header()?.type_flags.get_types() != DATA { - return None; - } - let offset = size_of::(); - Some(self.0.as_ref().get(offset)?) - } - - #[inline(always)] - fn get_payload_offset(&self) -> Option { - Some(size_of::() + self.get_packet_specific_size()?) - } - - #[inline(always)] - pub fn payload(&self) -> Option<&[u8]> { - self.0 - .as_ref() - .get(self.get_payload_offset()?..(self.0.as_ref().len().saturating_sub(1))) - } - #[inline(always)] - pub fn payload_mut(&mut self) -> Option<&mut [u8]> - where - T: AsMut<[u8]>, - { - let start_offset = self.get_payload_offset()?; - let end_offset = self.0.as_ref().len().saturating_sub(1); - self.0.as_mut().get_mut(start_offset..end_offset) - } - - #[inline(always)] - pub fn checksummed_data(&self) -> Option<&[u8]> { - self.0 - .as_ref() - .get(..self.0.as_ref().len().saturating_sub(1)) - } - - #[inline(always)] - pub fn checksum(&self) -> Option { - self.0.as_ref().last().copied() - } - #[inline(always)] - pub fn checksum_mut(&mut self) -> Option<&mut u8> - where - T: AsMut<[u8]>, - { - self.0.as_mut().last_mut() - } - - #[inline(always)] - pub fn check_checksum(&self, crypto: &impl Crypto) -> bool { - let Some(data) = self.checksummed_data() else { - return false; - }; - let Some(checksum) = self.checksum() else { - return false; - }; - - if checksum != crypto.calculate_checksum(data) { - warn!( - "checksum doesnt match expected checksum: {} != {}", - checksum, - crypto.calculate_checksum(data) - ) - } - - checksum == crypto.calculate_checksum(data) - } - - pub fn new(data: T) -> Self { - Self(data) - } -} - -const DEFAULT_SIGNAT: [u8; 4] = [0x12, 0x34, 0x56, 0x78]; -#[inline(always)] -#[allow(dead_code)] -const fn get_size_offset(tf: TypesFlags) -> usize { - size_of::() - + (if tf.get_types() & (SYN | CONNECT) != 0 { - 4 - } else if tf.get_types() & DATA != 0 { - 1 - } else { - 0 - }) -} -#[inline(always)] -const fn get_type_specific_size(tf: TypesFlags) -> usize { - if tf.get_types() == SYN || tf.get_types() == CONNECT { - 4 - } else if tf.get_types() & DATA != 0 { - 1 - } else { - 0 - } -} -#[inline(always)] -const fn get_types_flags_size_from_types_flags(tf: TypesFlags) -> usize { - get_type_specific_size(tf) + (if tf.get_flags() & HAS_SIZE != 0 { 2 } else { 0 }) -} -#[inline(always)] -pub const fn precalc_size(tf: TypesFlags, payload_size: usize) -> usize { - size_of::() + get_types_flags_size_from_types_flags(tf) + payload_size + 1 -} -pub fn new_syn_packet( - flags: u16, - source: VirtualPort, - destination: VirtualPort, - signat: [u8; 4], - crypto: &impl Crypto, -) -> Vec { - let type_flags = TypesFlags::default().types(SYN).flags(flags); - - let vec = vec![0; precalc_size(type_flags, 0)]; - let mut packet = PRUDPV0Packet::new(vec); - let header = packet.header_mut().expect("packet malformed in creation"); - - *header = PRUDPV0Header { - destination, - source, - packet_signature: DEFAULT_SIGNAT, - sequence_id: 0, - session_id: 0, - type_flags, - }; - *packet - .connection_signature_mut() - .expect("packet malformed in creation") = signat; - - *packet.checksum_mut().expect("packet malformed in creation") = crypto.calculate_checksum( - packet - .checksummed_data() - .expect("packet malformed in creation"), - ); - - packet.0 -} - -pub fn new_connect_packet( - flags: u16, - source: VirtualPort, - destination: VirtualPort, - self_signat: [u8; 4], - remote_signat: [u8; 4], - session_id: u8, - data: &[u8], - crypto: &impl Crypto, -) -> Vec { - let type_flags = TypesFlags::default().types(CONNECT).flags(flags); - - let vec = vec![0; precalc_size(type_flags, data.len())]; - let mut packet = PRUDPV0Packet::new(vec); - let header = packet.header_mut().expect("packet malformed in creation"); - - *header = PRUDPV0Header { - destination, - source, - packet_signature: self_signat, - sequence_id: 1, - session_id, - type_flags, - }; - *packet - .connection_signature_mut() - .expect("packet malformed in creation") = remote_signat; - - packet - .payload_mut() - .expect("packet malformed in creation") - .copy_from_slice(data); - - if let Some(size) = packet.size_mut() { - size.copy_from_slice(&(data.len() as u16).to_le_bytes()); - } - *packet.checksum_mut().expect("packet malformed in creation") = crypto.calculate_checksum( - packet - .checksummed_data() - .expect("packet malformed in creation"), - ); - info!("header: {:?}", packet.header()); - - packet.0 -} - -pub fn new_data_packet( - flags: u16, - source: VirtualPort, - destination: VirtualPort, - data: &[u8], - sequence_id: u16, - session_id: u8, - frag_id: u8, - crypto_instance: &mut impl CryptoInstance, - crypto: &impl Crypto, -) -> Vec { - let type_flags = TypesFlags::default().types(DATA).flags(flags); - - let vec = vec![0; precalc_size(type_flags, data.len())]; - let mut packet = PRUDPV0Packet::new(vec); - packet - .header_mut() - .expect("packet malformed in creation") - .type_flags = type_flags; - packet - .payload_mut() - .expect("packet malformed in creation") - .copy_from_slice(data); - - crypto_instance.encrypt_outgoing(packet.payload_mut().expect("packet malformed in creation")); - - if let Some(size) = packet.size_mut() { - size.copy_from_slice(&(data.len() as u16).to_le_bytes()); - } - *packet - .fragment_id_mut() - .expect("packet malformed in creation") = frag_id; - let packet_signature = crypto_instance.generate_signature( - type_flags, - packet.payload().expect("packet malformed in creation"), - ); - - let header = packet.header_mut().expect("packet malformed in creation"); - - *header = PRUDPV0Header { - destination, - source, - packet_signature, - sequence_id, - session_id, - type_flags, - }; - - *packet.checksum_mut().expect("packet malformed in creation") = crypto.calculate_checksum( - packet - .checksummed_data() - .expect("packet malformed in creation"), - ); - - info!("header: {:?}", packet.header()); - - packet.0 -} - -pub fn new_ping_packet( - flags: u16, - source: VirtualPort, - destination: VirtualPort, - sequence_id: u16, - session_id: u8, - crypto_instance: &mut impl CryptoInstance, - crypto: &impl Crypto, -) -> Vec { - let type_flags = TypesFlags::default().types(PING).flags(flags); - - let vec = vec![0; precalc_size(type_flags, 0)]; - let mut packet = PRUDPV0Packet::new(vec); - - let packet_signature = crypto_instance.generate_signature(type_flags, &[]); - - let header = packet.header_mut().expect("packet malformed in creation"); - - *header = PRUDPV0Header { - destination, - source, - packet_signature, - sequence_id, - session_id, - type_flags, - }; - - *packet.checksum_mut().expect("packet malformed in creation") = crypto.calculate_checksum( - packet - .checksummed_data() - .expect("packet malformed in creation"), - ); - - packet.0 -} -pub fn new_disconnect_packet( - flags: u16, - source: VirtualPort, - destination: VirtualPort, - sequence_id: u16, - session_id: u8, - crypto_instance: &mut impl CryptoInstance, - crypto: &impl Crypto, -) -> Vec { - let type_flags = TypesFlags::default().types(DISCONNECT).flags(flags); - - let vec = vec![0; precalc_size(type_flags, 0)]; - let mut packet = PRUDPV0Packet::new(vec); - - let packet_signature = crypto_instance.generate_signature(type_flags, &[]); - - let header = packet.header_mut().expect("packet malformed in creation"); - - *header = PRUDPV0Header { - destination, - source, - packet_signature, - sequence_id, - session_id, - type_flags, - }; - - *packet.checksum_mut().expect("packet malformed in creation") = crypto.calculate_checksum( - packet - .checksummed_data() - .expect("packet malformed in creation"), - ); - - info!("header: {:?}", packet.header()); - - packet.0 -} diff --git a/prudpv0/src/server.rs b/prudpv0/src/server.rs deleted file mode 100644 index 96b6416..0000000 --- a/prudpv0/src/server.rs +++ /dev/null @@ -1,536 +0,0 @@ -use std::{ - collections::HashMap, - net::{SocketAddr, SocketAddrV4}, - sync::{Arc, Weak}, - time::Duration, -}; - -use log::{error, info, warn}; -use proxy_common::{ProxyStartupParam, new_backend_connection}; -use rnex_core::{ - prudp::{ - socket_addr::PRUDPSockAddr, - types_flags::{ - flags::{ACK, NEED_ACK, RELIABLE}, - types::{CONNECT, DATA, DISCONNECT, PING, SYN}, - }, - }, - util::{SendingBufferConnection, SplittableBufferConnection}, -}; -use tokio::{ - net::UdpSocket, - spawn, - sync::{Mutex, RwLock}, - time::{Instant, sleep}, -}; - -use crate::{ - crypto::{Crypto, CryptoInstance}, - packet::{ - PRUDPV0Packet, new_connect_packet, new_data_packet, new_disconnect_packet, new_ping_packet, - new_syn_packet, - }, -}; - -pub struct InternalConnection { - last_action: Instant, - crypto_instance: C, - server_packet_counter: u16, - client_packet_counter: u16, - unacknowledged_packets: HashMap>>, - packet_queue: HashMap>)>, -} -pub struct Connection { - session_id: u8, - target: SendingBufferConnection, - addr: PRUDPSockAddr, - inner: Mutex>, -} - -impl InternalConnection { - #[allow(dead_code)] - fn next_server_count(&mut self) -> u16 { - let prev_val = self.server_packet_counter; - let (val, _) = self.server_packet_counter.overflowing_add(1); - self.server_packet_counter = val; - - prev_val - } -} - -pub struct Server { - param: ProxyStartupParam, - socket: UdpSocket, - crypto: C, - connections: RwLock>>>, -} - -impl Server { - async fn send_data_packet(self: Arc, conn: Arc>, data: &[u8]) { - /*let type_flags = TypesFlags::default().types(DATA).flags(HAS_SIZE | NEED_ACK); - let vec = vec![0; precalc_size(type_flags, data.len())]; - let mut packet = PRUDPV0Packet::new(vec); - - let payload = packet.payload_mut().expect("packet malformed in creation"); - payload.copy_from_slice(data); - - let mut inner = conn.inner.lock().await; - inner.crypto_instance.encrypt_outgoing(payload); - let packet_signat = inner.crypto_instance.generate_signature(payload); - let seq = inner.next_server_count(); - - *packet.header_mut().expect("packet malformed in creation") = PRUDPV0Header { - source: self.param.virtual_port, - destination: conn.addr.virtual_port, - type_flags, - session_id: conn.session_id, - packet_signature: packet_signat, - sequence_id: seq, - }; - /* we leave the sequence id as is for now as it defaults to 0 */ - - packet.checksum_mut().expect("packet malformed in creation") = - self.crypto.calculate_checksum( - packet - .checksummed_data() - .expect("packet malformed in creation"), - );*/ - let mut inner = conn.inner.lock().await; - let pieces = data.chunks(700); - let max_piece = pieces.len() - 1; - let mut frag_num = 1; - for (i, piece) in pieces.enumerate() { - let seq = inner.server_packet_counter; - let packet = new_data_packet( - NEED_ACK | RELIABLE, - (&self).param.virtual_port, - conn.addr.virtual_port, - piece, - inner.server_packet_counter, - conn.session_id, - if i == max_piece { 0 } else { frag_num }, - &mut inner.crypto_instance, - &(&self).crypto, - ); - inner.server_packet_counter += 1; - - let packet = Arc::new(packet); - let packet_ref = Arc::downgrade(&packet); - - inner.unacknowledged_packets.insert(seq, packet); - - let conn = Arc::downgrade(&conn); - let this = Arc::downgrade(&self); - - spawn(async move { - sleep(Duration::from_millis(i as u64 * 16)).await; - for n in 0..5 { - let Some(data) = packet_ref.upgrade() else { - return; - }; - let Some(conn) = conn.upgrade() else { - return; - }; - let Some(this) = this.upgrade() else { - return; - }; - info!("send attempt {}", n); - - this.socket - .send_to(&data, conn.addr.regular_socket_addr) - .await - .ok(); - - break; - } - }); - frag_num += 1; - } - drop(inner); - } - async fn connection_thread( - self: Arc, - conn: Weak>, - mut recv: SplittableBufferConnection, - ) { - while let Some(data) = recv.recv().await { - let Some(conn) = conn.upgrade() else { break }; - if &data[..] == &[0, 0, 0, 0, 0] { - info!("got keepalive"); - continue; - } - info!("got data from server: {:?}", data); - self.clone().send_data_packet(conn.clone(), &data).await; - } - } - async fn timeout_thread(self: Arc, conn: Weak>) { - loop { - let Some(conn) = conn.upgrade() else { break }; - sleep(Duration::from_secs(3)).await; - let mut inner = conn.inner.lock().await; - - if (Instant::now() - inner.last_action).as_secs() > 5 { - warn!("connection exceeded silence limit, sending ping"); - let packet = new_ping_packet( - NEED_ACK, - self.param.virtual_port, - conn.addr.virtual_port, - 0, - conn.session_id, - &mut inner.crypto_instance, - &self.crypto, - ); - - self.socket - .send_to(&packet, conn.addr.regular_socket_addr) - .await - .ok(); - } - - if (Instant::now() - inner.last_action).as_secs() > 15 { - warn!("client timed out..."); - - let packet = new_disconnect_packet( - NEED_ACK, - self.param.virtual_port, - conn.addr.virtual_port, - 0, - conn.session_id, - &mut inner.crypto_instance, - &self.crypto, - ); - - self.socket - .send_to(&packet, conn.addr.regular_socket_addr) - .await - .ok(); - self.socket - .send_to(&packet, conn.addr.regular_socket_addr) - .await - .ok(); - self.socket - .send_to(&packet, conn.addr.regular_socket_addr) - .await - .ok(); - drop(inner); - - let mut conns = self.connections.write().await; - conns.remove(&(conn.addr, conn.session_id)); - drop(conns); - break; - } - - drop(inner); - } - } - async fn handle_syn(self: Arc, packet: PRUDPV0Packet>, addr: PRUDPSockAddr) { - info!("got syn"); - let header = packet.header().unwrap(); - - let signat = addr.calculate_connection_signature(); - let signat = [signat[0], signat[1], signat[2], signat[3]]; - - let packet = new_syn_packet(ACK, header.destination, header.source, signat, &self.crypto); - self.socket - .send_to(&packet, addr.regular_socket_addr) - .await - .ok(); - } - async fn handle_connect(self: Arc, packet: PRUDPV0Packet>, addr: PRUDPSockAddr) { - let Some(data) = packet.payload() else { - warn!("malformed packet from: {:?}", addr.regular_socket_addr); - return; - }; - let Some(self_signat) = packet.connection_signature().copied() else { - warn!( - "malformed packet(unable to find connection signature) from: {:?}", - addr - ); - return; - }; - let remote_signat = addr.calculate_connection_signature(); - let remote_signat = [ - remote_signat[0], - remote_signat[1], - remote_signat[2], - remote_signat[3], - ]; - - let Some((ci, data)) = self.crypto.instantiate(&data, self_signat, remote_signat) else { - warn!("unable to instantiate crypto instance"); - return; - }; - - let pid = ci.get_user_id(); - println!("user with pid {} is connecting", pid); - let buf_conn = new_backend_connection(&self.param, addr, pid).await; - let Some(buf_conn) = buf_conn else { - error!("unable to connect to backend"); - return; - }; - - let header = packet.header().expect("header should be validated by now"); - - let conn = Arc::new(Connection { - target: buf_conn.duplicate_sender(), - addr, - session_id: header.session_id, - inner: Mutex::new(InternalConnection { - last_action: Instant::now(), - crypto_instance: ci, - client_packet_counter: 2, - server_packet_counter: 1, - unacknowledged_packets: HashMap::new(), - packet_queue: HashMap::new(), - }), - }); - - let mut conns = self.connections.write().await; - if conns.contains_key(&(addr, header.session_id)) { - error!("client already connected but tried to connect again"); - } - conns.insert((addr, header.session_id), conn.clone()); - drop(conns); - - spawn({ - let this = self.clone(); - let conn = Arc::downgrade(&conn); - this.connection_thread(conn, buf_conn) - }); - spawn({ - let this = self.clone(); - let conn = Arc::downgrade(&conn); - this.timeout_thread(conn) - }); - - let packet = new_connect_packet( - ACK, - header.destination, - header.source, - self_signat, - remote_signat, - packet.header().unwrap().session_id, - &data, - &self.crypto, - ); - - info!("sending back connection accept"); - self.socket - .send_to(&packet, addr.regular_socket_addr) - .await - .ok(); - } - async fn handle_data(self: Arc, packet: PRUDPV0Packet>, addr: PRUDPSockAddr) { - let Some(frag_id) = packet.fragment_id() else { - warn!("invalid packet from: {:?}", addr); - return; - }; - let Some(header) = packet.header() else { - warn!("invalid packet from: {:?}", addr); - return; - }; - - let Some(res) = self.get_connection((addr, header.session_id)).await else { - warn!("data packet on inactive connection from: {:?}", addr); - return; - }; - info!("frag: {}", frag_id); - let mut conn = res.inner.lock().await; - let ack = new_data_packet( - ACK, - self.param.virtual_port, - res.addr.virtual_port, - &[], - header.sequence_id, - header.session_id, - *frag_id, - &mut conn.crypto_instance, - &self.crypto, - ); - self.socket - .send_to(&ack, addr.regular_socket_addr) - .await - .ok(); - conn.packet_queue.insert( - packet.header().unwrap().sequence_id, - (Instant::now(), packet), - ); - while let Some((_, mut packet)) = { - let ctr = conn.client_packet_counter; - let packet = conn.packet_queue.remove(&ctr); - packet - } { - info!("processing packet: {}", conn.client_packet_counter); - let Some(payload) = packet.payload_mut() else { - //todo: at this point the stream would have been broken, we should probably disconnect the client - warn!("invalid packet from: {:?}", addr); - return; - }; - - conn.crypto_instance.decrypt_incoming(payload); - - res.target.send(payload.to_owned()).await; - conn.client_packet_counter += 1; - } - info!("finished handeling packets, dropping inner connection"); - drop(conn); - } - - async fn handle_ping(self: Arc, packet: PRUDPV0Packet>, addr: PRUDPSockAddr) { - info!("got ping"); - let header = packet.header().unwrap(); - - let Some(conn) = self.get_connection((addr, header.session_id)).await else { - warn!("ping on inactive connection: {:?}", addr); - return; - }; - let mut inner = conn.inner.lock().await; - let packet = new_ping_packet( - ACK, - self.param.virtual_port, - addr.virtual_port, - header.sequence_id, - header.session_id, - &mut inner.crypto_instance, - &self.crypto, - ); - drop(inner); - - self.socket - .send_to(&packet, addr.regular_socket_addr) - .await - .ok(); - } - async fn handle_disconnect( - self: Arc, - packet: PRUDPV0Packet>, - addr: PRUDPSockAddr, - ) { - info!("got disconnect"); - let header = packet.header().unwrap(); - - let Some(conn) = self.get_connection((addr, header.session_id)).await else { - warn!("ping on inactive connection: {:?}", addr); - return; - }; - let mut inner = conn.inner.lock().await; - let packet = new_disconnect_packet( - ACK, - self.param.virtual_port, - addr.virtual_port, - header.sequence_id, - header.session_id, - &mut inner.crypto_instance, - &self.crypto, - ); - drop(inner); - - let mut conns = self.connections.write().await; - conns.remove(&(addr, header.session_id)); - drop(conns); - - self.socket - .send_to(&packet, addr.regular_socket_addr) - .await - .ok(); - self.socket - .send_to(&packet, addr.regular_socket_addr) - .await - .ok(); - self.socket - .send_to(&packet, addr.regular_socket_addr) - .await - .ok(); - } - async fn get_connection( - &self, - addr: (PRUDPSockAddr, u8), - ) -> Option>> { - let rd = self.connections.read().await; - let res = rd.get(&addr).cloned(); - drop(rd); - res - } - - async fn process_packet(self: Arc, packet: PRUDPV0Packet>, addr: SocketAddrV4) { - if !packet.check_checksum(&self.crypto) { - warn!("invalid checksum from: {}", addr); - return; - } - - let Some(header) = packet.header() else { - warn!("malformatted packet from: {}", addr); - return; - }; - - info!("len: {}", packet.0.len()); - - let addr = PRUDPSockAddr::new(SocketAddr::V4(addr), header.source); - - if let Some(conn) = self.get_connection((addr, header.session_id)).await { - let mut inner = conn.inner.lock().await; - inner.last_action = Instant::now(); - drop(inner); - }; - if header.type_flags.get_flags() & ACK != 0 { - info!("got ack(acks are ignored for now)"); - return; - } - println!("{:?}", header); - match header.type_flags.get_types() { - SYN => { - self.handle_syn(packet, addr).await; - } - CONNECT => { - self.handle_connect(packet, addr).await; - } - DATA => { - self.handle_data(packet, addr).await; - } - PING => { - self.handle_ping(packet, addr).await; - } - DISCONNECT => { - self.handle_disconnect(packet, addr).await; - } - v => { - println!("unimplemented packed type: {}", v); - } - } - } - pub async fn run_task(self: Arc) { - loop { - let mut vec: Vec = vec![0u8; 65507]; - let (len, addr) = match self.socket.recv_from(&mut vec).await { - Err(e) => { - error!("unable to recv: {}", e); - break; - } - Ok(v) => v, - }; - let this = self.clone(); - tokio::spawn(async move { - let mut data = vec; - data.resize(len, 0); - let packet = PRUDPV0Packet::new(data); - - let SocketAddr::V4(addr) = addr else { - unreachable!() - }; - - this.process_packet(packet, addr).await; - }); - } - } - pub async fn new(param: ProxyStartupParam) -> Self { - let socket = UdpSocket::bind(param.self_private) - .await - .expect("unable to bind socket"); - Self { - socket, - crypto: C::new(), - connections: RwLock::new(HashMap::new()), - param, - } - } -} diff --git a/prudpv1/Cargo.toml b/prudpv1/Cargo.toml index b8346bf..bdf340e 100644 --- a/prudpv1/Cargo.toml +++ b/prudpv1/Cargo.toml @@ -9,15 +9,18 @@ tokio = { version = "1.47.0", features = ["full"] } hmac = "0.12.1" md-5 = "^0.10.6" rc4 = "0.1.0" -v-byte-helpers = { git = "https://github.com/RusticMaple/VByteMacros", version = "0.1.1" } +v-byte-helpers = { git = "https://github.com/DJMrTV/VByteMacros", version = "0.1.1" } thiserror = "2.0.12" log = "0.4.27" async-trait = "0.1.88" typenum = "1.18.0" once_cell = "1.21.3" rnex-core = { path = "../rnex-core", version = "0.1.1" } -proxy-common = {path = "../proxy-common"} -cfg-if = "1.0.4" -[features] -prudpv1 = [] +[[bin]] +name = "proxy_insecure" +path = "src/executables/proxy_insecure.rs" + +[[bin]] +name = "proxy_secure" +path = "src/executables/proxy_secure.rs" \ No newline at end of file diff --git a/prudpv1/src/executables/common.rs b/prudpv1/src/executables/common.rs new file mode 100644 index 0000000..e8162a1 --- /dev/null +++ b/prudpv1/src/executables/common.rs @@ -0,0 +1,18 @@ +use std::env; +use std::net::SocketAddrV4; +use once_cell::sync::Lazy; + +pub static EDGE_NODE_HOLDER: Lazy = Lazy::new(||{ + env::var("EDGE_NODE_HOLDER") + .ok() + .and_then(|s| s.parse().ok()) + .expect("EDGE_NODE_HOLDER not set") +}); + +pub static FORWARD_DESTINATION: Lazy = + Lazy::new(|| + env::var("FORWARD_DESTINATION") + .ok() + .and_then(|s| s.parse().ok()) + .expect("FORWARD_DESTINATION not set") + ); diff --git a/prudpv1/src/executables/mod.rs b/prudpv1/src/executables/mod.rs index dbcfdd7..ffac467 100644 --- a/prudpv1/src/executables/mod.rs +++ b/prudpv1/src/executables/mod.rs @@ -1,2 +1 @@ -pub mod proxy_insecure; -pub mod proxy_secure; +pub mod common; \ No newline at end of file diff --git a/prudpv1/src/executables/proxy_insecure.rs b/prudpv1/src/executables/proxy_insecure.rs index b9b974c..50446d5 100644 --- a/prudpv1/src/executables/proxy_insecure.rs +++ b/prudpv1/src/executables/proxy_insecure.rs @@ -1,27 +1,53 @@ -use crate::prudp::router::Router; -use crate::prudp::unsecure::Unsecure; -use log::error; -use proxy_common::{ProxyStartupParam, RNEX_ACCESS_KEY}; -use rnex_core::prudp::virtual_port::VirtualPort; + use rnex_core::reggie::UnitPacketRead; use rnex_core::reggie::UnitPacketWrite; use rnex_core::rmc::structures::RmcSerialize; -use rnex_core::rnex_proxy_common::ConnectionInitData; +use std::net::SocketAddrV4; +use std::sync::Arc; use std::time::Duration; +use log::error; use tokio::net::TcpStream; use tokio::task; use tokio::time::sleep; +use prudpv1::executables::common::{FORWARD_DESTINATION, EDGE_NODE_HOLDER}; +use prudpv1::prudp::router::Router; +use prudpv1::prudp::unsecure::Unsecure; +use rnex_core::common::setup; +use rnex_core::executables::common::{OWN_IP_PRIVATE, OWN_IP_PUBLIC, SERVER_PORT}; +use rnex_core::prudp::virtual_port::VirtualPort; +use rnex_core::reggie::EdgeNodeHolderConnectOption::Register; +use rnex_core::reggie::RemoteEdgeNodeHolder; +use rnex_core::rmc::protocols::{new_rmc_gateway_connection, OnlyRemote}; +use rnex_core::rnex_proxy_common::ConnectionInitData; +use rnex_core::util::SplittableBufferConnection; -pub async fn start(param: ProxyStartupParam) { - let (router_secure, _) = Router::new(param.self_private) + + +#[tokio::main] +async fn main() { + setup(); + + let conn = tokio::net::TcpStream::connect(&*EDGE_NODE_HOLDER).await.unwrap(); + + let conn: SplittableBufferConnection = conn.into(); + + conn.send(Register(SocketAddrV4::new(*OWN_IP_PUBLIC, *SERVER_PORT)).to_data().unwrap()).await; + + let conn = new_rmc_gateway_connection(conn, |r| Arc::new(OnlyRemote::::new(r))); + + let (router_secure, _) = Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *SERVER_PORT)) .await .expect("unable to start router"); let mut socket_secure = router_secure - .add_socket(VirtualPort::new(1, 10), Unsecure(RNEX_ACCESS_KEY)) + .add_socket(VirtualPort::new(1, 10), Unsecure( + "6f599f81" + )) .await .expect("unable to add socket"); + // let conn = socket_secure.connect(auth_sockaddr).await.unwrap(); + loop { let Some(mut conn) = socket_secure.accept().await else { error!("server crashed"); @@ -29,7 +55,8 @@ pub async fn start(param: ProxyStartupParam) { }; task::spawn(async move { - let mut stream = match TcpStream::connect(param.forward_destination).await { + let mut stream + = match TcpStream::connect(*FORWARD_DESTINATION).await { Ok(v) => v, Err(e) => { error!("unable to connect: {}", e); @@ -37,17 +64,10 @@ pub async fn start(param: ProxyStartupParam) { } }; - if let Err(e) = stream - .send_buffer( - &ConnectionInitData { - prudpsock_addr: conn.socket_addr, - pid: conn.user_id, - } - .to_data() - .unwrap(), - ) - .await - { + if let Err(e) = stream.send_buffer(&ConnectionInitData{ + prudpsock_addr: conn.socket_addr, + pid: conn.user_id + }.to_data().unwrap()).await{ error!("error connecting to backend: {}", e); return; }; @@ -72,7 +92,7 @@ pub async fn start(param: ProxyStartupParam) { return; } }; - + if conn.send(data).await == None{ return; } @@ -84,4 +104,5 @@ pub async fn start(param: ProxyStartupParam) { } }); } -} + drop(conn); +} \ No newline at end of file diff --git a/prudpv1/src/executables/proxy_secure.rs b/prudpv1/src/executables/proxy_secure.rs index c338ef9..d11b944 100644 --- a/prudpv1/src/executables/proxy_secure.rs +++ b/prudpv1/src/executables/proxy_secure.rs @@ -1,32 +1,53 @@ -use crate::prudp::router::Router; -use crate::prudp::secure::Secure; -use log::error; -use log::warn; -use proxy_common::{ProxyStartupParam, RNEX_ACCESS_KEY}; -use rnex_core::executables::common::SECURE_SERVER_ACCOUNT; -use rnex_core::prudp::virtual_port::VirtualPort; use rnex_core::reggie::UnitPacketRead; use rnex_core::reggie::UnitPacketWrite; use rnex_core::rmc::structures::RmcSerialize; -use rnex_core::rnex_proxy_common::ConnectionInitData; +use std::net::SocketAddrV4; +use std::sync::Arc; use std::time::Duration; +use log::error; use tokio::net::TcpStream; use tokio::task; use tokio::time::sleep; +use prudpv1::executables::common::{FORWARD_DESTINATION, EDGE_NODE_HOLDER}; +use prudpv1::prudp::router::Router; +use prudpv1::prudp::secure::Secure; +use rnex_core::common::setup; +use rnex_core::executables::common::{OWN_IP_PRIVATE, OWN_IP_PUBLIC, SECURE_SERVER_ACCOUNT, SERVER_PORT}; +use rnex_core::prudp::virtual_port::VirtualPort; +use rnex_core::reggie::EdgeNodeHolderConnectOption::Register; +use rnex_core::reggie::RemoteEdgeNodeHolder; +use rnex_core::rmc::protocols::{new_rmc_gateway_connection, OnlyRemote}; +use rnex_core::rnex_proxy_common::ConnectionInitData; +use rnex_core::util::SplittableBufferConnection; -pub async fn start(param: ProxyStartupParam) { - let (router_secure, _) = Router::new(param.self_private) +#[tokio::main] +async fn main() { + setup(); + + let conn = tokio::net::TcpStream::connect(&*EDGE_NODE_HOLDER).await.unwrap(); + + let conn: SplittableBufferConnection = conn.into(); + + conn.send(Register(SocketAddrV4::new(*OWN_IP_PUBLIC, *SERVER_PORT)).to_data().unwrap()).await; + + let conn = new_rmc_gateway_connection(conn, |r| Arc::new(OnlyRemote::::new(r))); + + + + let (router_secure, _) = Router::new(SocketAddrV4::new(*OWN_IP_PRIVATE, *SERVER_PORT)) .await .expect("unable to start router"); let mut socket_secure = router_secure - .add_socket( - VirtualPort::new(1, 10), - Secure(RNEX_ACCESS_KEY, SECURE_SERVER_ACCOUNT.clone()), - ) + .add_socket(VirtualPort::new(1, 10), Secure( + "6f599f81", + SECURE_SERVER_ACCOUNT.clone() + )) .await .expect("unable to add socket"); + // let conn = socket_secure.connect(auth_sockaddr).await.unwrap(); + loop { let Some(mut conn) = socket_secure.accept().await else { error!("server crashed"); @@ -34,25 +55,8 @@ pub async fn start(param: ProxyStartupParam) { }; task::spawn(async move { - let Ok(mut c) = rnex_core::grpc::account::Client::new().await else { - error!("failed to initialize gql client"); - return; - }; - - let v = match c.get_user_level(conn.user_id).await { - Ok(v) => v, - Err(e) => { - error!("failed to get user level: {}", e); - return; - } - }; - - if v < 0 { - warn!("person with too low account level joined"); - return; - } - - let mut stream = match TcpStream::connect(param.forward_destination).await { + let mut stream + = match TcpStream::connect(*FORWARD_DESTINATION).await { Ok(v) => v, Err(e) => { error!("unable to connect: {}", e); @@ -60,21 +64,16 @@ pub async fn start(param: ProxyStartupParam) { } }; - if let Err(e) = stream - .send_buffer( - &ConnectionInitData { - prudpsock_addr: conn.socket_addr, - pid: conn.user_id, - } - .to_data() - .unwrap(), - ) - .await - { + if let Err(e) = stream.send_buffer(&ConnectionInitData{ + prudpsock_addr: conn.socket_addr, + pid: conn.user_id + }.to_data().unwrap()).await{ error!("error connecting to backend: {}", e); return; }; + + loop { tokio::select! { data = conn.recv() => { @@ -95,7 +94,7 @@ pub async fn start(param: ProxyStartupParam) { return; } }; - + if conn.send(data).await == None{ return; } @@ -107,4 +106,6 @@ pub async fn start(param: ProxyStartupParam) { } }); } -} + + drop(conn); +} \ No newline at end of file diff --git a/prudpv1/src/lib.rs b/prudpv1/src/lib.rs index a24f714..ed53644 100644 --- a/prudpv1/src/lib.rs +++ b/prudpv1/src/lib.rs @@ -1,14 +1,2 @@ -cfg_if::cfg_if! { - if #[cfg(feature = "prudpv1")]{ - use proxy_common::ProxyStartupParam; - pub mod executables; - pub mod prudp; - pub async fn start_secure(param: ProxyStartupParam) { - executables::proxy_secure::start(param).await; - } - - pub async fn start_insecure(param: ProxyStartupParam) { - executables::proxy_insecure::start(param).await; - } - } -} +pub mod prudp; +pub mod executables; \ No newline at end of file diff --git a/prudpv1/src/prudp/packet.rs b/prudpv1/src/prudp/packet.rs index 027c0b4..da376bd 100644 --- a/prudpv1/src/prudp/packet.rs +++ b/prudpv1/src/prudp/packet.rs @@ -3,25 +3,21 @@ // force the compiler to shut up here #![allow(unused_parens)] -use crate::prudp::packet::PacketOption::{ - ConnectionSignature, FragmentId, InitialSequenceId, MaximumSubstreamId, SupportedFunctions, -}; +use std::fmt::{Debug, Formatter}; +use std::io; +use std::io::{Cursor, Read, Seek, Write}; +use std::net::SocketAddrV4; use bytemuck::{Pod, Zeroable}; use hmac::{Hmac, Mac}; use log::{error, warn}; -use md5::{Digest, Md5}; -use rnex_core::prudp::socket_addr::PRUDPSockAddr; -use rnex_core::prudp::types_flags::TypesFlags; -use rnex_core::prudp::types_flags::flags::ACK; -use rnex_core::prudp::virtual_port::VirtualPort; -use std::fmt::Debug; -use std::io; -use std::io::{Cursor, Read, Seek, Write}; -use std::net::SocketAddr; -use std::net::SocketAddrV4; +use md5::{Md5, Digest}; use thiserror::Error; -use v_byte_helpers::SwapEndian; +use v_byte_helpers::{SwapEndian}; use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions}; +use crate::prudp::packet::flags::ACK; +use crate::prudp::packet::PacketOption::{ConnectionSignature, FragmentId, InitialSequenceId, MaximumSubstreamId, SupportedFunctions}; +use rnex_core::prudp::socket_addr::PRUDPSockAddr; +use rnex_core::prudp::virtual_port::VirtualPort; type Md5Hmac = Hmac; @@ -36,11 +32,73 @@ pub enum Error { #[error("invalid option id {0}")] InvalidOptionId(u8), #[error("option size {size} doesnt match expected option for given option id {id}")] - InvalidOptionSize { id: u8, size: u8 }, + InvalidOptionSize { + id: u8, + size: u8, + }, } pub type Result = std::result::Result; +#[repr(transparent)] +#[derive(Copy, Clone, Pod, Zeroable, SwapEndian, Default, Eq, PartialEq)] +pub struct TypesFlags(u16); + +impl TypesFlags { + #[inline] + pub const fn get_types(self) -> u8 { + (self.0 & 0x000F) as u8 + } + #[inline] + pub const fn get_flags(self) -> u16 { + (self.0 & 0xFFF0) >> 4 + } + #[inline] + pub const fn types(self, val: u8) -> Self { + Self((self.0 & 0xFFF0) | (val as u16 & 0x000F)) + } + #[inline] + pub const fn flags(self, val: u16) -> Self { + Self((self.0 & 0x000F) | ((val << 4) & 0xFFF0)) + } + #[inline] + pub const fn set_flag(&mut self, val: u16){ + self.0 |= (val & 0xFFF) << 4; + } + #[inline] + pub const fn set_types(&mut self, val: u8){ + self.0 |= val as u16 & 0x0F; + } +} + +pub mod flags { + pub const ACK: u16 = 0x001; + pub const RELIABLE: u16 = 0x002; + pub const NEED_ACK: u16 = 0x004; + pub const HAS_SIZE: u16 = 0x008; + pub const MULTI_ACK: u16 = 0x200; +} + +pub mod types { + pub const SYN: u8 = 0x0; + pub const CONNECT: u8 = 0x1; + pub const DATA: u8 = 0x2; + pub const DISCONNECT: u8 = 0x3; + pub const PING: u8 = 0x4; + /// no idea what user is supposed to mean + pub const USER: u8 = 0x5; +} + +impl Debug for TypesFlags { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let stream_type = self.get_types(); + let port_number = self.get_flags(); + write!(f, "TypesFlags{{ types: {}, flags: {} }}", stream_type, port_number) + } +} + + + #[repr(C)] #[derive(Debug, Copy, Clone, Pod, Zeroable, SwapEndian, Eq, PartialEq)] pub struct PRUDPV1Header { @@ -58,7 +116,7 @@ pub struct PRUDPV1Header { impl Default for PRUDPV1Header { fn default() -> Self { - Self { + Self{ magic: [0xEA, 0xD0], version: 1, session_id: 0, @@ -68,30 +126,32 @@ impl Default for PRUDPV1Header { destination_port: VirtualPort(0), types_and_flags: TypesFlags(0), packet_specific_size: 0, - substream_id: 0, + substream_id: 0 } } } + #[derive(Debug, Clone, Eq, PartialEq)] -pub enum PacketOption { +pub enum PacketOption{ SupportedFunctions(u32), ConnectionSignature([u8; 16]), FragmentId(u8), InitialSequenceId(u16), - MaximumSubstreamId(u8), + MaximumSubstreamId(u8) } -impl PacketOption { - fn from(option_id: OptionId, option_data: &[u8]) -> io::Result { +impl PacketOption{ + fn from(option_id: OptionId, option_data: &[u8]) -> io::Result{ + let mut data_cursor = Cursor::new(option_data); - let val = match option_id.into() { + let val = match option_id.into(){ 0 => SupportedFunctions(data_cursor.read_struct(IS_BIG_ENDIAN)?), 1 => ConnectionSignature(data_cursor.read_struct(IS_BIG_ENDIAN)?), 2 => FragmentId(data_cursor.read_struct(IS_BIG_ENDIAN)?), 3 => InitialSequenceId(data_cursor.read_struct(IS_BIG_ENDIAN)?), 4 => MaximumSubstreamId(data_cursor.read_struct(IS_BIG_ENDIAN)?), - _ => unreachable!(), + _ => unreachable!() }; Ok(val) @@ -152,7 +212,7 @@ impl OptionId { // Invariant is upheld because we only create the object if it doesn't violate the invariant match val { 0 | 1 | 2 | 3 | 4 => Ok(Self(val)), - _ => Err(Error::InvalidOptionId(val)), + _ => Err(Error::InvalidOptionId(val)) } } @@ -163,7 +223,7 @@ impl OptionId { 2 => 1, 3 => 2, 4 => 1, - _ => unreachable!(), + _ => unreachable!() } } } @@ -178,7 +238,8 @@ impl PRUDPV1Packet { pub fn new(reader: &mut (impl Read + Seek)) -> Result { let header: PRUDPV1Header = reader.read_struct(IS_BIG_ENDIAN)?; - if header.magic[0] != 0xEA || header.magic[1] != 0xD0 { + if header.magic[0] != 0xEA || + header.magic[1] != 0xD0 { return Err(Error::InvalidMagic(u16::from_be_bytes(header.magic))); } @@ -186,31 +247,31 @@ impl PRUDPV1Packet { return Err(Error::InvalidVersion(header.version)); } + let packet_signature: [u8; 16] = reader.read_struct(IS_BIG_ENDIAN)?; //let packet_signature: [u8; 16] = [0; 16]; assert_eq!(reader.stream_position().ok(), Some(14 + 16)); + + let mut packet_specific_buffer = vec![0u8; header.packet_specific_size as usize]; reader.read_exact(&mut packet_specific_buffer)?; + //no clue whats up with options but they are broken let mut packet_specific_data_cursor = Cursor::new(&packet_specific_buffer); let mut options = Vec::new(); loop { - let Ok(option_id): io::Result = - packet_specific_data_cursor.read_struct(IS_BIG_ENDIAN) - else { - break; + let Ok(option_id): io::Result = packet_specific_data_cursor.read_struct(IS_BIG_ENDIAN) else { + break }; - let Ok(value_size): io::Result = - packet_specific_data_cursor.read_struct(IS_BIG_ENDIAN) - else { - break; + let Ok(value_size): io::Result = packet_specific_data_cursor.read_struct(IS_BIG_ENDIAN) else { + break }; if value_size == 0 { @@ -230,21 +291,20 @@ impl PRUDPV1Packet { } let mut option_data = vec![0u8; value_size as usize]; - if packet_specific_data_cursor - .read_exact(&mut option_data[..]) - .is_err() - { + if packet_specific_data_cursor.read_exact(&mut option_data[..]).is_err() { error!("unable to read options"); break; } options.push(PacketOption::from(option_id, &option_data)?); } - + let mut payload = vec![0u8; header.payload_size as usize]; reader.read_exact(&mut payload)?; + + Ok(Self { header, packet_signature, @@ -253,21 +313,22 @@ impl PRUDPV1Packet { }) } - pub fn base_acknowledgement_packet(&self) -> Self { + pub fn base_acknowledgement_packet(&self) -> Self{ let base = self.base_response_packet(); let mut flags = self.header.types_and_flags.flags(0); flags.set_flag(ACK); - let options = self - .options + let options = self.options .iter() .filter(|o| matches!(o, FragmentId(_))) .cloned() .collect(); - Self { + + + Self{ header: PRUDPV1Header { types_and_flags: flags, sequence_id: self.header.sequence_id, @@ -282,29 +343,22 @@ impl PRUDPV1Packet { pub fn source_sockaddr(&self, socket_addr_v4: SocketAddrV4) -> PRUDPSockAddr { PRUDPSockAddr { - regular_socket_addr: SocketAddr::V4(socket_addr_v4), + regular_socket_addr: socket_addr_v4, virtual_port: self.header.source_port, } } - fn generate_options_bytes(&self) -> Vec { + fn generate_options_bytes(&self) -> Vec{ let mut vec = Vec::new(); - for option in &self.options { - option - .write_to_stream(&mut vec) - .expect("vec should always automatically be able to extend"); + for option in &self.options{ + option.write_to_stream(&mut vec).expect("vec should always automatically be able to extend"); } vec } - pub fn calculate_signature_value( - &self, - access_key: &str, - session_key: Option<[u8; 32]>, - connection_signature: Option<[u8; 16]>, - ) -> [u8; 16] { + pub fn calculate_signature_value(&self, access_key: &str, session_key: Option<[u8; 32]>, connection_signature: Option<[u8; 16]>) -> [u8; 16]{ let access_key_bytes = access_key.as_bytes(); let access_key_sum: u32 = access_key_bytes.iter().map(|v| *v as u32).sum(); let access_key_sum_bytes: [u8; 4] = access_key_sum.to_le_bytes(); @@ -320,46 +374,32 @@ impl PRUDPV1Packet { let mut hmac = Md5Hmac::new_from_slice(&key).expect("fuck"); - hmac.write(&header_data) - .expect("error during hmac calculation"); + hmac.write(&header_data).expect("error during hmac calculation"); if let Some(session_key) = session_key { - hmac.write(&session_key) - .expect("error during hmac calculation"); + hmac.write(&session_key).expect("error during hmac calculation"); } - hmac.write(&access_key_sum_bytes) - .expect("error during hmac calculation"); + hmac.write(&access_key_sum_bytes).expect("error during hmac calculation"); if let Some(connection_signature) = connection_signature { - hmac.write(&connection_signature) - .expect("error during hmac calculation"); + hmac.write(&connection_signature).expect("error during hmac calculation"); } - hmac.write(&option_bytes) - .expect("error during hmac calculation"); + hmac.write(&option_bytes).expect("error during hmac calculation"); - hmac.write_all(&self.payload) - .expect("error during hmac calculation"); + hmac.write_all(&self.payload).expect("error during hmac calculation"); - hmac.finalize().into_bytes()[0..16] - .try_into() - .expect("invalid hmac size") + hmac.finalize().into_bytes()[0..16].try_into().expect("invalid hmac size") } - pub fn calculate_and_assign_signature( - &mut self, - access_key: &str, - session_key: Option<[u8; 32]>, - connection_signature: Option<[u8; 16]>, - ) { - self.packet_signature = - self.calculate_signature_value(access_key, session_key, connection_signature); + pub fn calculate_and_assign_signature(&mut self, access_key: &str, session_key: Option<[u8; 32]>, connection_signature: Option<[u8; 16]>){ + self.packet_signature = self.calculate_signature_value(access_key, session_key, connection_signature); } - pub fn set_sizes(&mut self) { + pub fn set_sizes(&mut self){ self.header.packet_specific_size = self.options.iter().map(|o| o.write_size()).sum(); self.header.payload_size = self.payload.len() as u16; } - pub fn base_response_packet(&self) -> Self { + pub fn base_response_packet(&self) -> Self { Self { header: PRUDPV1Header { magic: [0xEA, 0xD0], @@ -372,18 +412,19 @@ impl PRUDPV1Packet { sequence_id: 0, session_id: 0, substream_id: 0, + }, packet_signature: [0; 16], payload: Default::default(), - options: Default::default(), + options: Default::default() } } - pub fn write_to(&self, writer: &mut impl Write) -> io::Result<()> { + pub fn write_to(&self, writer: &mut impl Write) -> io::Result<()>{ writer.write_all(bytemuck::bytes_of(&self.header))?; writer.write_all(&self.packet_signature)?; - for option in &self.options { + for option in &self.options{ option.write_to_stream(writer)?; } @@ -395,24 +436,20 @@ impl PRUDPV1Packet { #[cfg(test)] mod test { - use super::{OptionId, PRUDPV1Header, PacketOption, TypesFlags}; - use rnex_core::prudp::{ - types_flags::{ - flags::{NEED_ACK, RELIABLE}, - types::DATA, - }, - virtual_port::VirtualPort, - }; + use crate::prudp::packet::flags::{NEED_ACK, RELIABLE}; + use crate::prudp::packet::types::DATA; + use super::{OptionId, PacketOption, PRUDPV1Header, TypesFlags}; + use rnex_core::prudp::virtual_port::VirtualPort; #[test] fn size_test() { assert_eq!(size_of::(), 14); } #[test] - fn test_options() { - let packet_types = [0, 1, 2, 3, 4]; + fn test_options(){ + let packet_types = [0,1,2,3,4]; - for p_type in packet_types { + for p_type in packet_types{ let option_id = OptionId::new(p_type).unwrap(); let buf = vec![0; option_id.option_type_size() as usize]; @@ -426,10 +463,12 @@ mod test { assert_eq!(write_buf.len() as u8, opt.write_size()) } } + + } #[test] - fn header_read() { + fn header_read(){ let header = PRUDPV1Header { version: 0, destination_port: VirtualPort(0), @@ -439,23 +478,23 @@ mod test { packet_specific_size: 0, payload_size: 0, sequence_id: 0, - magic: [0xEA, 0xD0], - source_port: VirtualPort(0), + magic: [0xEA,0xD0], + source_port: VirtualPort(0) }; let bytes = bytemuck::bytes_of(&header); let bytes = &bytes[0x6..]; - let _: [u8; 8] = bytes.try_into().unwrap(); + let header_data: [u8; 8] = bytes.try_into().unwrap(); } #[test] - fn test_types_flags() { + fn test_types_flags(){ let types = TypesFlags::default().types(DATA).flags(NEED_ACK | RELIABLE); assert_ne!((types.0 >> 4) & NEED_ACK, 0); assert_ne!((types.0 >> 4) & RELIABLE, 0); assert_ne!((types.0 & 0xFF) as u8 & DATA, 0); } -} +} \ No newline at end of file diff --git a/prudpv1/src/prudp/packet/v1/sanity_checks.rs b/prudpv1/src/prudp/packet/v1/sanity_checks.rs deleted file mode 100644 index 335c269..0000000 --- a/prudpv1/src/prudp/packet/v1/sanity_checks.rs +++ /dev/null @@ -1,12 +0,0 @@ -//! # PRUDPV1 Feature sanity checks -//! -//! Checks wether the set features are actually sensical or wether they are -//! nonsense and throws a compiler error incase of nonsense - -#[cfg(feature = "friends")] -compile_error!( - "friends uses prudpv0 instead of prudpv1, please do not enable both at the same time" -); - -#[cfg(feature = "prudpv0")] -compile_error!("you cannot enable two prudp versions at the same time"); diff --git a/prudpv1/src/prudp/secure.rs b/prudpv1/src/prudp/secure.rs index c7d312f..acf8bfb 100644 --- a/prudpv1/src/prudp/secure.rs +++ b/prudpv1/src/prudp/secure.rs @@ -1,53 +1,115 @@ -use crate::prudp::packet::PRUDPV1Packet; -use crate::prudp::socket::{CryptoHandler, CryptoHandlerConnectionInstance}; +use std::io::Cursor; use hmac::digest::consts::U32; +use log::error; use rc4::cipher::StreamCipherCoreWrapper; use rc4::{KeyInit, Rc4, Rc4Core, StreamCipher}; -use rnex_core::nex::account::Account; -use rnex_core::prudp::encryption::EncryptionPair; -use rnex_core::prudp::ticket::read_secure_connection_data; -use rnex_core::rmc::structures::RmcSerialize; +use rc4::consts::U16; use typenum::U5; +use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions}; +use rnex_core::kerberos::{derive_key, TicketInternalData}; +use rnex_core::nex::account::Account; +use crate::prudp::packet::PRUDPV1Packet; +use crate::prudp::socket::{CryptoHandler, CryptoHandlerConnectionInstance, EncryptionPair}; +use rnex_core::rmc::structures::RmcSerialize; + +pub fn read_secure_connection_data(data: &[u8], act: &Account) -> Option<([u8; 32], u32, u32)>{ + let mut cursor = Cursor::new(data); + + let mut ticket_data: Vec = Vec::deserialize(&mut cursor).ok()?; + let mut request_data: Vec = Vec::deserialize(&mut cursor).ok()?; + + let ticket_data_size = ticket_data.len(); + + let ticket_data = &mut ticket_data[0..ticket_data_size-0x10]; + + let server_key = derive_key(act.pid, act.kerbros_password); + + let mut rc4: StreamCipherCoreWrapper> = + Rc4::new_from_slice(&server_key).expect("unable to init rc4 keystream"); + + rc4.apply_keystream(ticket_data); + + let ticket_data: &TicketInternalData = match bytemuck::try_from_bytes(ticket_data){ + Ok(v) => v, + Err(e) => { + error!("unable to read internal ticket data: {}", e); + return None; + } + }; + + // todo: add ticket expiration + + let TicketInternalData{ + session_key, + pid: ticket_source_pid, + issued_time + } = *ticket_data; + + // todo: add checking if tickets are signed with a valid md5-hmac + let request_data_length = request_data.len(); + let request_data = &mut request_data[0.. request_data_length - 0x10]; + + let mut rc4: StreamCipherCoreWrapper> = + Rc4::new_from_slice(&session_key).expect("unable to init rc4 keystream"); + + rc4.apply_keystream(request_data); + + let mut reqest_data_cursor = Cursor::new(request_data); + + let pid: u32 = reqest_data_cursor.read_struct(IS_BIG_ENDIAN).ok()?; + + if pid != ticket_source_pid{ + let ticket_created_on = issued_time.to_regular_time(); + + error!("someone tried to spoof their pid, ticket was created on: {}", ticket_created_on.to_rfc2822()); + return None; + } + + let _cid: u32 = reqest_data_cursor.read_struct(IS_BIG_ENDIAN).ok()?; + let response_check: u32 = reqest_data_cursor.read_struct(IS_BIG_ENDIAN).ok()?; + + + + Some((session_key, pid, response_check)) +} 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 { + vec.push(EncryptionPair{ send: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4"), - recv: 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 { + for _ in 1..=count{ let modifier = session_key.len() + 1; let key_length = session_key.len(); - for (position, val) in (&mut session_key[0..key_length / 2]).iter_mut().enumerate() { + for (position, val) in (&mut session_key[0..key_length/2]).iter_mut().enumerate(){ *val = val.wrapping_add((modifier - position) as u8); } - vec.push(EncryptionPair { + vec.push(EncryptionPair{ send: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4"), - recv: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4"), + recv: Rc4U32::new_from_slice(&session_key).expect("unable to create rc4") }); } vec } + pub struct Secure(pub &'static str, pub Account); + pub struct SecureInstance { access_key: &'static str, session_key: [u8; 32], streams: Vec>>, self_signature: [u8; 16], - #[allow(dead_code)] remote_signature: [u8; 16], pid: u32, } @@ -93,17 +155,18 @@ impl CryptoHandler for Secure { } } + impl CryptoHandlerConnectionInstance for SecureInstance { 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) { + 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) { + if let Some(crypt_pair) = self.streams.get_mut(substream as usize){ crypt_pair.send.apply_keystream(data); } } @@ -119,14 +182,10 @@ impl CryptoHandlerConnectionInstance for SecureInstance { fn sign_packet(&self, packet: &mut PRUDPV1Packet) { packet.set_sizes(); - packet.calculate_and_assign_signature( - self.access_key, - Some(self.session_key), - Some(self.self_signature), - ); + packet.calculate_and_assign_signature(self.access_key, Some(self.session_key), Some(self.self_signature)); } fn verify_packet(&self, _packet: &PRUDPV1Packet) -> bool { true } -} +} \ No newline at end of file diff --git a/prudpv1/src/prudp/socket.rs b/prudpv1/src/prudp/socket.rs index c6f5faa..6467d8f 100644 --- a/prudpv1/src/prudp/socket.rs +++ b/prudpv1/src/prudp/socket.rs @@ -1,35 +1,47 @@ +use crate::prudp::packet::flags::{ACK, HAS_SIZE, MULTI_ACK, NEED_ACK, RELIABLE}; +use crate::prudp::packet::types::{CONNECT, DATA, DISCONNECT, PING, SYN}; use crate::prudp::packet::PacketOption::{ ConnectionSignature, FragmentId, MaximumSubstreamId, SupportedFunctions, }; -use crate::prudp::packet::{PRUDPV1Header, PRUDPV1Packet}; -use async_trait::async_trait; -use log::error; -use log::{info, warn}; -use rc4::StreamCipher; -use rnex_core::prudp::socket_addr::PRUDPSockAddr; -use rnex_core::prudp::types_flags::TypesFlags; -use rnex_core::prudp::types_flags::flags::{ACK, HAS_SIZE, MULTI_ACK, NEED_ACK, RELIABLE}; -use rnex_core::prudp::types_flags::types::{CONNECT, DATA, DISCONNECT, PING, SYN}; +use crate::prudp::packet::{PRUDPV1Header, PRUDPV1Packet, TypesFlags}; use rnex_core::prudp::virtual_port::VirtualPort; +use rnex_core::prudp::socket_addr::PRUDPSockAddr; +use async_trait::async_trait; +use log::{info, warn}; +use log::error; +use rc4::StreamCipher; +use v_byte_helpers::ReadExtensions; +use v_byte_helpers::little_endian::read_u16; use std::collections::{BTreeMap, HashMap}; use std::io::Cursor; use std::marker::PhantomData; use std::ops::Deref; use std::sync::{Arc, Weak}; -use tokio::spawn; -use v_byte_helpers::ReadExtensions; -use v_byte_helpers::little_endian::read_u16; use std::time::Duration; use tokio::net::UdpSocket; +use tokio::sync::mpsc::{channel, Receiver, Sender}; use tokio::sync::Mutex; -use tokio::sync::mpsc::{Receiver, Sender, channel}; -use tokio::time::{Instant, sleep}; +use tokio::time::{sleep, Instant}; // 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 EncryptionPair { + pub send: T, + pub recv: T, +} + +impl EncryptionPair { + pub fn init_both T>(func: F) -> Self { + Self { + recv: func(), + send: func(), + } + } +} + pub struct CommonConnection { pub user_id: u32, pub socket_addr: PRUDPSockAddr, @@ -49,7 +61,7 @@ struct InternalConnection { socket: Arc, packet_queue: HashMap, last_packet_time: Instant, - unacknowleged_packets: Vec<(Instant, PRUDPV1Packet)>, + unacknowleged_packets: Vec<(Instant, PRUDPV1Packet)> } impl Deref for InternalConnection { @@ -69,45 +81,18 @@ impl InternalConnection { prev_val } - async fn close_connection(&mut self) { - let mut packet = PRUDPV1Packet { - header: PRUDPV1Header { - sequence_id: self.next_server_count(), - substream_id: 0, - session_id: self.session_id, - types_and_flags: TypesFlags::default().types(DISCONNECT), - destination_port: self.common.socket_addr.virtual_port, - source_port: self.server_port, - ..Default::default() - }, - payload: Vec::new(), - options: vec![FragmentId(0)], - ..Default::default() - }; - - // no need for encryption the, the payload is empty - - packet.set_sizes(); - - self.crypto_handler_instance.sign_packet(&mut packet); - - self.send_raw_packet(&packet).await; - - self.delete_connection().await; - } - /// Sends a raw packet to a given client on the connection - /// - /// a raw packet is one which does not get processed any further(other than to send it + /// + /// a raw packet is one which does not get processed any further(other than to send it /// off without buffering or anything), - /// as such you need to make sure that + /// as such you need to make sure that /// the sizes are set correctly and so on #[inline] async fn send_raw_packet(&self, prudp_packet: &PRUDPV1Packet) { send_raw_prudp_to_sockaddr(&self.socket, self.socket_addr, prudp_packet).await; } - async fn delete_connection(&self) { + async fn delete_connection(&self){ let Some(conns) = self.connections.upgrade() else { // this is fine as it implies the server has already quit, thus meaning that we dont // have to remove ourselves from the server @@ -131,7 +116,7 @@ pub struct ExternalConnection { #[derive(Clone)] pub struct SendingConnection { common: Arc, - internal: Weak, + internal: Weak>, } pub struct CommonSocket { @@ -194,75 +179,78 @@ pub(super) trait AnyInternalSocket: } #[async_trait] -pub(super) trait AnyInternalConnection: Send + Sync + 'static { - async fn send_data_packet(&self, data: Vec); +pub(super) trait AnyInternalConnection: + Send + Sync + Deref + 'static +{ + async fn send_data_packet(&mut self, data: Vec); - async fn close_connection(&self); + async fn close_connection(&mut self); } + + #[async_trait] -impl AnyInternalConnection for Mutex> { - async fn send_data_packet(&self, data: Vec) { - let pieces = data.chunks(600); - let max_piece = pieces.len() - 1; - let mut piece_num = 1; - let mut locked = self.lock().await; - let packets: Vec<_> = pieces - .enumerate() - .map(|(i, piece)| { - let mut packet = PRUDPV1Packet { - header: PRUDPV1Header { - sequence_id: locked.next_server_count(), - substream_id: 0, - session_id: locked.session_id, - types_and_flags: TypesFlags::default() - .types(DATA) - .flags(RELIABLE | NEED_ACK), - destination_port: locked.common.socket_addr.virtual_port, - source_port: locked.server_port, - ..Default::default() - }, - payload: piece.to_owned(), - options: vec![FragmentId(if i == max_piece { 0 } else { piece_num })], - ..Default::default() - }; +impl AnyInternalConnection for InternalConnection { + async fn send_data_packet(&mut self, data: Vec) { + let mut packet = PRUDPV1Packet { + header: PRUDPV1Header { + 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() + }; - locked - .crypto_handler_instance - .encrypt_outgoing(0, &mut packet.payload[..]); + self.crypto_handler_instance + .encrypt_outgoing(0, &mut packet.payload[..]); - packet.set_sizes(); + packet.set_sizes(); - locked.crypto_handler_instance.sign_packet(&mut packet); + self.crypto_handler_instance.sign_packet(&mut packet); - piece_num += 1; - packet - }) - .collect(); - drop(locked); + self.send_raw_packet(&packet).await; - for packet in packets { - let mut locked = self.lock().await; - locked.send_raw_packet(&packet).await; - - locked.unacknowleged_packets.push((Instant::now(), packet)); - drop(locked); - sleep(Duration::from_secs(16)).await; - } + self.unacknowleged_packets.push((Instant::now(), packet)); } - async fn close_connection(&self) { - let mut locked = self.lock().await; - locked.close_connection().await; + async fn close_connection(&mut self) { + // jon confirmed that this should be a safe way to dc a client + + let mut packet = PRUDPV1Packet { + header: PRUDPV1Header { + sequence_id: self.next_server_count(), + substream_id: 0, + session_id: self.session_id, + types_and_flags: TypesFlags::default().types(DISCONNECT), + destination_port: self.common.socket_addr.virtual_port, + source_port: self.server_port, + ..Default::default() + }, + payload: Vec::new(), + options: vec![FragmentId(0)], + ..Default::default() + }; + + // no need for encryption the, the payload is empty + + packet.set_sizes(); + + self.crypto_handler_instance.sign_packet(&mut packet); + + self.send_raw_packet(&packet).await; + + self.delete_connection().await; } } -async fn send_raw_prudp_to_sockaddr( - udp_socket: &UdpSocket, - dest: PRUDPSockAddr, - packet: &PRUDPV1Packet, -) { +async fn send_raw_prudp_to_sockaddr(udp_socket: &UdpSocket, dest: PRUDPSockAddr, packet: &PRUDPV1Packet){ let mut vec = Vec::new(); packet @@ -293,7 +281,7 @@ impl InternalSocket { } /// sends a raw packet to a specific prudp socket address - /// + /// /// a raw packet is a packet is a packet which wont get processed any further, /// sizes signatures etc need to be set before using this function async fn send_packet_unbuffered(&self, dest: PRUDPSockAddr, packet: &PRUDPV1Packet) { @@ -365,15 +353,13 @@ impl InternalSocket { conn.close_connection().await; } - for (send_time, packet) in &conn.unacknowleged_packets { - if *send_time < (Instant::now() - Duration::from_millis(3000)) { - warn!( - "failed to resend packet 5 times and never got response, destroying connection" - ); + for (send_time, packet) in &conn.unacknowleged_packets{ + if *send_time < (Instant::now() - Duration::from_millis(3000)){ + warn!("failed to resend packet 5 times and never got response, destroying connection"); conn.close_connection().await; break; } - if *send_time < (Instant::now() - Duration::from_millis(500)) { + if *send_time < (Instant::now() - Duration::from_millis(500)){ info!("unacknowledged packet sat arround for more than 500 ms, resending"); conn.send_raw_packet(packet).await; } @@ -413,12 +399,12 @@ impl InternalSocket { packet_queue: Default::default(), last_packet_time: Instant::now(), unacknowleged_packets: Vec::new(), - supported_function_version, + supported_function_version }; let internal = Arc::new(Mutex::new(internal)); - let dyn_internal: Arc = internal.clone(); + let dyn_internal: Arc> = internal.clone(); let external = ExternalConnection { sending: SendingConnection { @@ -501,7 +487,7 @@ impl InternalSocket { SupportedFunctions(funcs) => { functions = *funcs & 0xFF; response.options.push(SupportedFunctions(*funcs & 0xFF)); - } + }, _ => { /* ? */ } } } @@ -624,6 +610,7 @@ impl AnyInternalSocket for InternalSocket { 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 { @@ -658,8 +645,9 @@ impl AnyInternalSocket for InternalSocket { // remove the packet whose sequence id matches the ack packet // or in other words keep all of those which dont match the sequence id - conn.unacknowleged_packets - .retain_mut(|v| packet.header.sequence_id != v.1.header.sequence_id); + conn.unacknowleged_packets.retain_mut(|v| { + packet.header.sequence_id != v.1.header.sequence_id + }); } else { error!("non connection acknowledgement packet on nonexistent connection...") } @@ -671,23 +659,26 @@ impl AnyInternalSocket for InternalSocket { if let Some(conn) = self.get_connection(address).await { let mut conn = conn.lock().await; - if conn.supported_function_version == 1 { + if conn.supported_function_version == 1{ let mut collected_ids: Vec = Vec::new(); let mut cursor = Cursor::new(&packet.payload); - while let Ok(v) = read_u16(&mut cursor) { + while let Ok(v) = read_u16(&mut cursor){ collected_ids.push(v); } conn.unacknowleged_packets.retain_mut(|(_, up)| { - !(collected_ids.iter().any(|id| up.header.sequence_id == *id) - || up.header.sequence_id <= packet.header.sequence_id) + !( + collected_ids.iter().any(|id| up.header.sequence_id == *id) || + up.header.sequence_id <= packet.header.sequence_id + ) }); + } else { let mut collected_ids: Vec = Vec::new(); let mut cursor = Cursor::new(&packet.payload); - let Ok(_substream_id): Result = cursor.read_le_struct() else { + let Ok(_substream_id): Result = cursor.read_le_struct() else{ error!("invalid data whilest reading new version agregate acknowledgement"); return; }; @@ -699,20 +690,19 @@ impl AnyInternalSocket for InternalSocket { error!("invalid data whilest reading new version agregate acknowledgement"); return; }; - for _ in 0..additional_sequence_ids { - let Ok(additional_sequence_id): Result = cursor.read_le_struct() - else { - error!( - "invalid data whilest reading new version agregate acknowledgement" - ); + for _ in 0..additional_sequence_ids{ + let Ok(additional_sequence_id): Result = cursor.read_le_struct() else { + error!("invalid data whilest reading new version agregate acknowledgement"); return; }; collected_ids.push(additional_sequence_id); } conn.unacknowleged_packets.retain_mut(|(_, up)| { - !(collected_ids.iter().any(|id| up.header.sequence_id == *id) - || up.header.sequence_id <= sequence_id) + !( + collected_ids.iter().any(|id| up.header.sequence_id == *id) || + up.header.sequence_id <= sequence_id + ) }); } } else { @@ -899,9 +889,10 @@ impl ExternalConnection { impl SendingConnection { pub async fn send(&self, data: Vec) -> Option<()> { let internal = self.internal.upgrade()?; - spawn(async move { - internal.send_data_packet(data).await; - }); + + let mut internal = internal.lock().await; + + internal.send_data_packet(data).await; Some(()) } @@ -910,6 +901,8 @@ impl SendingConnection { return; }; + let mut internal = internal.lock().await; + internal.close_connection().await; } } diff --git a/prudpv1/src/prudp/unsecure.rs b/prudpv1/src/prudp/unsecure.rs index 79cc908..6c45824 100644 --- a/prudpv1/src/prudp/unsecure.rs +++ b/prudpv1/src/prudp/unsecure.rs @@ -1,22 +1,24 @@ -use crate::prudp::packet::PRUDPV1Packet; -use crate::prudp::socket::{CryptoHandler, CryptoHandlerConnectionInstance}; -use rc4::{KeyInit, Rc4, StreamCipher}; -use rnex_core::prudp::encryption::{DEFAULT_KEY, EncryptionPair}; +use once_cell::sync::Lazy; +use rc4::{Key, KeyInit, Rc4, StreamCipher}; use typenum::U5; +use crate::prudp::packet::PRUDPV1Packet; +use crate::prudp::socket::{CryptoHandler, CryptoHandlerConnectionInstance, EncryptionPair}; pub struct Unsecure(pub &'static str); + + pub struct UnsecureInstance { key: &'static str, streams: Vec>>, self_signature: [u8; 16], - #[allow(dead_code)] 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; @@ -51,13 +53,13 @@ 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) { + 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) { + if let Some(crypt_pair) = self.streams.get_mut(substream as usize){ crypt_pair.send.apply_keystream(data); } } @@ -79,4 +81,4 @@ impl CryptoHandlerConnectionInstance for UnsecureInstance { fn verify_packet(&self, _packet: &PRUDPV1Packet) -> bool { true } -} +} \ No newline at end of file diff --git a/rnex-core/Cargo.toml b/rnex-core/Cargo.toml index f30c47c..554a8d9 100644 --- a/rnex-core/Cargo.toml +++ b/rnex-core/Cargo.toml @@ -9,15 +9,15 @@ dotenv = "0.15.0" once_cell = "1.20.2" rc4 = "0.1.0" thiserror = "2.0.11" -v-byte-helpers = { git = "https://github.com/RusticMaple/VByteMacros", version = "0.1.1" } +v-byte-helpers = { git = "https://github.com/DJMrTV/VByteMacros", version = "0.1.1" } simplelog = "0.12.2" chrono = "0.4.39" log = "0.4.25" rand = "0.8.5" -cfg-if = "1.0.4" + hmac = "0.12.1" md-5 = "^0.10.6" -tokio = { version = "1.43.0", features = ["full"] } +tokio = { version = "1.43.0", features = ["macros", "rt-multi-thread", "net", "sync", "fs"] } hex = "0.4.3" macros = { path = "../macros" } @@ -25,36 +25,13 @@ paste = "1.0.15" typenum = "1.18.0" json = "0.12.4" anyhow = "1.0.100" -ureq = { version = "3.1.4", features = [ "json" ] } -serde = { version = "1.0.228", features = [ "derive" ] } -serde_json = "1.0.149" -sqlx = { version = "0.8.6", optional = true, features = ["postgres", "runtime-tokio", "chrono", "time"] } -aws-sdk-s3 = { version = "1.129.0", optional = true } -aws-config = { version = "1.8.15", optional = true } -base64 = "0.22.1" -sha2 = "0.10.9" -urlencoding = "2.1.3" -futures = "0.3.32" +ureq = "3.1.4" [dev-dependencies] # criterion = "0.7.0" [features] rmc_struct_header = [] -guest_login = [] -friends = ["guest_login", "database-support"] -big_pid = [] -v3-3-2 = [] -third-notif-param = [] -v3-4-0 = ["v3-3-2", "third-notif-param", "rmc_struct_header"] -v3-5-0 = ["v3-4-0"] -v3-8-15 = ["v3-5-0"] -v3-10-22 = ["v3-8-15"] -v4-3-11 = ["v3-8-15"] -nx = ["big_pid"] -splatoon = [] -datastore = ["database-support", "v3-8-15", "dep:aws-sdk-s3", "dep:aws-config"] -database-support = ["dep:sqlx"] [[bench]] name = "rmc_serialization" @@ -71,4 +48,4 @@ path = "src/executables/backend_server_secure.rs" [[bin]] name = "edge_node_holder_server" -path = "src/executables/edge_node_holder_server.rs" +path = "src/executables/edge_node_holder_server.rs" \ No newline at end of file diff --git a/rnex-core/src/executables/backend_server_insecure.rs b/rnex-core/src/executables/backend_server_insecure.rs index b7ce979..4cbe591 100644 --- a/rnex-core/src/executables/backend_server_insecure.rs +++ b/rnex-core/src/executables/backend_server_insecure.rs @@ -1,47 +1,45 @@ +use rnex_core::reggie::RemoteEdgeNodeHolder; use once_cell::sync::Lazy; use rnex_core::common::setup; -use rnex_core::executables::common::{SECURE_SERVER_ACCOUNT, new_simple_backend}; -use rnex_core::nex::auth_handler::AuthHandler; -use rnex_core::reggie::EdgeNodeHolderConnectOption::DontRegister; -use rnex_core::reggie::RemoteEdgeNodeHolder; -use rnex_core::rmc::protocols::{OnlyRemote, new_rmc_gateway_connection}; use rnex_core::rmc::structures::RmcSerialize; -use rnex_core::util::SplittableBufferConnection; use std::env; use std::net::SocketAddrV4; use std::sync::Arc; use tokio::net::TcpStream; +use rnex_core::executables::common::{SECURE_SERVER_ACCOUNT, new_simple_backend}; +use rnex_core::nex::auth_handler::AuthHandler; +use rnex_core::reggie::EdgeNodeHolderConnectOption::DontRegister; +use rnex_core::rmc::protocols::{new_rmc_gateway_connection, OnlyRemote}; +use rnex_core::util::SplittableBufferConnection; -pub static FORWARD_EDGE_NODE_HOLDER: Lazy = Lazy::new(|| { + +pub static FORWARD_EDGE_NODE_HOLDER: Lazy = Lazy::new(||{ env::var("FORWARD_EDGE_NODE_HOLDER") .ok() - .and_then(|s| Some(s.parse().unwrap())) + .and_then(|s| s.parse().ok()) .expect("FORWARD_EDGE_NODE_HOLDER not set") }); + + #[tokio::main] async fn main() { setup(); - let conn = TcpStream::connect(&*FORWARD_EDGE_NODE_HOLDER) - .await - .unwrap(); + let conn = TcpStream::connect(&*FORWARD_EDGE_NODE_HOLDER).await.unwrap(); let conn: SplittableBufferConnection = conn.into(); conn.send(DontRegister.to_data().unwrap()).await; - let conn = new_rmc_gateway_connection(conn, |r| { - Arc::new(OnlyRemote::::new(r)) - }); + let conn = new_rmc_gateway_connection(conn, |r| Arc::new(OnlyRemote::::new(r))); - new_simple_backend(move |_, _| { + new_simple_backend(move |_, _|{ let controller = conn.clone(); Arc::new(AuthHandler { destination_server_acct: &SECURE_SERVER_ACCOUNT, - build_name: env!("AUTH_REPORT_VERSION"), - control_server: controller, + build_name: "branch:origin/project/wup-agmj build:3_8_15_2004_0", + control_server: controller }) - }) - .await; + }).await; } diff --git a/rnex-core/src/executables/backend_server_secure.rs b/rnex-core/src/executables/backend_server_secure.rs index 88f2508..1488369 100644 --- a/rnex-core/src/executables/backend_server_secure.rs +++ b/rnex-core/src/executables/backend_server_secure.rs @@ -1,30 +1,37 @@ -use cfg_if::cfg_if; +use std::sync::Arc; +use std::sync::atomic::AtomicU32; use rnex_core::common::setup; +use rnex_core::executables::common::{new_simple_backend}; +use rnex_core::nex::matchmake::MatchmakeManager; +use rnex_core::nex::remote_console::RemoteConsole; +use rnex_core::nex::user::User; +use rnex_core::rmc::protocols::RemoteInstantiatable; #[tokio::main] async fn main() { setup(); - cfg_if! { - if #[cfg(feature = "friends")]{ - use rnex_core::executables::friends_backend::start_friends_backend; - start_friends_backend().await; - } else if #[cfg(feature = "datastore")] { - use rnex_core::executables::common::DB_POOL; - use sqlx::PgPool; - let database_url = std::env::var("RNEX_DATASTORE_DATABASE_URL") - .expect("RNEX_DATASTORE_DATABASE_URL must be set"); - let pool = PgPool::connect(&database_url) - .await - .expect("Failed to create pool"); + let mmm = Arc::new(MatchmakeManager{ + gid_counter: AtomicU32::new(1), + sessions: Default::default(), + users: Default::default(), + rv_cid_counter: AtomicU32::new(1), + }); - DB_POOL.set(pool).expect("failed to set global DB_POOL"); - use rnex_core::executables::regular_backend; - regular_backend::start_regular_backend().await - } else { - use rnex_core::executables::regular_backend; - regular_backend::start_regular_backend().await - } - } -} + let weak_mmm = Arc::downgrade(&mmm); + + MatchmakeManager::initialize_garbage_collect_thread(weak_mmm).await; + + new_simple_backend(move |c, r|{ + let mmm = mmm.clone(); + Arc::new_cyclic(move |this| User{ + this: this.clone(), + ip: c.prudpsock_addr, + pid:c.pid, + remote: RemoteConsole::new(r), + matchmake_manager: mmm, + station_url: Default::default() + }) + }).await; +} \ No newline at end of file diff --git a/rnex-core/src/executables/common.rs b/rnex-core/src/executables/common.rs index c94a463..7a55f24 100644 --- a/rnex-core/src/executables/common.rs +++ b/rnex-core/src/executables/common.rs @@ -1,51 +1,27 @@ -use once_cell::sync::Lazy; -use rnex_core::nex::account::Account; -use rnex_core::rmc::protocols::{RmcCallable, RmcConnection, new_rmc_gateway_connection}; -use rnex_core::rmc::structures::RmcSerialize; -use rnex_core::rnex_proxy_common::ConnectionInitData; use std::env; use std::io::Cursor; use std::net::{Ipv4Addr, SocketAddrV4}; use std::sync::Arc; +use once_cell::sync::Lazy; +use rnex_core::nex::account::Account; +use rnex_core::rmc::protocols::{RmcCallable, RmcConnection, new_rmc_gateway_connection}; +use rnex_core::rnex_proxy_common::ConnectionInitData; +use rnex_core::rmc::structures::RmcSerialize; use tokio::net::TcpListener; -cfg_if! { - if #[cfg(feature = "datastore")] { - use sqlx::postgres::PgPool; - } -} -use crate::reggie::UnitPacketRead; -use cfg_if::cfg_if; -use log::error; + use std::error::Error; +use log::error; + +use crate::reggie::UnitPacketRead; const IP_REQ_SERVICE_URL: &str = "https://ipinfo.io/ip"; -cfg_if! { - if #[cfg(feature = "datastore")] { - use std::sync::{LazyLock, OnceLock}; - pub static RNEX_DATASTORE_DATABASE_URL: LazyLock = LazyLock::new(|| { - std::env::var("RNEX_DATASTORE_DATABASE_URL") - .expect("RNEX_DATASTORE_DATABASE_URL must be set") - }); - pub static DB_POOL: OnceLock = OnceLock::new(); - pub fn get_db() -> &'static PgPool { - DB_POOL.get().expect("db_pool not initialized") - } - pub static RNEX_DATASTORE_S3_ENDPOINT: LazyLock = LazyLock::new(|| { - std::env::var("RNEX_DATASTORE_S3_ENDPOINT") - .expect("RNEX_DATASTORE_S3_ENDPOINT must be set") - }); - pub static RNEX_DATASTORE_S3_BUCKET: LazyLock = LazyLock::new(|| { - std::env::var("RNEX_DATASTORE_S3_BUCKET") - .expect("RNEX_DATASTORE_S3_BUCKET must be set") - }); - } -} +fn try_get_ip() -> Result> { + let mut req = ureq::get(IP_REQ_SERVICE_URL) + .call()?; -pub fn try_get_ip() -> Result> { - let mut req = ureq::get(IP_REQ_SERVICE_URL).call()?; Ok(req.body_mut().read_to_string()?.parse()?) } @@ -61,7 +37,9 @@ pub static OWN_IP_PUBLIC: Lazy = Lazy::new(|| { env::var("SERVER_IP_PUBLIC") .ok() .map(|s| s.parse().expect("invalid ip address")) - .unwrap_or_else(|| try_get_ip().unwrap()) + .unwrap_or_else(||{ + try_get_ip().unwrap() + }) }); pub static SERVER_PORT: Lazy = Lazy::new(|| { @@ -82,28 +60,24 @@ pub static AUTH_SERVER_ACCOUNT: Lazy = pub static SECURE_SERVER_ACCOUNT: Lazy = Lazy::new(|| Account::new(2, "Quazal Rendez-Vous", &KERBEROS_SERVER_PASSWORD)); -pub async fn new_simple_backend(mut creation_function: F) + +pub async fn new_simple_backend(mut creation_function: F) where F: FnMut(ConnectionInitData, RmcConnection) -> Arc, { - let listen = TcpListener::bind(SocketAddrV4::new(*OWN_IP_PRIVATE, *SERVER_PORT)) - .await - .unwrap(); + let listen = TcpListener::bind(SocketAddrV4::new(*OWN_IP_PRIVATE, *SERVER_PORT)).await.unwrap(); while let Ok((mut stream, _addr)) = listen.accept().await { - let buffer = match stream.read_buffer().await { + let buffer = match stream.read_buffer().await{ Ok(v) => v, Err(e) => { - error!( - "an error ocurred whilest reading connection data buffer: {:?}", - e - ); + error!("an error ocurred whilest reading connection data buffer: {:?}", e); continue; } }; let user_connection_data = ConnectionInitData::deserialize(&mut Cursor::new(buffer)); - let user_connection_data = match user_connection_data { + let user_connection_data = match user_connection_data{ Ok(v) => v, Err(e) => { error!("an error ocurred whilest reading connection data: {:?}", e); @@ -111,6 +85,8 @@ where } }; let fun_ref = &mut creation_function; - new_rmc_gateway_connection(stream.into(), move |r| fun_ref(user_connection_data, r)); + new_rmc_gateway_connection(stream.into(), move |r|{ + fun_ref(user_connection_data, r) + }); } -} +} \ No newline at end of file diff --git a/rnex-core/src/executables/friends_backend.rs b/rnex-core/src/executables/friends_backend.rs deleted file mode 100644 index d2ce497..0000000 --- a/rnex-core/src/executables/friends_backend.rs +++ /dev/null @@ -1,72 +0,0 @@ -use std::{ - io::Cursor, - net::SocketAddrV4, - sync::{Arc, atomic::AtomicU32}, -}; - -use log::error; -use tokio::net::TcpListener; - -use crate::{ - executables::common::{OWN_IP_PRIVATE, SERVER_PORT}, - nex::friends_handler::{FriendsGuest, FriendsManager, FriendsUser, RemoteFriendRemote}, - reggie::UnitPacketRead, - rmc::{ - protocols::{RmcPureRemoteObject, new_rmc_gateway_connection}, - structures::RmcSerialize, - }, - rnex_proxy_common::ConnectionInitData, -}; - -pub async fn start_friends_backend() { - let fm = Arc::new(FriendsManager { - cid_counter: AtomicU32::new(1), - users: Default::default(), - }); - let listen = TcpListener::bind(SocketAddrV4::new(*OWN_IP_PRIVATE, *SERVER_PORT)) - .await - .unwrap(); - while let Ok((mut stream, _addr)) = listen.accept().await { - let buffer = match stream.read_buffer().await { - Ok(v) => v, - Err(e) => { - error!( - "an error ocurred whilest reading connection data buffer: {:?}", - e - ); - continue; - } - }; - - let user_connection_data = ConnectionInitData::deserialize(&mut Cursor::new(buffer)); - - let c = match user_connection_data { - Ok(v) => v, - Err(e) => { - error!("an error ocurred whilest reading connection data: {:?}", e); - continue; - } - }; - let fm = fm.clone(); - if c.pid != 100 { - new_rmc_gateway_connection(stream.into(), move |r| { - Arc::new_cyclic(move |this| FriendsUser { - fm, - addr: c.prudpsock_addr, - pid: c.pid, - data: Default::default(), - current_friends: Default::default(), - this: this.clone(), - remote: RemoteFriendRemote::new(r), - }) - }); - } else { - new_rmc_gateway_connection(stream.into(), move |_| { - Arc::new_cyclic(move |_| FriendsGuest { - fm, - addr: c.prudpsock_addr, - }) - }); - } - } -} diff --git a/rnex-core/src/executables/mod.rs b/rnex-core/src/executables/mod.rs index 83a9df5..ffac467 100644 --- a/rnex-core/src/executables/mod.rs +++ b/rnex-core/src/executables/mod.rs @@ -1,10 +1 @@ -use cfg_if::cfg_if; - -pub mod common; -cfg_if! { - if #[cfg(feature = "friends")]{ - pub mod friends_backend; - } else { - pub mod regular_backend; - } -} +pub mod common; \ No newline at end of file diff --git a/rnex-core/src/executables/regular_backend.rs b/rnex-core/src/executables/regular_backend.rs deleted file mode 100644 index 7f62864..0000000 --- a/rnex-core/src/executables/regular_backend.rs +++ /dev/null @@ -1,34 +0,0 @@ -use std::sync::{Arc, atomic::AtomicU32}; - -use crate::{ - executables::common::new_simple_backend, - nex::{matchmake::MatchmakeManager, remote_console::RemoteConsole, user::User}, - rmc::protocols::RmcPureRemoteObject, -}; - -pub async fn start_regular_backend() { - let mmm = Arc::new(MatchmakeManager { - //gid_counter: AtomicU32::new(1), - sessions: Default::default(), - users: Default::default(), - users_by_pid: Default::default(), - rv_cid_counter: AtomicU32::new(1), - }); - - let weak_mmm = Arc::downgrade(&mmm); - - MatchmakeManager::initialize_garbage_collect_thread(weak_mmm).await; - - new_simple_backend(move |c, r| { - let mmm = mmm.clone(); - Arc::new_cyclic(move |this| User { - this: this.clone(), - ip: c.prudpsock_addr, - pid: c.pid, - remote: RemoteConsole::new(r), - matchmake_manager: mmm, - station_url: Default::default(), - }) - }) - .await; -} diff --git a/rnex-core/src/grpc/account.rs b/rnex-core/src/grpc/account.rs index 9d2d4e8..a70149f 100644 --- a/rnex-core/src/grpc/account.rs +++ b/rnex-core/src/grpc/account.rs @@ -1,27 +1,29 @@ -use crate::grpc::account::Error::SomethingHappened; -use json::{JsonValue, object}; -use once_cell::sync::Lazy; -use rnex_core::PID; +use std::{env, result}; use std::array::TryFromSliceError; use std::ops::Deref; -use std::{env, result}; +use json::{object, JsonValue}; +use once_cell::sync::Lazy; use thiserror::Error; -use tokio::task::{JoinError, spawn_blocking}; -static API_KEY: Lazy = Lazy::new(|| { - let key = env::var("ACCOUNT_GQL_API_KEY").expect("no graphql ip specified"); +use tokio::task::{spawn_blocking, JoinError}; +use crate::grpc::account::Error::SomethingHappened; +static API_KEY: Lazy = Lazy::new(||{ + let key = env::var("ACCOUNT_GQL_API_KEY") + .expect("no graphql ip specified"); key }); -static CLIENT_URI: Lazy = Lazy::new(|| { +static CLIENT_URI: Lazy = Lazy::new(||{ env::var("ACCOUNT_GQL_URL") .ok() .and_then(|s| s.parse().ok()) .expect("no graphql ip specified") }); + + #[derive(Error, Debug)] -pub enum Error { +pub enum Error{ #[error(transparent)] RequestError(#[from] ureq::Error), #[error(transparent)] @@ -33,20 +35,20 @@ pub enum Error { #[error("something happened")] SomethingHappened, #[error("error joining blocking task: {0}")] - Join(#[from] JoinError), + Join(#[from] JoinError) } pub type Result = result::Result; -pub struct Client; //(reqwest::Client); +pub struct Client;//(reqwest::Client); -impl Client { +impl Client{ pub async fn new() -> Result { //Ok(Self(reqwest::ClientBuilder::new().build()?)) Ok(Self) } - async fn do_request(&self, request_data: JsonValue) -> Result { + async fn do_request(&self, request_data: JsonValue) -> Result{ let request = ureq::post(CLIENT_URI.as_str()) .header("X-API-Key", API_KEY.deref()) .content_type("application/json"); @@ -68,112 +70,34 @@ impl Client { */ } - pub async fn get_nex_password(&mut self, pid: PID) -> Result<[u8; 16]> { - let req = self - .do_request(object! { - "query": r"query($pid: Int!){ + pub async fn get_nex_password(&mut self , pid: u32) -> Result<[u8; 16]>{ + let req = self.do_request(object!{ + "query": r"query($pid: Int!){ userByPid(pid: $pid){ nexPassword } }", - "variables": { - "pid": pid - } - }) - .await?; + "variables": { + "pid": pid + } + }).await?; - let Some(val) = req - .entries() + let Some(val) = req.entries() .find(|v| v.0 == "data") - .ok_or(SomethingHappened)? - .1 + .ok_or(SomethingHappened)?.1 .entries() .find(|v| v.0 == "userByPid") - .ok_or(SomethingHappened)? - .1 + .ok_or(SomethingHappened)?.1 .entries() .find(|v| v.0 == "nexPassword") - .ok_or(SomethingHappened)? - .1 - .as_str() - else { + .ok_or(SomethingHappened)?.1 + .as_str() else { return Err(SomethingHappened); }; Ok(val.as_bytes().try_into().map_err(|_| SomethingHappened)?) } - pub async fn get_user_level(&mut self, pid: PID) -> Result { - let req = self - .do_request(object! { - "query": r"query($pid: Int!){ - userByPid(pid: $pid){ - accountLevel - } - }", - "variables": { - "pid": pid - } - }) - .await?; - - let Some(val) = req - .entries() - .find(|v| v.0 == "data") - .ok_or(SomethingHappened)? - .1 - .entries() - .find(|v| v.0 == "userByPid") - .ok_or(SomethingHappened)? - .1 - .entries() - .find(|v| v.0 == "accountLevel") - .ok_or(SomethingHappened)? - .1 - .as_i32() - else { - return Err(SomethingHappened); - }; - - Ok(val) - } - - pub async fn get_pid_from_token(&mut self, token: String) -> Result { - let req = self - .do_request(object! { - "query": - r"query($token: String!){ - token(tokenData: $token){ - pid - } - }", - "variables": { - "token": token - } - }) - .await?; - // this breaks switch nex servers and should be fixed eventually - let Some(val) = req - .entries() - .find(|v| v.0 == "data") - .ok_or(SomethingHappened)? - .1 - .entries() - .find(|v| v.0 == "token") - .ok_or(SomethingHappened)? - .1 - .entries() - .find(|v| v.0 == "pid") - .ok_or(SomethingHappened)? - .1 - .as_u32() - else { - return Err(SomethingHappened); - }; - - Ok(val) - } - /*pub async fn get_user_data(&mut self , pid: u32) -> Result{ let req = Request::new(GetUserDataRequest{ pid @@ -185,6 +109,8 @@ impl Client { }*/ } + + /* pub struct Client(AccountClient>); @@ -222,4 +148,4 @@ impl Client{ Ok(response) } } -*/ +*/ \ No newline at end of file diff --git a/rnex-core/src/kerberos/mod.rs b/rnex-core/src/kerberos/mod.rs index 3512eb6..b118651 100644 --- a/rnex-core/src/kerberos/mod.rs +++ b/rnex-core/src/kerberos/mod.rs @@ -1,44 +1,23 @@ -use bytemuck::{Pod, Zeroable, bytes_of}; -use cfg_if::cfg_if; +use std::io::{Read, Write}; +use bytemuck::{bytes_of, Pod, Zeroable}; use chrono::{Datelike, NaiveDate, NaiveDateTime, NaiveTime, Timelike, Utc}; use hmac::Hmac; -use hmac::Mac; use md5::{Digest, Md5}; -use rc4::KeyInit; -use rc4::cipher::StreamCipherCoreWrapper; use rc4::{Rc4, Rc4Core, StreamCipher}; -use rnex_core::rmc::structures::RmcSerialize; -use std::io::{Read, Write}; -use typenum::U16; -use typenum::Unsigned; - -use rnex_core::rmc::structures::Result; - -use rnex_core::PID; - -cfg_if! { - if #[cfg(feature = "friends")]{ - pub type SessionLengthTy = U16; - } else { - use rc4::consts::U32; - pub type SessionLengthTy = U32; - } -} -pub const SESSION_KEY_LENGTH: usize = SessionLengthTy::USIZE; +use rc4::cipher::StreamCipherCoreWrapper; +use rc4::consts::U16; +use hmac::Mac; +use rc4::KeyInit; +use crate::rmc::structures::RmcSerialize; type Md5Hmac = Hmac; -pub fn derive_key(pid: PID, password: &[u8]) -> [u8; 16] { - let iteration_count = 65000 + pid % 1024; - // we do one iteration out here to ensure the key is always 16 bytes +pub fn derive_key(pid: u32, password: [u8; 16]) -> [u8; 16]{ + let iteration_count = 65000 + pid%1024; - let mut key: [u8; 16] = { - let mut md5 = Md5::new(); - md5.update(password); - md5.finalize().try_into().unwrap() - }; + let mut key = password; - for _ in 1..iteration_count { + for _ in 0..iteration_count { let mut md5 = Md5::new(); md5.update(key); key = md5.finalize().try_into().unwrap(); @@ -50,29 +29,12 @@ pub fn derive_key(pid: PID, password: &[u8]) -> [u8; 16] { #[repr(transparent)] pub struct KerberosDateTime(pub u64); -impl KerberosDateTime { - pub fn from_u64(val: u64) -> Self { - Self(val) - } - - pub fn from_naive(dt: chrono::NaiveDateTime) -> Self { - use chrono::Datelike; - use chrono::Timelike; - Self::new( - dt.second() as u64, - dt.minute() as u64, - dt.hour() as u64, - dt.day() as u64, - dt.month() as u64, - dt.year() as u64, - ) - } - - pub fn new(second: u64, minute: u64, hour: u64, day: u64, month: u64, year: u64) -> Self { +impl KerberosDateTime{ + pub fn new(second: u64, minute: u64, hour: u64, day: u64, month: u64, year:u64 ) -> Self { Self(second | (minute << 6) | (hour << 12) | (day << 17) | (month << 22) | (year << 26)) } - pub fn now() -> Self { + pub fn now() -> Self{ let now = chrono::Utc::now(); Self::new( now.second() as u64, @@ -85,80 +47,69 @@ impl KerberosDateTime { } #[inline] - pub fn get_seconds(&self) -> u8 { + pub fn get_seconds(&self) -> u8{ (self.0 & 0b111111) as u8 } #[inline] - pub fn get_minutes(&self) -> u8 { + pub fn get_minutes(&self) -> u8{ ((self.0 >> 6) & 0b111111) as u8 } #[inline] - pub fn get_hours(&self) -> u8 { + pub fn get_hours(&self) -> u8{ ((self.0 >> 12) & 0b111111) as u8 } #[inline] - pub fn get_days(&self) -> u8 { + pub fn get_days(&self) -> u8{ ((self.0 >> 17) & 0b111111) as u8 } #[inline] - pub fn get_month(&self) -> u8 { + pub fn get_month(&self) -> u8{ ((self.0 >> 22) & 0b1111) as u8 } #[inline] - pub fn get_year(&self) -> u64 { + pub fn get_year(&self) -> u64{ (self.0 >> 26) & 0xFFFFFFFF } - pub fn to_regular_time(&self) -> chrono::DateTime { + pub fn to_regular_time(&self) -> chrono::DateTime{ NaiveDateTime::new( - NaiveDate::from_ymd_opt( - self.get_year() as i32, - self.get_month() as u32, - self.get_days() as u32, - ) - .unwrap(), - NaiveTime::from_hms_opt( - self.get_hours() as u32, - self.get_minutes() as u32, - self.get_seconds() as u32, - ) - .unwrap(), - ) - .and_utc() + NaiveDate::from_ymd_opt(self.get_year() as i32, self.get_month() as u32, self.get_days() as u32).unwrap(), + NaiveTime::from_hms_opt(self.get_hours() as u32, self.get_minutes() as u32, self.get_seconds() as u32).unwrap() + ).and_utc() } } -impl RmcSerialize for KerberosDateTime { - fn serialize(&self, writer: &mut impl Write) -> Result<()> { +impl RmcSerialize for KerberosDateTime{ + fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { Ok(self.0.serialize(writer)?) } - fn deserialize(reader: &mut impl Read) -> Result { + fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result { Ok(Self(u64::deserialize(reader)?)) } } #[derive(Pod, Zeroable, Copy, Clone)] #[repr(C, packed)] -pub struct TicketInternalData { +pub struct TicketInternalData{ pub issued_time: KerberosDateTime, - pub pid: PID, - pub session_key: [u8; SESSION_KEY_LENGTH], + pub pid: u32, + pub session_key: [u8; 32], } -impl TicketInternalData { - pub(crate) fn new(pid: PID) -> Self { - Self { +impl TicketInternalData{ + pub(crate) fn new(pid: u32) -> Self{ + Self{ issued_time: KerberosDateTime::now(), pid, - session_key: rand::random(), + session_key: rand::random() } } - pub(crate) fn encrypt(&self, key: [u8; 16]) -> Box<[u8]> { + pub(crate) fn encrypt(&self, key: [u8; 16]) -> Box<[u8]>{ let mut data = bytes_of(self).to_vec(); let mut rc4: StreamCipherCoreWrapper> = Rc4::new_from_slice(&key).unwrap(); @@ -166,58 +117,53 @@ impl TicketInternalData { let mut hmac = ::new_from_slice(&key).unwrap(); - hmac.write_all(&data[..]) - .expect("failed to write data to hmac"); + hmac.write_all(&data[..]).expect("failed to write data to hmac"); let hmac_result = &hmac.finalize().into_bytes()[..]; - data.write_all(&hmac_result) - .expect("failed to write data to vec"); + data.write_all(&hmac_result).expect("failed to write data to vec"); data.into_boxed_slice() } } -#[derive(Pod, Zeroable, Debug, Copy, Clone)] +#[derive(Pod, Zeroable, Copy, Clone)] #[repr(C, packed)] -pub struct Ticket { - pub session_key: [u8; SESSION_KEY_LENGTH], - pub pid: PID, +pub struct Ticket{ + pub session_key: [u8; 32], + pub pid: u32, } -impl Ticket { - pub fn encrypt(&self, key: [u8; 16], internal_data: &[u8]) -> Box<[u8]> { +impl Ticket{ + pub fn encrypt(&self, key: [u8; 16], internal_data: &[u8]) -> Box<[u8]>{ let mut data = bytes_of(self).to_vec(); - internal_data - .serialize(&mut data) - .expect("unable to write to vec"); + internal_data.serialize(&mut data).expect("unable to write to vec"); let mut rc4: StreamCipherCoreWrapper> = Rc4::new_from_slice(&key).unwrap(); rc4.apply_keystream(&mut data); let mut hmac = ::new_from_slice(&key).unwrap(); - hmac.write_all(&data[..]) - .expect("failed to write data to hmac"); + hmac.write_all(&data[..]).expect("failed to write data to hmac"); let hmac_result = &hmac.finalize().into_bytes()[..]; - data.write_all(&hmac_result) - .expect("failed to write data to vec"); + data.write_all(&hmac_result).expect("failed to write data to vec"); data.into_boxed_slice() } } + #[cfg(test)] -mod test { +mod test{ use crate::kerberos::KerberosDateTime; #[test] - fn kerberos_time_convert_test() { + fn kerberos_time_convert_test(){ let time = KerberosDateTime(135904948834); println!("{}", time.to_regular_time().to_rfc2822()); } -} +} \ No newline at end of file diff --git a/rnex-core/src/lib.rs b/rnex-core/src/lib.rs index 28bdd48..3920565 100644 --- a/rnex-core/src/lib.rs +++ b/rnex-core/src/lib.rs @@ -4,10 +4,7 @@ #![allow(async_fn_in_trait)] //#![warn(missing_docs)] -#[cfg(feature = "big_pid")] -pub type PID = u64; -#[cfg(not(feature = "big_pid"))] -pub type PID = u32; + extern crate self as rnex_core; @@ -15,18 +12,18 @@ pub mod prudp; pub mod rmc; //mod protocols; -pub mod common; -pub mod executables; pub mod grpc; pub mod kerberos; pub mod nex; -pub mod reggie; pub mod result; +pub mod versions; +pub mod common; +pub mod reggie; pub mod rnex_proxy_common; pub mod util; -pub mod versions; +pub mod executables; pub use macros::*; -pub mod config { +pub mod config{ pub const FEATURE_HAS_STRUCT_HEADER: bool = cfg!(feature = "rmc_struct_header"); } diff --git a/rnex-core/src/main.rs b/rnex-core/src/main.rs new file mode 100644 index 0000000..eda5915 --- /dev/null +++ b/rnex-core/src/main.rs @@ -0,0 +1,127 @@ +#![allow(dead_code)] +#![allow(async_fn_in_trait)] +//#![warn(missing_docs)] + +//! # Splatoon RNEX server +//! +//! This server still includes the code for rnex itself as this is the first rnex server and thus +//! also the first and only current usage of rnex, expect this and rnex to be split into seperate +//! repos soon. + +extern crate self as rust_nex; + +use once_cell::sync::Lazy; +use std::hint::black_box; + +mod prudp; +pub mod rmc; +//mod protocols; + +mod grpc; +mod kerberos; +mod nex; +mod result; +mod versions; +pub mod reggie; +pub mod util; +pub mod common; + +pub mod config{ + pub const FEATURE_HAS_STRUCT_HEADER: bool = cfg!(feature = "rmc_struct_header"); +} + +use std::io::Cursor; +use std::ops::Deref; +use rnex_core::kerberos::KerberosDateTime; +use rnex_core::rmc::structures::matchmake::{AutoMatchmakeParam, Gathering, MatchmakeParam, MatchmakeSession, MatchmakeSessionSearchCriteria}; +use rnex_core::rmc::structures::RmcSerialize; +use rnex_core::rmc::structures::variant::Variant; + +static DUMMY: Lazy = Lazy::new(|| AutoMatchmakeParam{ + additional_participants: vec![1,2,3,4], + auto_matchmake_option: 10, + gid_for_participation_check: 9, + join_message: "hi".to_string(), + participation_count: 32, + target_gids: vec![45,2,51,1,1,1,1], + search_criteria: vec![MatchmakeSessionSearchCriteria{ + attribs: vec!["hi".to_string(), "ig".to_string(), "gotta put data here".to_string()], + exclude_locked: true, + exclude_non_host_pid: false, + exclude_system_password_set: true, + exclude_user_password_set: false, + game_mode: "some gamemode".to_string(), + matchmake_param: MatchmakeParam{ + params: vec![ + ("SR".to_string(), Variant::Bool(true)), + ("SR2".to_string(), Variant::Double(1.0)), + ("SR3".to_string(), Variant::SInt64(42)), + ("SR4".to_string(), Variant::String("test".to_string())) + ] + }, + matchmake_system_type: "some type".to_string(), + maximum_participants: "???".to_string(), + minimum_participants: "-99".to_string(), + refer_gid: 123, + selection_method: 9999999, + vacant_only: true, + vacant_participants: 1000 + }], + matchmake_session: MatchmakeSession{ + refer_gid: 10, + matchmake_system_type: 139, + matchmake_param: MatchmakeParam{ + params: vec![ + ("QSR".to_string(), Variant::Bool(false)), + ("SRQ2".to_string(), Variant::Double(1.1)), + ("SQR3".to_string(), Variant::SInt64(422)), + ("SDR4".to_string(), Variant::String("tetst".to_string())) + ] + }, + participation_count: 99, + application_buffer: vec![1,2,3,4,5,6,7,8,9], + attributes: vec![10,20,99,100000], + datetime: KerberosDateTime::now(), + gamemode: 111, + open_participation: false, + option0: 100, + progress_score: 1, + system_password_enabled: false, + user_password: "aaa".to_string(), + session_key: vec![91,123,5,2,1,2,4,124,4], + user_password_enabled: false, + gathering: Gathering{ + minimum_participants: 1, + maximum_participants: 12, + description: "aaargh".to_string(), + flags: 100, + host_pid: 999999919, + owner_pid: 138830, + participant_policy: 1, + policy_argument: 99837, + self_gid: 129, + state: 1389488 + } + } +}); + +static DUMMY_SER: Lazy> = Lazy::new(|| serialize_to_vec(DUMMY.deref())); + +fn serialize_to_vec(r: &impl RmcSerialize) -> Vec{ + let vec = r.to_data(); + + vec.unwrap() +} + +fn read_struct(r: &[u8]) -> T{ + T::deserialize(&mut Cursor::new(r)).unwrap() +} + +fn main(){ + for _ in 0..10000000 { + let v = serialize_to_vec(black_box(DUMMY.deref())); + let u = read_struct::(black_box(DUMMY_SER.deref().as_slice())); + black_box(v); + black_box(u); + } +} \ No newline at end of file diff --git a/rnex-core/src/nex/account.rs b/rnex-core/src/nex/account.rs index eb542ff..75c53ce 100644 --- a/rnex-core/src/nex/account.rs +++ b/rnex-core/src/nex/account.rs @@ -1,32 +1,39 @@ use macros::RmcSerialize; -use rnex_core::PID; - -#[derive(RmcSerialize, Clone)] -pub struct Account { - pub pid: PID, +#[derive(RmcSerialize)] +#[derive(Clone)] +pub struct Account{ + pub pid: u32, pub username: String, - pub kerbros_password: Box<[u8]>, + pub kerbros_password: [u8; 16], } -impl Account { - pub fn new(pid: PID, username: &str, passwd: &str) -> Self { - Self { - kerbros_password: passwd.as_bytes().into(), +impl Account{ + pub fn new(pid: u32, username: &str, passwd: &str) -> Self{ + let passwd_data = passwd.as_bytes(); + + let mut passwd = [0u8; 16]; + + for (idx, byte) in passwd_data.iter().enumerate(){ + passwd[idx] = *byte; + } + + Self{ + kerbros_password: passwd, username: username.into(), - pid, + pid } } - pub fn new_raw_password(pid: PID, username: &str, passwd: &[u8]) -> Self { - Self { - kerbros_password: passwd.into(), + pub fn new_raw_password(pid: u32, username: &str, passwd: [u8; 16]) -> Self{ + Self{ + kerbros_password: passwd, username: username.into(), - pid, + pid } } - pub fn get_login_data(&self) -> (PID, &[u8]) { - (self.pid, &self.kerbros_password) + pub fn get_login_data(&self) -> (u32, [u8; 16]){ + (self.pid, self.kerbros_password) } -} +} \ No newline at end of file diff --git a/rnex-core/src/nex/auth_handler.rs b/rnex-core/src/nex/auth_handler.rs index a5ffe2b..9b67fca 100644 --- a/rnex-core/src/nex/auth_handler.rs +++ b/rnex-core/src/nex/auth_handler.rs @@ -1,23 +1,19 @@ +use std::hash::{DefaultHasher, Hasher}; +use std::net::SocketAddrV4; +use std::sync::Arc; use crate::grpc::account; -use crate::reggie::{RemoteEdgeNodeHolder, RemoteEdgeNodeManagement}; -use crate::{define_rmc_proto, kerberos}; -use cfg_if::cfg_if; -use log::{info, warn}; -use macros::rmc_struct; -use rnex_core::PID; -use rnex_core::kerberos::{KerberosDateTime, Ticket, derive_key}; +use rnex_core::kerberos::{derive_key, KerberosDateTime, Ticket}; use rnex_core::nex::account::Account; -use rnex_core::rmc::protocols::OnlyRemote; use rnex_core::rmc::protocols::auth::{Auth, RawAuth, RawAuthInfo, RemoteAuth}; use rnex_core::rmc::response::ErrorCode; use rnex_core::rmc::response::ErrorCode::Core_Unknown; use rnex_core::rmc::structures::any::Any; use rnex_core::rmc::structures::connection_data::ConnectionData; -use rnex_core::rmc::structures::connection_data::ConnectionDataOld; use rnex_core::rmc::structures::qresult::QResult; -use std::hash::{DefaultHasher, Hasher}; -use std::net::SocketAddrV4; -use std::sync::{Arc, LazyLock}; +use crate::{define_rmc_proto, kerberos}; +use macros::rmc_struct; +use crate::reggie::{RemoteEdgeNodeHolder, RemoteEdgeNodeManagement}; +use rnex_core::rmc::protocols::OnlyRemote; define_rmc_proto!( proto AuthClientProtocol{ @@ -34,8 +30,8 @@ pub struct AuthHandler { } pub fn generate_ticket( - source_act_login_data: (PID, &[u8]), - dest_act_login_data: (PID, &[u8]), + source_act_login_data: (u32, [u8; 16]), + dest_act_login_data: (u32, [u8; 16]), ) -> Box<[u8]> { let source_key = derive_key(source_act_login_data.0, source_act_login_data.1); let dest_key = derive_key(dest_act_login_data.0, dest_act_login_data.1); @@ -51,34 +47,8 @@ pub fn generate_ticket( encrypted_session_ticket } -pub fn generate_ticket_with_string_user_key( - source_act: PID, - dest_act_login_data: (PID, &[u8]), -) -> (String, Box<[u8]>) { - let source_key: [u8; 8] = rand::random(); - let key_string = hex::encode(source_key); - let key_data: [u8; 16] = key_string.as_bytes().try_into().unwrap(); - let dest_key = derive_key(dest_act_login_data.0, dest_act_login_data.1); - - let internal_data = kerberos::TicketInternalData::new(source_act); - - let encrypted_inner = internal_data.encrypt(dest_key); - let encrypted_session_ticket = Ticket { - pid: dest_act_login_data.0, - session_key: internal_data.session_key, - } - .encrypt(key_data, &encrypted_inner); - - (key_string, encrypted_session_ticket) -} - -async fn get_login_data_by_pid(pid: PID) -> Option<(PID, Box<[u8]>)> { - if pid == GUEST_ACCOUNT.pid { - let source_login_data = GUEST_ACCOUNT.get_login_data(); - - return Some((source_login_data.0, source_login_data.1.into())); - } +async fn get_login_data_by_pid(pid: u32) -> Option<(u32, [u8; 16])> { let Ok(mut client) = account::Client::new().await else { return None; }; @@ -87,253 +57,133 @@ async fn get_login_data_by_pid(pid: PID) -> Option<(PID, Box<[u8]>)> { return None; }; - Some((pid, passwd.into())) + Some((pid, passwd)) } -fn station_url_from_sock_addr(sock_addr: SocketAddrV4) -> String { +fn station_url_from_sock_addr(sock_addr: SocketAddrV4) -> String{ format!( "prudps:/PID=2;sid=1;stream=10;type=2;address={};port={};CID=1", - sock_addr.ip(), - sock_addr.port() + sock_addr.ip(), sock_addr.port() ) } -static GUEST_ACCOUNT: LazyLock = - LazyLock::new(|| Account::new(100, "guest", "MMQea3n!fsik")); +impl Auth for AuthHandler { + async fn login(&self, _name: String) -> Result<(), ErrorCode> { + todo!() + } -impl AuthHandler { - pub async fn generate_ticket_from_name( + async fn login_ex( &self, - name: &str, - ) -> Result<(PID, Box<[u8]>), ErrorCode> { - #[cfg(feature = "guest_login")] - { - if name == GUEST_ACCOUNT.username { - let source_login_data = GUEST_ACCOUNT.get_login_data(); - let destination_login_data = self.destination_server_acct.get_login_data(); - - return Ok(( - source_login_data.0, - generate_ticket(source_login_data, destination_login_data), - )); - } - } + name: String, + _extra_data: Any, + ) -> Result<(QResult, u32, Vec, ConnectionData, String), ErrorCode> { let Ok(pid) = name.parse() else { - warn!("unable to connect to parse pid: {}", name); return Err(ErrorCode::Core_InvalidArgument); }; let Ok(mut client) = account::Client::new().await else { - warn!("unable to connect to grpc"); return Err(ErrorCode::Core_Exception); }; let Ok(passwd) = client.get_nex_password(pid).await else { - warn!("unable to get nex password for pid: {}:", pid); return Err(ErrorCode::Core_Exception); }; - let source_login_data = (pid, &passwd[..]); - println!("{}, {:?}", pid, passwd); + let source_login_data = (pid, passwd); let destination_login_data = self.destination_server_acct.get_login_data(); - Ok(( - pid, - generate_ticket(source_login_data, destination_login_data), - )) - } - - pub async fn generate_ticket_from_name_string_user_key( - &self, - name: &str, - ) -> Result<(PID, String, Box<[u8]>), ErrorCode> { - { - if name == GUEST_ACCOUNT.username { - let source_login_data = GUEST_ACCOUNT.get_login_data(); - let destination_login_data = self.destination_server_acct.get_login_data(); - let ticket = generate_ticket_with_string_user_key( - source_login_data.0, - destination_login_data, - ); - - return Ok((source_login_data.0, ticket.0, ticket.1)); - } - } - let Ok(pid) = name.parse() else { - warn!("unable to connect to parse pid: {}", name); - return Err(ErrorCode::Core_InvalidArgument); - }; - let destination_login_data = self.destination_server_acct.get_login_data(); - - let data = generate_ticket_with_string_user_key(pid, destination_login_data); - Ok((pid, data.0, data.1)) - } -} - -impl Auth for AuthHandler { - async fn login( - &self, - name: String, - ) -> Result<(QResult, PID, Vec, ConnectionDataOld, String), ErrorCode> { - let (pid, ticket) = self.generate_ticket_from_name(&name).await?; + let ticket = generate_ticket(source_login_data, destination_login_data); let result = QResult::success(Core_Unknown); let mut hasher = DefaultHasher::new(); hasher.write(name.as_bytes()); - + let Ok(addr) = self.control_server.get_url(hasher.finish()).await else { - warn!("no secure proxies"); return Err(ErrorCode::Core_Exception); }; - let connection_data = ConnectionDataOld { + let connection_data = ConnectionData { station_url: station_url_from_sock_addr(addr), special_station_url: "".to_string(), + //date_time: KerberosDateTime::new(1,1,1,1,1,1), + date_time: KerberosDateTime::now(), special_protocols: Vec::new(), }; - let ret = ( + Ok(( result, - pid, + source_login_data.0, ticket.into(), connection_data, - self.build_name.to_string(), - ); - - info!("data: {:?}", ret); - Ok(ret) + self.build_name.to_string() //format!("{}; Rust NEX Version {} by DJMrTV", self.build_name, env!("CARGO_PKG_VERSION")), + )) } - cfg_if! { - if #[cfg(feature = "nx")]{ - async fn login_ex( - &self, - name: String, - _extra_data: Any, - ) -> Result<(QResult, PID, Vec, ConnectionData, String, String), ErrorCode> { - let (pid, key, ticket) = self.generate_ticket_from_name_string_user_key(&name).await?; + async fn request_ticket( + &self, + source_pid: u32, + destination_pid: u32, + ) -> Result<(QResult, Vec), ErrorCode> { + let Some(source_login_data) = get_login_data_by_pid(source_pid).await else { + return Err(ErrorCode::Core_Exception); + }; - let result = QResult::success(Core_Unknown); - - let mut hasher = DefaultHasher::new(); - - hasher.write(name.as_bytes()); - - let Ok(addr) = self.control_server.get_url(hasher.finish()).await else { - warn!("no secure proxies"); - return Err(ErrorCode::Core_Exception); - }; - - let connection_data = ConnectionData { - station_url: station_url_from_sock_addr(addr), - special_station_url: "".to_string(), - //date_time: KerberosDateTime::new(1,1,1,1,1,1), - date_time: KerberosDateTime::now(), - special_protocols: Vec::new(), - }; - - let ret = ( - result, - pid, - ticket.into(), - connection_data, - self.build_name.to_string(), - key - ); - - info!("data: {:?}", ret); - Ok(ret) - } - async fn request_ticket( - &self, - source_pid: PID, - destination_pid: PID, - ) -> Result<(QResult, Vec, String), ErrorCode> { - let Some((pid, _)) = get_login_data_by_pid(source_pid).await else { - return Err(ErrorCode::Core_Exception); - }; - - let desgination_login_data = if destination_pid == self.destination_server_acct.pid { - self.destination_server_acct.get_login_data() - } else { - return Err(ErrorCode::RendezVous_InvalidOperation); - }; - - let result = QResult::success(Core_Unknown); - - let ticket = generate_ticket_with_string_user_key(pid, desgination_login_data); - - Ok((result, ticket.1.into(), ticket.0)) - } + let desgination_login_data = if destination_pid == self.destination_server_acct.pid { + self.destination_server_acct.get_login_data() } else { - async fn login_ex( - &self, - name: String, - _extra_data: Any, - ) -> Result<(QResult, PID, Vec, ConnectionData, String), ErrorCode> { - let (pid, ticket) = self.generate_ticket_from_name(&name).await?; + let Some(login) = get_login_data_by_pid(destination_pid).await else { + return Err(ErrorCode::Core_Exception); + }; + login + }; - let result = QResult::success(Core_Unknown); + let result = QResult::success(Core_Unknown); - let mut hasher = DefaultHasher::new(); + let ticket = generate_ticket(source_login_data, desgination_login_data); - hasher.write(name.as_bytes()); - - let Ok(addr) = self.control_server.get_url(hasher.finish()).await else { - warn!("no secure proxies"); - return Err(ErrorCode::Core_Exception); - }; - - let connection_data = ConnectionData { - station_url: station_url_from_sock_addr(addr), - special_station_url: "".to_string(), - //date_time: KerberosDateTime::new(1,1,1,1,1,1), - date_time: KerberosDateTime::now(), - special_protocols: Vec::new(), - }; - - let ret = ( - result, - pid, - ticket.into(), - connection_data, - self.build_name.to_string(), - ); - - info!("data: {:?}", ret); - Ok(ret) - } - async fn request_ticket( - &self, - source_pid: PID, - destination_pid: PID, - ) -> Result<(QResult, Vec), ErrorCode> { - let Some((pid, passwd)) = get_login_data_by_pid(source_pid).await else { - return Err(ErrorCode::Core_Exception); - }; - - let desgination_login_data = if destination_pid == self.destination_server_acct.pid { - self.destination_server_acct.get_login_data() - } else { - return Err(ErrorCode::RendezVous_InvalidOperation); - }; - - let result = QResult::success(Core_Unknown); - - let ticket = generate_ticket((pid, &passwd[..]), desgination_login_data); - - Ok((result, ticket.into())) - } - } + Ok((result, ticket.into())) } async fn get_pid(&self, _username: String) -> Result { Err(ErrorCode::Core_Exception) } - async fn get_name(&self, _pid: PID) -> Result { + async fn get_name(&self, _pid: u32) -> Result { Err(ErrorCode::Core_Exception) } } + +#[cfg(test)] +mod test { + use rnex_core::rmc::structures::connection_data::ConnectionData; + use rnex_core::rmc::structures::qresult::QResult; + use rnex_core::rmc::structures::RmcSerialize; + use rnex_core::rmc::response::RMCResponse; + use std::io::Cursor; + + + + #[test] + fn test() { + + let stuff = hex::decode("200100000a0106000000028000000100010051b3995774000000a6321c7f78847c1c5e9fb825eb26bd91841f1a40d92fc694159666119cb13527f1463ac48ad42a63e6613ede67041554b1770978112e6f1f3e177a2bfc75933216dbe38f70133a1eb28e2ae32a4b5c4b0c3e3efd4c02907992e259b257270b57a9dbe7792f4721b07f8fafb9e32d50f2555c616a015c0000004b007072756470733a2f5049443d323b7369643d313b73747265616d3d31303b747970653d323b616464726573733d322e3234332e39352e3131333b706f72743d31303030313b4349443d3100000000000100002c153ba51f00000033006272616e63683a6f726967696e2f70726f6a6563742f7775702d61676d6a206275696c643a335f385f31355f323030345f3000").unwrap(); + let stuff = RMCResponse::new(&mut Cursor::new(stuff)).unwrap(); + + let rnex_core::rmc::response::RMCResponseResult::Success { .. } = stuff.response_result else { + panic!() + }; + + + + // let stuff = hex::decode("0100010051B399577400000085F1736FCFBE93660275A3FE36FED6C2EFC57222AC99A9219CF54170A415B02DF1463AC48AD42A6307813FDE67041554B177097832ED000F892D9551A09F88E9CB0388DC1BC9527CC7384556A3287B2A349ABBF7E34A5A3EC14C2287CC7F78DA616BC3B03A035347FBD2E9A505C8EF42447CD809015F0000004E007072756470733A2F73747265616D3D31303B747970653D323B616464726573733D3139322E3136382E3137382E3132303B706F72743D31303030313B4349443D313B5049443D323B7369643D310000000000010000CDF53AA51F00000033006272616E63683A6F726967696E2F70726F6A6563742F7775702D61676D6A206275696C643A335F385F31355F323030345F3000").unwrap(); + let stuff = hex::decode("0100010051b399577400000037d3d4814d2b16dd546c94a75d32637b45f856b5abe73cf26cfaa235c5f2c1cef1463ac48ad42a637d873fde67041554b177097880cfa7e10bb810eaf686bfb0a0cf3d65b1f476ebc046d0855327986f557dca14fbb8594883c186b863f2206f22baa0309dbcc81da2f883cb2cdc12628ec7fced015c0000004b007072756470733a2f5049443d323b7369643d313b73747265616d3d31303b747970653d323b616464726573733d322e3234332e39352e3131333b706f72743d31303030313b4349443d310000000000010000b7f33aa51f00000033006272616e63683a6f726967696e2f70726f6a6563742f7775702d61676d6a206275696c643a335f385f31355f323030345f3000").unwrap(); + + let data = <(QResult, u32, Vec, ConnectionData, String) as RmcSerialize>::deserialize( + &mut Cursor::new(stuff), + ).unwrap(); + + println!("data: {:?}", data); + } +} diff --git a/rnex-core/src/nex/common.rs b/rnex-core/src/nex/common.rs deleted file mode 100644 index 48b080d..0000000 --- a/rnex-core/src/nex/common.rs +++ /dev/null @@ -1,95 +0,0 @@ -use rnex_core::prudp::station_url::StationUrl; -use rnex_core::prudp::station_url::UrlOptions::{ - Address, NatFiltering, NatMapping, NatType, Port, PrincipalID, RVConnectionID, -}; -use rnex_core::prudp::station_url::nat_types::PUBLIC; -use rnex_core::rmc::response::ErrorCode::Core_Exception; - -use rnex_core::prudp::socket_addr::PRUDPSockAddr; -use rnex_core::rmc::response::ErrorCode; - -use rnex_core::PID; - -pub async fn get_station_urls( - station_urls: &[StationUrl], - addr: PRUDPSockAddr, - pid: PID, - cid: u32, -) -> Result, ErrorCode> { - let mut public_station: Option = None; - let mut private_station: Option = None; - - for station in station_urls { - let is_public = station.options.iter().any(|v| { - if let NatType(v) = v { - if *v & PUBLIC != 0 { - return true; - } - } - false - }); - - let Some(nat_filtering) = station.options.iter().find_map(|v| match v { - NatFiltering(v) => Some(v), - _ => None, - }) else { - return Err(Core_Exception); - }; - - let Some(nat_mapping) = station.options.iter().find_map(|v| match v { - NatMapping(v) => Some(v), - _ => None, - }) else { - return Err(Core_Exception); - }; - - if !is_public || (*nat_filtering == 0 && *nat_mapping == 0) { - private_station = Some(station.clone()); - } - - if is_public { - public_station = Some(station.clone()); - } - } - - let Some(mut private_station) = private_station else { - return Err(Core_Exception); - }; - - let mut public_station = if let Some(public_station) = public_station { - public_station - } else { - let mut public_station = private_station.clone(); - - public_station.options.retain(|v| match v { - Address(_) | Port(_) | NatFiltering(_) | NatMapping(_) | NatType(_) => false, - _ => true, - }); - - public_station - .options - .push(Address(addr.regular_socket_addr.ip().clone())); - public_station - .options - .push(Port(addr.regular_socket_addr.port())); - public_station.options.push(NatFiltering(0)); - public_station.options.push(NatMapping(0)); - public_station.options.push(NatType(3)); - - public_station - }; - - let both = [&mut public_station, &mut private_station]; - - for station in both { - station.options.retain(|v| match v { - PrincipalID(_) | RVConnectionID(_) => false, - _ => true, - }); - - station.options.push(PrincipalID(pid)); - station.options.push(RVConnectionID(cid)); - } - - Ok(vec![public_station]) -} diff --git a/rnex-core/src/nex/datastore.rs b/rnex-core/src/nex/datastore.rs deleted file mode 100644 index fad7300..0000000 --- a/rnex-core/src/nex/datastore.rs +++ /dev/null @@ -1,1042 +0,0 @@ -use crate::nex::user::User; -use rnex_core::executables::common::{ - RNEX_DATASTORE_S3_BUCKET, RNEX_DATASTORE_S3_ENDPOINT, get_db, -}; -use rnex_core::kerberos::KerberosDateTime; -use rnex_core::nex::s3presigner::S3Presigner; -use rnex_core::rmc::protocols::datastore::{ - BufferQueueParam, CompletePostParam, DataStoreCustomRankingResult, - DataStoreGetCustomRankingByDataIDParam, DataStorePrepareGetParam, DataStoreReqGetInfo, - DataStoreSearchParam, GetMetaInfo, GetMetaParam, KeyValue, Permission, PersistenceTarget, - RateCustomRankingParam, RatingInfo, RatingInfoWithSlot, -}; -use rnex_core::rmc::protocols::datastore::{DataStore, PreparePostParam, ReqPostInfo}; -use rnex_core::rmc::response::ErrorCode; -use rnex_core::rmc::structures::qbuffer::QBuffer; -use rnex_core::rmc::structures::qresult::QResult; -use sqlx::types::time; - -fn map_row_to_meta_info( - row_data_id: i64, - row_owner: i32, - row_size: i32, - row_name: String, - row_data_type: i16, - row_meta_binary: Vec, - row_permission: i16, - row_permission_recipients: Vec, - row_delete_permission: i16, - row_delete_permission_recipients: Vec, - row_period: i16, - row_refer_data_id: i64, - row_flag: i32, - row_tags: Vec, - row_creation_date: chrono::NaiveDateTime, - row_update_date: chrono::NaiveDateTime, - ratings: Vec, -) -> GetMetaInfo { - GetMetaInfo { - dataid: row_data_id as u64, - owner: row_owner as u32, - size: row_size as u32, - name: row_name, - data_type: row_data_type as u16, - meta_binary: QBuffer(row_meta_binary), - permission: Permission { - permission: row_permission as u8, - recipient_ids: row_permission_recipients - .into_iter() - .map(|id| id as u32) - .collect(), - }, - del_permission: Permission { - permission: row_delete_permission as u8, - recipient_ids: row_delete_permission_recipients - .into_iter() - .map(|id| id as u32) - .collect(), - }, - period: row_period as u16, - status: 0, - referred_count: 0, - refer_dat_id: row_refer_data_id as u32, - flag: row_flag as u32, - tags: row_tags, - expire_time: KerberosDateTime::from_u64(0x9C3F3E0000), - created_time: KerberosDateTime::from_naive(row_creation_date), - updated_time: KerberosDateTime::from_naive(row_update_date), - referred_time: KerberosDateTime::from_naive(row_creation_date), - ratings, - } -} - -async fn check_object_availability(data_id: u64, password: u64) -> Result<(), ErrorCode> { - let row = sqlx::query!( - r#" - SELECT under_review, access_password - FROM datastore.objects - WHERE data_id = $1 AND upload_completed = TRUE AND deleted = FALSE - "#, - data_id as i64 - ) - .fetch_optional(get_db()) - .await - .map_err(|e| { - eprintln!("Availability check DB error: {:?}", e); - ErrorCode::DataStore_SystemFileError - })? - .ok_or(ErrorCode::DataStore_NotFound)?; - - let access_password = row.access_password as u64; - if access_password != 0 && access_password != password { - return Err(ErrorCode::DataStore_InvalidPassword); - } - - if row.under_review { - return Err(ErrorCode::DataStore_UnderReviewing); - } - - Ok(()) -} - -async fn get_object_ratings( - data_id: u64, - password: u64, -) -> Result, ErrorCode> { - check_object_availability(data_id, password).await?; - - let rows = sqlx::query!( - r#" - SELECT slot, total_value, count, initial_value - FROM datastore.object_ratings - WHERE data_id = $1 - "#, - data_id as i64 - ) - .fetch_all(get_db()) - .await - .map_err(|e| { - eprintln!("Ratings fetch error: {:?}", e); - ErrorCode::DataStore_SystemFileError - })?; - - let ratings = rows - .into_iter() - .map(|row| RatingInfoWithSlot { - slot: row.slot as i8, - rating: RatingInfo { - total_value: row.total_value.unwrap_or(0), - count: row.count as u32, - initial_value: row.initial_value.unwrap_or(0), - }, - }) - .collect(); - - Ok(ratings) -} - -async fn get_object_info_by_data_id(data_id: u64, password: u64) -> Result { - check_object_availability(data_id, password).await?; - - let row = sqlx::query!( - r#"SELECT data_id, owner, size, name, data_type, meta_binary, - permission, permission_recipients, delete_permission, delete_permission_recipients, - period, refer_data_id, flag, tags, creation_date, update_date - FROM datastore.objects WHERE data_id = $1"#, - data_id as i64 - ) - .fetch_optional(get_db()) - .await - .map_err(|_| ErrorCode::DataStore_SystemFileError)? - .ok_or(ErrorCode::DataStore_NotFound)?; - - let ratings = get_object_ratings(data_id, password).await?; - - Ok(map_row_to_meta_info( - row.data_id, - row.owner.unwrap_or(0), - row.size.unwrap_or(0), - row.name.unwrap_or_default(), - row.data_type.unwrap_or(0) as i16, - row.meta_binary.unwrap_or_default(), - row.permission.unwrap_or(0) as i16, - row.permission_recipients - .unwrap_or_default() - .into_iter() - .map(|id| id as i64) - .collect(), - row.delete_permission.unwrap_or(0) as i16, - row.delete_permission_recipients - .unwrap_or_default() - .into_iter() - .map(|id| id as i64) - .collect(), - row.period.unwrap_or(0) as i16, - row.refer_data_id.unwrap_or(0), - row.flag.unwrap_or(0), - row.tags.unwrap_or_default(), - row.creation_date - .map(|dt| { - chrono::NaiveDateTime::new( - chrono::NaiveDate::from_ymd_opt(dt.year(), dt.month() as u32, dt.day() as u32) - .unwrap(), - chrono::NaiveTime::from_hms_opt( - dt.hour() as u32, - dt.minute() as u32, - dt.second() as u32, - ) - .unwrap(), - ) - }) - .unwrap_or_default(), - row.update_date - .map(|dt| { - chrono::NaiveDateTime::new( - chrono::NaiveDate::from_ymd_opt(dt.year(), dt.month() as u32, dt.day() as u32) - .unwrap(), - chrono::NaiveTime::from_hms_opt( - dt.hour() as u32, - dt.minute() as u32, - dt.second() as u32, - ) - .unwrap(), - ) - }) - .unwrap_or_default(), - ratings, - )) -} - -async fn get_object_info_by_persistence_target( - target: PersistenceTarget, - password: u64, -) -> Result { - let row = sqlx::query!( - r#"SELECT data_id, owner, size, name, data_type, meta_binary, - permission, permission_recipients, delete_permission, delete_permission_recipients, - period, refer_data_id, flag, tags, creation_date, update_date, - access_password, under_review - FROM datastore.objects - WHERE owner = $1 AND persistence_slot_id = $2 - AND upload_completed = TRUE AND deleted = FALSE"#, - target.owner as i32, - target.persistence_slot_id as i16 - ) - .fetch_optional(get_db()) - .await - .map_err(|_| ErrorCode::DataStore_SystemFileError)? - .ok_or(ErrorCode::DataStore_NotFound)?; - - let db_password = row.access_password as u64; - if db_password != 0 && db_password != password { - return Err(ErrorCode::DataStore_InvalidPassword); - } - - if row.under_review { - return Err(ErrorCode::DataStore_UnderReviewing); - } - - let ratings = get_object_ratings(row.data_id as u64, password).await?; - - Ok(map_row_to_meta_info( - row.data_id, - row.owner.unwrap_or(0), - row.size.unwrap_or(0), - row.name.unwrap_or_default(), - row.data_type.unwrap_or(0) as i16, - row.meta_binary.unwrap_or_default(), - row.permission.unwrap_or(0) as i16, - row.permission_recipients - .unwrap_or_default() - .into_iter() - .map(|id| id as i64) - .collect(), - row.delete_permission.unwrap_or(0) as i16, - row.delete_permission_recipients - .unwrap_or_default() - .into_iter() - .map(|id| id as i64) - .collect(), - row.period.unwrap_or(0) as i16, - row.refer_data_id.unwrap_or(0), - row.flag.unwrap_or(0), - row.tags.unwrap_or_default(), - row.creation_date - .map(|dt| { - chrono::NaiveDateTime::new( - chrono::NaiveDate::from_ymd_opt(dt.year(), dt.month() as u32, dt.day() as u32) - .unwrap(), - chrono::NaiveTime::from_hms_opt( - dt.hour() as u32, - dt.minute() as u32, - dt.second() as u32, - ) - .unwrap(), - ) - }) - .unwrap_or_default(), - row.update_date - .map(|dt| { - chrono::NaiveDateTime::new( - chrono::NaiveDate::from_ymd_opt(dt.year(), dt.month() as u32, dt.day() as u32) - .unwrap(), - chrono::NaiveTime::from_hms_opt( - dt.hour() as u32, - dt.minute() as u32, - dt.second() as u32, - ) - .unwrap(), - ) - }) - .unwrap_or_default(), - ratings, - )) -} - -async fn get_buffer_queues_by_data_id_and_slot( - data_id: u64, - slot: u32, -) -> Result, ErrorCode> { - check_object_availability(data_id, 0).await?; - - let rows = sqlx::query!( - r#" - SELECT buffer - FROM datastore.buffer_queues - WHERE data_id = $1 AND slot = $2 - ORDER BY creation_date ASC - "#, - data_id as i64, - slot as i32 - ) - .fetch_all(get_db()) - .await - .map_err(|e| { - log::error!("Buffer queue fetch error: {:?}", e); - ErrorCode::DataStore_SystemFileError - })?; - - let buffer_queues = rows.into_iter().map(|row| QBuffer(row.buffer)).collect(); - - Ok(buffer_queues) -} - -fn verify_object_permission( - owner_id: u32, - viewer_id: u32, - permission: &Permission, -) -> Result<(), ErrorCode> { - if owner_id == viewer_id { - return Ok(()); - } - - match permission.permission { - 0 => Ok(()), // All can read - 1 => Err(ErrorCode::DataStore_PermissionDenied), // Friends only, unimplemented - 2 => { - // Recipient IDs can read - if permission.recipient_ids.contains(&viewer_id) { - Ok(()) - } else { - Err(ErrorCode::DataStore_PermissionDenied) - } - } - 3 => Err(ErrorCode::DataStore_PermissionDenied), // Owner only, redundant - _ => Err(ErrorCode::DataStore_InvalidArgument), // ??? haxx0r - } -} - -fn filter_properties_by_result_option(meta_info: &mut GetMetaInfo, result_option: u8) { - if (result_option & 0x01) == 0 { - meta_info.meta_binary = QBuffer(Vec::new()); - } - - if (result_option & 0x04) == 0 { - meta_info.ratings = Vec::new(); - } - - // No idea what the other things do. :shrug: -} - -// Dawg... -async fn get_custom_rankings_by_data_ids( - application_id: u32, - data_ids: Vec, -) -> Vec { - let mut results = Vec::with_capacity(data_ids.len()); - - let rows = sqlx::query!( - r#" - SELECT - rankings.data_id, - rankings.value - FROM datastore.object_custom_rankings rankings - JOIN UNNEST($1::bigint[]) WITH ORDINALITY AS rows(data_id, ord) - ON rankings.data_id = rows.data_id - AND rankings.application_id = $2 - ORDER BY rows.ord - "#, - &data_ids.iter().map(|&id| id as i64).collect::>(), - application_id as i32 - ) - .fetch_all(get_db()) - .await; - - let rows = match rows { - Ok(r) => r, - Err(e) => { - log::error!("Custom ranking query error: {:?}", e); - return results; - } - }; - - for row in rows { - let data_id = row.data_id as u64; - let score = row.value.unwrap_or(0) as u32; - - if let Ok(meta) = get_object_info_by_data_id(data_id, 0).await { - results.push(DataStoreCustomRankingResult { - order: 0, - score, - meta_info: meta, - }); - } else { - log::warn!("Could not find metadata for ranked object {}", data_id); - } - } - - results -} - -async fn get_user_course_object_ids(owner_pid: u32) -> Result, ErrorCode> { - let rows = sqlx::query!( - r#" - SELECT data_id - FROM datastore.objects - WHERE owner = $1 AND data_type > 2 AND data_type < 50 - "#, - owner_pid as i64 - ) - .fetch_all(get_db()) - .await - .map_err(|e| { - log::error!("error fetching course IDs for PID {}: {:?}", owner_pid, e); - ErrorCode::DataStore_SystemFileError - })?; - - let mut valid_ids = Vec::new(); - for row in rows { - let data_id = row.data_id as u64; - // always check avail - if check_object_availability(data_id, 0).await.is_ok() { - valid_ids.push(data_id); - } - } - - Ok(valid_ids) -} - -fn get_blacklist_1() -> Vec { - vec![ - "けされ", - "消され", - "削除され", - "リセットされ", - "BANされ", - "BANされ", - "キミのコース", - "君のコース", - "きみのコース", - "い い ね", - "遊びます", - "地震", - "震災", - "被災", - "津波", - "バンされ", - "い~ね", - "震度", - "じしん", - "banされ", - "くわしくは", - "詳しくは", - "ちんちん", - "ち0こ", - "bicth", - "い.い.ね", - "ナイ~ス", - "い&い", - "い-いね", - "いぃね", - "nigger", - "ngger", - "star if u", - "Star if u", - "Star if you", - "star if you", - "PENlS", - "マンコ", - "butthole", - "LILI", - "vagina", - "vagyna", - "うんち", - "うんこ", - "ウンコ", - "Iine", - "EENE", - "まんこ", - "ウンチ", - "niglet", - "nigglet", - "please like", - "きんたま", - "Butthole", - "llね", - "iいね", - "give a star", - "ちんぽ", - "亀頭", - "penis", - "ウンコ", - "plz more stars", - "star plz", - "い()ね", - "PLEASE star", - "Bitte Sterne", - ] - .into_iter() - .map(String::from) - .collect() -} - -fn get_blacklist_2() -> Vec { - vec![ - "ゼロから", - "0から", - "0から", - "い  い  ね", - "いい", - "東日本", - "大震", - ] - .into_iter() - .map(String::from) - .collect() -} - -fn get_blacklist_3() -> Vec { - vec![ - "いいね", - "下さい", - "ください", - "押して", - "おして", - "返す", - "かえす", - "星", - "してくれ", - "するよ", - "☆くれたら", - "☆あげます", - "★くれたら", - "★あげます", - "しね", - "ころす", - "ころされた", - "アナル", - "ファック", - "キンタマ", - "○ね", - "キチガイ", - "うんこ", - "KITIGAI", - "金玉", - "おっぱい", - "☆おす", - "☆押す", - "★おす", - "★押す", - "いいする", - "いいよ", - "イイネ", - "ケツ", - "うんち", - "かくせいざい", - "覚せい剤", - "シャブ", - "きんたま", - "ちんちん", - "おしっこ", - "ちんぽこ", - "ころして", - "グッド", - "グット", - "レ●プ", - "バーカ", - "きちがい", - "ちんげ", - "マンコ", - "まんこ", - "チンポ", - "クズ", - "ウンコ", - "ナイスおねがいします", - "penis", - "イイね", - "☆よろ", - "ナイス!して", - "ま/んこ", - "まん/こ", - ] - .into_iter() - .map(String::from) - .collect() -} - -impl DataStore for User { - async fn get_meta(&self, mut metaparam: GetMetaParam) -> Result { - let mut meta_info = if metaparam.dataid != 0 { - get_object_info_by_data_id(metaparam.dataid, metaparam.access_password).await? - } else { - get_object_info_by_persistence_target( - metaparam.persistence_target, - metaparam.access_password, - ) - .await? - }; - - let current_pid = self.pid; - verify_object_permission(meta_info.owner, current_pid, &meta_info.permission)?; - - filter_properties_by_result_option(&mut meta_info, metaparam.result_option); - - Ok(meta_info) - } - - async fn prepare_post_object( - &self, - postparam: PreparePostParam, - ) -> Result { - let recipient_ids: Vec = postparam - .permission - .recipient_ids - .iter() - .map(|&id| id as i32) - .collect(); - let del_recipient_ids: Vec = postparam - .del_permission - .recipient_ids - .iter() - .map(|&id| id as i32) - .collect(); - let now = time::OffsetDateTime::now_utc(); - - let row = sqlx::query!( - r#" - INSERT INTO datastore.objects ( - owner, size, name, data_type, meta_binary, - permission, permission_recipients, - delete_permission, delete_permission_recipients, - flag, period, refer_data_id, tags, - persistence_slot_id, extra_data, creation_date, update_date - ) VALUES ( - $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17 - ) RETURNING data_id - "#, - self.pid as i32, - postparam.size as i32, - postparam.name, - postparam.data_type as i32, - &postparam.meta_binary.0, - postparam.permission.permission as i32, - &recipient_ids, - postparam.del_permission.permission as i32, - &del_recipient_ids, - postparam.flag as i32, - postparam.period as i32, - postparam.refer_data_id as i64, - &postparam.tags, - postparam.persistence_init_param.persistence_slot_id as i32, - &postparam.extra_data, - time::PrimitiveDateTime::new(now.date(), now.time()), - time::PrimitiveDateTime::new(now.date(), now.time()) - ) - .fetch_one(get_db()) - .await - .map_err(|e| { - log::error!("DB Error: {:?}", e); - ErrorCode::DataStore_SystemFileError - })?; - - let data_id = row.data_id as u64; - let presigner = S3Presigner::new( - &format!("https://{}", *RNEX_DATASTORE_S3_ENDPOINT), - format!("{}", *RNEX_DATASTORE_S3_BUCKET), - ) - .await; - - let key = format!("data/{}.bin", data_id); - - let (upload_url, fields) = presigner.generate_presigned_post(&key).await; - - let form_fields = fields - .into_iter() - .map(|(k, v)| KeyValue { key: k, value: v }) - .collect(); - - Ok(ReqPostInfo { - dataid: data_id, - url: upload_url, - request_headers: vec![], - form_fields, - root_ca_cert: vec![], - }) - } - - async fn complete_post_object( - &self, - completeparam: CompletePostParam, - ) -> Result<(), ErrorCode> { - log::info!("Data ID: {:?}", completeparam.dataid); - log::info!("Success: {:?}", completeparam.success); - - let record = sqlx::query!( - r#"SELECT owner, under_review FROM datastore.objects WHERE data_id = $1"#, - completeparam.dataid as i64 - ) - .fetch_optional(get_db()) - .await - .map_err(|e| { - eprintln!("select error: {:?}", e); - ErrorCode::DataStore_SystemFileError - })?; - - let record = record.ok_or(ErrorCode::DataStore_NotFound)?; - - if record.under_review { - return Err(ErrorCode::DataStore_UnderReviewing); - } - - if record.owner.unwrap_or(0) as u32 != self.pid { - return Err(ErrorCode::DataStore_PermissionDenied); - } - - if completeparam.success { - sqlx::query!( - r#"UPDATE datastore.objects SET upload_completed = true WHERE data_id = $1"#, - completeparam.dataid as i64 - ) - .execute(get_db()) - .await - .map_err(|e| { - eprintln!("update error: {:?}", e); - ErrorCode::DataStore_SystemFileError - })?; - } else { - return Err(ErrorCode::Transport_TemporaryServerError); - } - - Ok(()) - } - - async fn rate_custom_ranking( - &self, - rankingparam: Vec, - ) -> Result<(), ErrorCode> { - for abcparam in rankingparam { - let exists = sqlx::query_scalar!( - r#"SELECT EXISTS(SELECT 1 FROM datastore.objects WHERE data_id = $1)"#, - abcparam.dataid as i64 - ) - .fetch_one(get_db()) - .await - .map_err(|_| ErrorCode::DataStore_SystemFileError)?; - - if !exists.unwrap_or(false) { - return Err(ErrorCode::DataStore_NotFound); - } - - sqlx::query!( - r#" - INSERT INTO datastore.object_custom_rankings (data_id, application_id, value) - VALUES ($1, $2, $3) - ON CONFLICT (data_id, application_id) - DO UPDATE SET value = datastore.object_custom_rankings.value + EXCLUDED.value - "#, - abcparam.dataid as i64, - abcparam.appid as i32, - abcparam.score as i32 - ) - .execute(get_db()) - .await - .map_err(|e| { - log::error!("update/insert error: {:?}", e); - ErrorCode::DataStore_SystemFileError - })?; - } - - Ok(()) - } - - async fn get_application_config(&self, appid: u32) -> Result, ErrorCode> { - const MAX_COURSE_UPLOADS: i32 = 100; - - let config = match appid { - 0 => vec![ - 0x00000001, - 0x00000032, - 0x00000096, - 0x0000012c, - 0x000001f4, - 0x00000320, - 0x00000514, - 0x000007d0, - 0x00000bb8, - 0x00001388, - MAX_COURSE_UPLOADS, - 0x00000014, - 0x0000001e, - 0x00000028, - 0x00000032, - 0x0000003c, - 0x00000046, - 0x00000050, - 0x0000005a, - 0x00000064, - 0x00000023, - 0x0000004b, - 0x00000023, - 0x0000004b, - 0x00000032, - 0x00000000, - 0x00000003, - 0x00000003, - 0x00000064, - 0x00000006, - 0x00000001, - 0x00000060, - 0x00000005, - 0x00000060, - 0x00000000, - 0x000007e4, - 0x00000001, - 0x00000001, - 0x0000000c, - 0x00000000, - ], - 1 => vec![ - 2, 1770179696, 1770179664, 1770179640, 1770180827, 1770180777, 1770180745, - 1770177625, 1770177590, - ], - 2 => vec![0x000007df, 0x0000000c, 0x00000016, 0x00000005, 0x00000000], - 10 => vec![35, 75, 96, 40, 5, 6], - _ => { - log::error!("unknown SMM app id: {}", appid); - return Err(ErrorCode::DataStore_Unknown); - } - }; - - Ok(config) - } - - async fn get_custom_ranking_by_data_id( - &self, - custom_ranking_param: DataStoreGetCustomRankingByDataIDParam, - ) -> Result<(Vec, Vec), ErrorCode> { - println!("appid: {:?}", custom_ranking_param.application_id); - println!("dataid list: {:?}", custom_ranking_param.data_id_list); - println!("result option: {:?}", custom_ranking_param.result_option); - - let mut ranking_results = get_custom_rankings_by_data_ids( - custom_ranking_param.application_id, - custom_ranking_param.data_id_list, - ) - .await; - - let mut q_results = Vec::with_capacity(ranking_results.len()); - - for result in &mut ranking_results { - if (custom_ranking_param.result_option & 0x01) == 0 { - result.meta_info.tags = Vec::new(); - } - - if (custom_ranking_param.result_option & 0x02) == 0 { - result.meta_info.ratings = Vec::new(); - } - - if (custom_ranking_param.result_option & 0x04) == 0 { - result.meta_info.meta_binary = QBuffer(Vec::new()); - } - - if (custom_ranking_param.result_option & 0x20) == 0 { - result.score = 0; - } - - q_results.push(QResult::success(ErrorCode::Core_Unknown)); - } - - Ok((ranking_results, q_results)) - } - - async fn get_buffer_queue( - &self, - bufferparam: BufferQueueParam, - ) -> Result, ErrorCode> { - // log::info!("GetBufferQueue: dataid={}, slot={}", param.dataid, param.slot); - - let buffers = - get_buffer_queues_by_data_id_and_slot(bufferparam.dataid, bufferparam.slot).await?; - - Ok(buffers) - } - - async fn prepare_get_object( - &self, - prepare_get_param: DataStorePrepareGetParam, - ) -> Result { - let meta_info = if prepare_get_param.dataid != 0 { - get_object_info_by_data_id(prepare_get_param.dataid, prepare_get_param.access_password) - .await? - } else { - get_object_info_by_persistence_target( - prepare_get_param.persistence_target, - prepare_get_param.access_password, - ) - .await? - }; - - verify_object_permission(meta_info.owner, self.pid, &meta_info.permission)?; - - let presigner = S3Presigner::new( - &format!("https://{}", *RNEX_DATASTORE_S3_ENDPOINT), - format!("{}", *RNEX_DATASTORE_S3_BUCKET), - ) - .await; - - let key = format!("data/{}.bin", meta_info.dataid); - let download_url = presigner.generate_presigned_get(&key); - - Ok(DataStoreReqGetInfo { - url: download_url, - request_headers: vec![], - size: meta_info.size, - root_ca_cert: vec![], - dataid: meta_info.dataid, - }) - } - - async fn followings_latest_course_search_object( - &self, - course_search_param: DataStoreSearchParam, - _extra_data: Vec, - ) -> Result, ErrorCode> { - let mut all_results = Vec::new(); - - for &owner_pid in &course_search_param.owner_ids { - let course_ids = get_user_course_object_ids(owner_pid).await?; - - if course_ids.is_empty() { - continue; - } - - let mut results = get_custom_rankings_by_data_ids(0, course_ids).await; - - // Flag 0x1: Return Tags - // Flag 0x2: Return Ratings - // Flag 0x4: Return MetaBinary - // Flag 0x20: Return Score - for res in &mut results { - if course_search_param.result_option & 0x1 == 0 { - res.meta_info.tags = Vec::new(); - } - if course_search_param.result_option & 0x2 == 0 { - res.meta_info.ratings = Vec::new(); - } - if course_search_param.result_option & 0x4 == 0 { - res.meta_info.meta_binary = - rnex_core::rmc::structures::qbuffer::QBuffer(Vec::new()); - } - if course_search_param.result_option & 0x20 == 0 { - res.score = 0; - } - } - - all_results.extend(results); - } - - // note: we assume the client sorts the data lol - - Ok(all_results) - } - - async fn get_application_config_string( - &self, - application_id: u32, - ) -> Result, ErrorCode> { - let config = match application_id { - 128 => get_blacklist_1(), - 129 => get_blacklist_2(), - 130 => get_blacklist_3(), - _ => { - log::warn!( - "unsupported application_id in GetApplicationConfigString: {}", - application_id - ); - Vec::new() - } - }; - - Ok(config) - } - - async fn get_metas_multiple_param( - &self, - params: Vec, - ) -> Result<(Vec, Vec), ErrorCode> { - let mut metas = Vec::with_capacity(params.len()); - let mut results = Vec::with_capacity(params.len()); - - for param in params { - let info_result = if param.dataid != 0 { - get_object_info_by_data_id(param.dataid, param.access_password).await - } else { - get_object_info_by_persistence_target( - param.persistence_target, - param.access_password, - ) - .await - }; - - match info_result { - Ok(mut meta) => { - if let Err(e) = verify_object_permission(meta.owner, self.pid, &meta.permission) - { - metas.push(GetMetaInfo::default()); - results.push(QResult::error(e)); - } else { - if param.result_option & 0x1 == 0 { - meta.tags = Vec::new(); - } - if param.result_option & 0x2 == 0 { - meta.ratings = Vec::new(); - } - if param.result_option & 0x4 == 0 { - meta.meta_binary = - rnex_core::rmc::structures::qbuffer::QBuffer(Vec::new()); - } - - metas.push(meta); - results.push(QResult::success(ErrorCode::Core_Unknown)); - } - } - Err(e) => { - metas.push(GetMetaInfo::default()); - results.push(QResult::error(e)); - } - } - } - - Ok((metas, results)) - } -} diff --git a/rnex-core/src/nex/friends_handler.rs b/rnex-core/src/nex/friends_handler.rs deleted file mode 100644 index 3af6ff6..0000000 --- a/rnex-core/src/nex/friends_handler.rs +++ /dev/null @@ -1,435 +0,0 @@ -use std::io::{Cursor, Write}; -use std::ops::Deref; -use std::sync::Weak; -use std::sync::{Arc, atomic::AtomicU32}; - -use bytemuck::bytes_of; -use hmac::Mac; -use log::info; -use macros::rmc_struct; -use rnex_core::rmc::protocols::account_management::{ - AccountManagement, RawAccountManagement, RawAccountManagementInfo, RemoteAccountManagement, -}; -use rnex_core::rmc::protocols::friends::{Friends, RawFriends, RawFriendsInfo, RemoteFriends}; -use rnex_core::rmc::protocols::nintendo_notification::{ - NintendoNotification, RawNintendoNotification, RawNintendoNotificationInfo, - RemoteNintendoNotification, -}; -use rnex_core::rmc::protocols::secure::{RawSecure, RawSecureInfo, RemoteSecure, Secure}; -use rnex_core::{ - define_rmc_proto, - kerberos::KerberosDateTime, - nex::common::get_station_urls, - prudp::{socket_addr::PRUDPSockAddr, station_url::StationUrl}, - rmc::{ - protocols::friends::{ - BlacklistedPrincipal, Comment, FriendInfo, FriendRequest, NNAInfo, NintendoPresenceV2, - PersistentNotification, PrincipalPreference, - }, - response::ErrorCode, - structures::{any::Any, qresult::QResult}, - }, -}; -use std::sync::atomic::Ordering::Relaxed; -use tokio::spawn; -use tokio::sync::RwLock; - -use rnex_core::rmc::protocols::friends::{GameKey, MiiV2, PrincipalBasicInfo}; - -use rnex_core::PID; - -use rnex_core::rmc::protocols::account_management::NintendoCreateAccountData; -use rnex_core::rmc::protocols::nintendo_notification::NintendoNotificationEvent; -use rnex_core::rmc::structures::RmcSerialize; - -use rnex_core::rmc::structures::data::Data; - -define_rmc_proto!( - proto FriendsUser{ - Secure, - Friends - } -); -define_rmc_proto!( - proto FriendRemote{ - NintendoNotification - } -); -define_rmc_proto!( - proto FriendsGuest{ - Secure, - AccountManagement - } -); - -pub struct UserData { - info: NNAInfo, - presence: NintendoPresenceV2, -} - -#[rmc_struct(FriendsUser)] -pub struct FriendsUser { - pub fm: Arc, - pub addr: PRUDPSockAddr, - pub pid: PID, - pub data: RwLock>, - pub current_friends: RwLock>, - pub this: Weak, - pub remote: RemoteFriendRemote, -} - -#[rmc_struct(FriendsGuest)] -pub struct FriendsGuest { - pub fm: Arc, - pub addr: PRUDPSockAddr, -} - -pub struct FriendsManager { - pub cid_counter: AtomicU32, - pub users: RwLock>>, -} - -impl FriendsManager { - pub fn next_cid(&self) -> u32 { - self.cid_counter.fetch_add(1, Relaxed) - } -} - -pub fn friend_info_from_user(data: &UserData) -> FriendInfo { - FriendInfo { - data: Data {}, - nna_info: data.info.clone(), - presence: data.presence.clone(), - comment: Comment { - data: Data {}, - unk: 0, - message: "haii =w=".to_string(), - last_changed: KerberosDateTime::now(), - }, - became_friends: KerberosDateTime::now(), - last_online: KerberosDateTime::now(), - unk: 0, - } -} - -impl Friends for FriendsUser { - async fn update_and_get_all_information( - &self, - info: NNAInfo, - presence: NintendoPresenceV2, - _date_time: KerberosDateTime, - ) -> Result< - ( - PrincipalPreference, - Comment, - Vec, - Vec, - Vec, - Vec, - bool, - Vec, - bool, - ), - ErrorCode, - > { - println!("updating own data"); - let mut data = self.data.write().await; - *data = Some(UserData { info, presence }); - let self_fr_info = friend_info_from_user(data.as_ref().unwrap()); - let Ok(any_self_fr_info) = Any::new(&self_fr_info) else { - return Err(ErrorCode::RendezVous_ControlScriptFailure); - }; - let Ok(any_self_presence) = Any::new(&self_fr_info.presence) else { - return Err(ErrorCode::RendezVous_ControlScriptFailure); - }; - drop(data); - - let mut fr_list = vec![FriendInfo { - data: Data{}, - became_friends: KerberosDateTime::now(), - comment: Comment { - data: Data{}, - last_changed: KerberosDateTime::now(), - message: "I'm just a dummy account :3".to_string(), - unk: 0, - }, - last_online: KerberosDateTime::now(), - nna_info: NNAInfo { - data: Data{}, - principal_basic_info: PrincipalBasicInfo { - data: Data{}, - pid: 101, - nnid: "dummy:3".to_string(), - mii: MiiV2{ - data: Data{}, - date_time: KerberosDateTime::now(), - name: "TheDummy".to_string(), - mii_data: hex::decode("030000402bd7c32986a771f2dc6b35e31da15e37ff7c0000391e6f006f006d0069000000000000000000000000004040001065033568641e2013661a611821640f0000290052485000000000000000000000000000000000000000000000e838").unwrap(), - unk: 0, - unk2: 0, - }, - unk: 0 - }, - unk: 0, - unk2: 0 - }, - presence: NintendoPresenceV2{ - data: Data{}, - changed_flags: 0, - message: "".to_string(), - app_data: vec![], - game_key: GameKey{ - data: Data{}, - tid: 0x00050002101ce400, - version: 0x0 - }, - game_server_id: 0, - is_online: true, - gid: 0, - pid: 101, - unk: 0, - unk2: 0, - unk3: 0, - unk4: 0, - unk5: 0, - unk6: 0, - unk7: 0 - }, - unk: 0 - }]; - - println!("acquiring user and current friends locks"); - let users = self.fm.users.read().await; - if users.iter().filter(|u| u.upgrade().is_some()).count() >= 100 { - return Err(ErrorCode::RendezVous_ConnectionFailure); - } - println!("started summing users"); - for u in users.deref().iter().filter_map(|u| u.upgrade()) { - let data = u.data.read().await; - let Some(inner_data) = data.as_ref() else { - continue; - }; - fr_list.push(friend_info_from_user(&inner_data)); - drop(data); - - let mut curr_friends = self.current_friends.write().await; - curr_friends.push(u.pid); - drop(curr_friends); - - let mut fr = u.current_friends.write().await; - if !fr.contains(&self.pid) { - fr.push(self.pid); - drop(fr); - let data = any_self_fr_info.clone(); - let u = u.clone(); - let sender = self.pid; - spawn(async move { - u.remote - .process_nintendo_notification_event_1(NintendoNotificationEvent { - event_type: 30, - sender, - data, - }) - .await; - }); - } else { - let data = any_self_presence.clone(); - let u = u.clone(); - let sender = self.pid; - spawn(async move { - u.remote - .process_nintendo_notification_event_2(NintendoNotificationEvent { - event_type: 24, - sender, - data, - }) - .await; - }); - drop(fr); - } - } - println!("finished summing users"); - drop(users); - - println!("adding self to users"); - let mut users = self.fm.users.write().await; - users.push(self.this.clone()); - drop(users); - - println!("done..."); - Ok(( - PrincipalPreference { - data: Data {}, - block_friend_request: false, - show_online: false, - show_playing_title: false, - }, - Comment { - data: Data {}, - last_changed: KerberosDateTime::now(), - message: "".to_string(), - unk: 0, - }, - fr_list, - vec![], - vec![], - vec![], - false, - vec![], - false, - )) - } - - async fn update_presence(&self, presence: NintendoPresenceV2) -> Result<(), ErrorCode> { - info!("user updated presence: {:?}", presence); - let mut data = self.data.write().await; - let Some(inner_data) = data.as_mut() else { - log::error!("unable to get presence data"); - return Err(ErrorCode::RendezVous_PermissionDenied); - }; - inner_data.presence = presence; - let Ok(any_self_fr_info) = Any::new(&inner_data.presence) else { - log::error!("unable to create presence any data holder"); - return Err(ErrorCode::RendezVous_ControlScriptFailure); - }; - drop(data); - - let users = self.fm.users.read().await; - for u in users.deref().iter().filter_map(|u| u.upgrade()) { - info!("sending presence update"); - u.remote - .process_nintendo_notification_event_2(NintendoNotificationEvent { - event_type: 24, - sender: self.pid, - data: any_self_fr_info.clone(), - }) - .await; - } - drop(users); - - Ok(()) - } - - async fn delete_persistent_notification( - &self, - _notifs: Vec, - ) -> Result<(), ErrorCode> { - Ok(()) - } - - async fn check_setting_status(&self) -> Result { - Ok(0xFF) - } - - async fn update_preference(&self, preference: PrincipalPreference) -> Result<(),ErrorCode> { - info!("user updated preference: {:?}", preference); - let any_presence: Any = Any::new(&preference).expect("out of memory"); - - let users = self.fm.users.read().await; - for u in users.deref().iter().filter_map(|u| u.upgrade()) { - info!("sending preference update"); - u.remote - .process_nintendo_notification_event_2(NintendoNotificationEvent { - event_type: 23, - sender: self.pid, - data: any_presence.clone(), - }) - .await; - } - drop(users); - - Ok(()) - } -} - -type HMacMd5 = hmac::Hmac; - -impl Secure for FriendsUser { - async fn register( - &self, - station_urls: Vec, - ) -> Result<(QResult, u32, StationUrl), ErrorCode> { - let cid = self.fm.next_cid(); - let users = self.fm.users.read().await; - if users.iter().filter(|u| u.upgrade().is_some()).count() >= 100 { - return Err(ErrorCode::RendezVous_ConnectionFailure); - } - Ok(( - QResult::success(ErrorCode::Core_Unknown), - cid, - get_station_urls(&station_urls, self.addr, self.pid, cid).await?[0].clone(), - )) - } - async fn register_ex( - &self, - station_urls: Vec, - _data: Any, - ) -> Result<(QResult, u32, StationUrl), ErrorCode> { - info!("register"); - self.register(station_urls).await - } - async fn replace_url(&self, _target: StationUrl, _dest: StationUrl) -> Result<(), ErrorCode> { - Err(ErrorCode::Core_NotImplemented) - } -} - -impl Secure for FriendsGuest { - async fn register( - &self, - station_urls: Vec, - ) -> Result<(QResult, u32, StationUrl), ErrorCode> { - let cid = self.fm.next_cid(); - Ok(( - QResult::success(ErrorCode::Core_Unknown), - cid, - get_station_urls(&station_urls, self.addr, 100, cid).await?[0].clone(), - )) - } - async fn register_ex( - &self, - station_urls: Vec, - _data: Any, - ) -> Result<(QResult, u32, StationUrl), ErrorCode> { - info!("register"); - self.register(station_urls).await - } - async fn replace_url(&self, _target: StationUrl, _dest: StationUrl) -> Result<(), ErrorCode> { - Err(ErrorCode::Core_NotImplemented) - } -} - -impl AccountManagement for FriendsGuest { - async fn nintendo_create_account( - &self, - principal_name: String, - key: String, - groups: u32, - email: String, - auth_data: Any, - ) -> Result<(PID, String), ErrorCode> { - println!("{}, {}, {}, {}", principal_name, key, groups, email); - if auth_data.name == "NintendoCreateAccountData" { - let Ok(data) = - NintendoCreateAccountData::deserialize(&mut Cursor::new(&auth_data.data)) - else { - return Err(ErrorCode::Authentication_InvalidParam); - }; - - let pid = data.nna_info.principal_basic_info.pid; - info!("create account: {}", pid); - - let Ok(mut mac) = HMacMd5::new_from_slice(key.as_bytes()) else { - return Err(ErrorCode::Authentication_InvalidParam); - }; - - mac.write_all(bytes_of(&pid)) - .expect("failed to write to hmac???"); - let mac = mac.finalize().into_bytes(); - - let hex_str = hex::encode(mac); - - return Ok((pid, hex_str)); - } - Err(ErrorCode::Core_NotImplemented) - } -} diff --git a/rnex-core/src/nex/matchmake.rs b/rnex-core/src/nex/matchmake.rs index 70e720d..a2f8c20 100644 --- a/rnex-core/src/nex/matchmake.rs +++ b/rnex-core/src/nex/matchmake.rs @@ -1,50 +1,40 @@ -use log::info; -use rand::random; -use rnex_core::PID; -use rnex_core::kerberos::KerberosDateTime; -use rnex_core::nex::user::User; -use rnex_core::rmc::protocols::notifications::notification_types::{ - HOST_CHANGED, OWNERSHIP_CHANGED, -}; -use rnex_core::rmc::protocols::notifications::{NotificationEvent, RemoteNotification}; -use rnex_core::rmc::response::ErrorCode; -use rnex_core::rmc::response::ErrorCode::{Core_InvalidArgument, RendezVous_SessionVoid}; -use rnex_core::rmc::structures::matchmake::gathering_flags::PERSISTENT_GATHERING; -use rnex_core::rmc::structures::matchmake::{ - Gathering, MatchmakeParam, MatchmakeSession, MatchmakeSessionSearchCriteria, -}; -use rnex_core::rmc::structures::variant::Variant; use std::collections::HashMap; use std::str::FromStr; +use std::sync::{Arc, Weak}; use std::sync::atomic::AtomicU32; use std::sync::atomic::Ordering::Relaxed; -use std::sync::{Arc, Weak}; use std::time::Duration; +use log::info; +use rand::random; use tokio::sync::{Mutex, RwLock}; use tokio::time::sleep; +use rnex_core::kerberos::KerberosDateTime; +use crate::nex::user::User; +use crate::rmc::protocols::notifications::{NotificationEvent, RemoteNotification}; +use rnex_core::rmc::protocols::notifications::notification_types::{HOST_CHANGED, OWNERSHIP_CHANGED}; +use rnex_core::rmc::response::ErrorCode; +use rnex_core::rmc::response::ErrorCode::{Core_InvalidArgument, RendezVous_SessionVoid}; +use rnex_core::rmc::structures::matchmake::{Gathering, MatchmakeParam, MatchmakeSession, MatchmakeSessionSearchCriteria}; +use rnex_core::rmc::structures::matchmake::gathering_flags::PERSISTENT_GATHERING; +use rnex_core::rmc::structures::variant::Variant; -pub struct MatchmakeManager { - //pub gid_counter: AtomicU32, +pub struct MatchmakeManager{ + pub gid_counter: AtomicU32, pub sessions: RwLock>>>, pub rv_cid_counter: AtomicU32, - pub users: RwLock>>, - pub users_by_pid: RwLock>>, + pub users: RwLock>> } -impl MatchmakeManager { - pub fn next_gid(&self) -> u32 { - random() - //self.gid_counter.fetch_add(1, Relaxed) +impl MatchmakeManager{ + pub fn next_gid(&self) -> u32{ + self.gid_counter.fetch_add(1, Relaxed) } - pub fn next_cid(&self) -> u32 { + pub fn next_cid(&self) -> u32{ self.rv_cid_counter.fetch_add(1, Relaxed) } - pub async fn get_session( - &self, - gid: u32, - ) -> Result>, ErrorCode> { + pub async fn get_session(&self, gid: u32) -> Result>, ErrorCode>{ let sessions = self.sessions.read().await; let Some(session) = sessions.get(&gid) else { @@ -57,7 +47,7 @@ impl MatchmakeManager { Ok(session) } - async fn garbage_collect(&self) { + async fn garbage_collect(&self){ info!("running rnex garbage collector over all sessions and users"); let mut idx = 0; @@ -71,12 +61,12 @@ impl MatchmakeManager { let sessions = self.sessions.read().await; let session_pair = sessions.iter().nth(idx).map(|s| (*s.0, s.1.clone())); drop(sessions); - + session_pair - } { + }{ let session = session.lock().await; - if !session.is_reachable() { + if !session.is_reachable(){ to_be_deleted_gids.push(gid); } @@ -85,14 +75,14 @@ impl MatchmakeManager { let mut sessions = self.sessions.write().await; - for gid in to_be_deleted_gids { + for gid in to_be_deleted_gids{ sessions.remove(&gid); } } - pub async fn initialize_garbage_collect_thread(this: Weak) { + pub async fn initialize_garbage_collect_thread(this: Weak){ tokio::spawn(async move { - while let Some(this) = this.upgrade() { + while let Some(this) = this.upgrade(){ this.garbage_collect().await; // every 30 minutes @@ -102,114 +92,77 @@ impl MatchmakeManager { } } + #[derive(Default, Debug)] -pub struct ExtendedMatchmakeSession { +pub struct ExtendedMatchmakeSession{ pub session: MatchmakeSession, pub connected_players: Vec>, } -fn read_bounds_string(str: &str) -> Option<(T, T)> { +fn read_bounds_string(str: &str) -> Option<(T,T)>{ let bounds = str.split_once(",")?; Some((T::from_str(bounds.0).ok()?, T::from_str(bounds.1).ok()?)) } -fn check_bounds_str(compare: T, str: &str) -> Option { - if let Some(bounds) = read_bounds_string::(str) { - return Some(bounds.0 <= compare && compare <= bounds.1); - } - if let Ok(val) = T::from_str(str) { - return Some(val == compare); - } - if str.is_empty() { - return Some(true); - } - None +fn check_bounds_str(compare: T, str: &str) -> Option{ + let bounds: (T, T) = read_bounds_string(str)?; + + Some(bounds.0 <= compare && compare <= bounds.1) } -pub async fn broadcast_notification>( - players: &[T], - notification_event: &NotificationEvent, -) { - for player in players { +pub async fn broadcast_notification>(players: &[T], notification_event: &NotificationEvent){ + for player in players{ let player = player.as_ref(); - player - .remote - .process_notification_event(notification_event.clone()) - .await; + player.remote.process_notification_event(notification_event.clone()).await; } } -impl ExtendedMatchmakeSession { +impl ExtendedMatchmakeSession{ #[inline(always)] - pub fn get_active_players(&self) -> Vec> { - self.connected_players - .iter() - .filter_map(|u| u.upgrade()) - .collect() + pub fn get_active_players(&self) -> Vec>{ + self.connected_players.iter().filter_map(|u| u.upgrade()).collect() } #[inline(always)] - pub async fn broadcast_notification(&self, notification_event: &NotificationEvent) { + pub async fn broadcast_notification(&self, notification_event: &NotificationEvent){ broadcast_notification(&self.get_active_players(), notification_event).await; } - pub async fn from_matchmake_session( - gid: u32, - session: MatchmakeSession, - host: &Weak, - ) -> Self { - let Some(host) = host.upgrade() else { + pub async fn from_matchmake_session(gid: u32, session: MatchmakeSession, host: &Weak) -> Self{ + let Some(host) = host.upgrade() else{ return Default::default(); }; - cfg_if::cfg_if! { - if #[cfg(feature = "v3-5-0")]{ - let mm_session = MatchmakeSession { - gathering: Gathering { - self_gid: gid, - owner_pid: host.pid, - host_pid: host.pid, - ..session.gathering.clone() - }, - datetime: KerberosDateTime::now(), - session_key: (0..32).map(|_| random()).collect(), - matchmake_param: MatchmakeParam { - params: vec![ - ("@SR".to_owned(), Variant::Bool(true)), - ("@GIR".to_owned(), Variant::SInt64(3)), - ], - }, - system_password_enabled: false, - ..session - }; - return Self { - session: mm_session, - connected_players: Default::default(), - } - } else { - let mm_session = MatchmakeSession { - gathering: Gathering { - self_gid: gid, - owner_pid: host.pid, - host_pid: host.pid, - ..session.gathering.clone() - }, - session_key: (0..32).map(|_| random()).collect(), - ..session - }; - return Self { - session: mm_session, - connected_players: Default::default(), - } - } + let mm_session = MatchmakeSession{ + gathering: Gathering{ + self_gid: gid, + owner_pid: host.pid, + host_pid: host.pid, + ..session.gathering.clone() + }, + datetime: KerberosDateTime::now(), + session_key: (0..32).map(|_| random()).collect(), + matchmake_param: MatchmakeParam{ + params: vec![ + ("@SR".to_owned(), Variant::Bool(true)), + ("@GIR".to_owned(), Variant::SInt64(3)) + ] + }, + system_password_enabled: false, + ..session + }; + + Self{ + session: mm_session, + connected_players: Default::default() } } pub async fn add_players(&mut self, conns: &[Weak], join_msg: String) { let Some(initiating_user) = conns[0].upgrade() else { - return; + return }; let initiating_pid = initiating_user.pid; @@ -220,43 +173,36 @@ impl ExtendedMatchmakeSession { } self.session.participation_count = self.connected_players.len() as u32; - for other_connection in &conns[1..] { + for other_connection in &conns[1..]{ let Some(other_conn) = other_connection.upgrade() else { continue; }; + let other_pid = other_conn.pid; /*if other_pid == self.session.gathering.owner_pid && joining_pid == self.session.gathering.owner_pid{ continue; }*/ - other_conn - .remote - .process_notification_event(NotificationEvent { - pid_source: initiating_pid, - notif_type: 122000, - param_1: self.session.gathering.self_gid as PID, - param_2: other_pid, - str_param: "".into(), - #[cfg(feature = "third-notif-param")] - param_3: 0, - }) - .await; + other_conn.remote.process_notification_event(NotificationEvent{ + pid_source: initiating_pid, + notif_type: 122000, + param_1: self.session.gathering.self_gid, + param_2: other_pid, + str_param: "".into(), + param_3: 0 + }).await; } - let list_of_connected_pids: Vec<_> = self - .connected_players - .iter() - .filter_map(|p| p.upgrade()) - .map(|p| p.pid) - .collect(); + let list_of_connected_pids: Vec<_> = self.connected_players.iter().filter_map(|p| p.upgrade()).map(|p| p.pid).collect(); - for other_connection in conns { + for other_connection in conns{ let Some(other_conn) = other_connection.upgrade() else { continue; }; + // let other_pid = other_conn.pid; /*if other_pid == self.session.gathering.owner_pid && joining_pid == self.session.gathering.owner_pid{ @@ -264,57 +210,44 @@ impl ExtendedMatchmakeSession { }*/ for pid in &list_of_connected_pids { - other_conn - .remote - .process_notification_event(NotificationEvent { - pid_source: initiating_pid, - notif_type: 3001, - param_1: self.session.gathering.self_gid as PID, - param_2: *pid, - str_param: join_msg.clone(), - #[cfg(feature = "third-notif-param")] - param_3: self.connected_players.len() as _, - }) - .await; + other_conn.remote.process_notification_event(NotificationEvent { + pid_source: initiating_pid, + notif_type: 3001, + param_1: self.session.gathering.self_gid, + param_2: *pid, + str_param: join_msg.clone(), + param_3: self.connected_players.len() as _ + }).await; } } - for old_conns in &old_particip { + for old_conns in &old_particip{ let Some(old_conns) = old_conns.upgrade() else { continue; }; - /*if old_conns.pid != self.session.gathering.host_pid { - continue; - }*/ - for new_conn_pid in conns.iter().filter_map(Weak::upgrade).map(|c| c.pid) { - old_conns - .remote - .process_notification_event(NotificationEvent { - pid_source: initiating_pid, - notif_type: 3001, - param_1: self.session.gathering.self_gid as PID, - param_2: new_conn_pid, - str_param: join_msg.clone(), - #[cfg(feature = "third-notif-param")] - param_3: self.connected_players.len() as _, - }) - .await; - } + + let older_pid = old_conns.pid; + + + + initiating_user.remote.process_notification_event(NotificationEvent{ + pid_source: initiating_pid, + notif_type: 3001, + param_1: self.session.gathering.self_gid, + param_2: older_pid, + str_param: join_msg.clone(), + param_3: self.connected_players.len() as _ + }).await; } } - - pub fn has_active_players(&self) -> bool { - self.connected_players - .iter() - .filter(|v| v.upgrade().is_some()) - .count() - != 0 + pub fn has_active_players(&self) -> bool{ + self.connected_players.iter().filter(|v| v.upgrade().is_some()).count() != 0 } #[inline] - pub fn is_reachable(&self) -> bool { - (if self.session.gathering.flags & PERSISTENT_GATHERING != 0 { - if self.has_active_players() { + pub fn is_reachable(&self) -> bool{ + (if self.session.gathering.flags & PERSISTENT_GATHERING != 0{ + if self.has_active_players(){ true } else { self.session.open_participation @@ -324,124 +257,75 @@ impl ExtendedMatchmakeSession { }) & self.has_active_players() } #[inline] - pub fn is_joinable(&self) -> bool { + pub fn is_joinable(&self) -> bool{ self.is_reachable() && self.session.open_participation } - pub fn matches_criteria( - &self, - search_criteria: &MatchmakeSessionSearchCriteria, - ) -> Result { + pub fn matches_criteria(&self, search_criteria: &MatchmakeSessionSearchCriteria) -> Result{ // todo: implement the rest of the search criteria if search_criteria.vacant_only { - if (self.connected_players.len() as u16 + search_criteria.vacant_participants) - > self.session.gathering.maximum_participants - { + if (self.connected_players.len() as u16 + search_criteria.vacant_participants) > self.session.gathering.maximum_participants{ return Ok(false); } } - if search_criteria.exclude_locked { - if !self.session.open_participation { + if search_criteria.exclude_locked{ + if !self.session.open_participation{ return Ok(false); } } - cfg_if::cfg_if! { - if #[cfg(feature = "v3-5-0")]{ - if search_criteria.exclude_system_password_set { - if self.session.system_password_enabled { - return Ok(false); - } - } - - if search_criteria.exclude_user_password_set { - if self.session.user_password_enabled { - return Ok(false); - } - } + if search_criteria.exclude_system_password_set{ + if self.session.system_password_enabled{ + return Ok(false); } } - if !check_bounds_str( - self.session.gathering.minimum_participants, - &search_criteria.minimum_participants, - ) - .ok_or(Core_InvalidArgument)? - { + if search_criteria.exclude_user_password_set{ + if self.session.user_password_enabled{ + return Ok(false); + } + } + + if !check_bounds_str(self.session.gathering.minimum_participants, &search_criteria.minimum_participants).ok_or(Core_InvalidArgument)? { return Ok(false); } - if !check_bounds_str( - self.session.gathering.maximum_participants, - &search_criteria.maximum_participants, - ) - .ok_or(Core_InvalidArgument)? - { + if !check_bounds_str(self.session.gathering.maximum_participants, &search_criteria.maximum_participants).ok_or(Core_InvalidArgument)? { return Ok(false); } - let game_mode: u32 = search_criteria - .game_mode - .parse() - .map_err(|_| Core_InvalidArgument)?; + let game_mode: u32 = search_criteria.game_mode.parse().map_err(|_| Core_InvalidArgument)?; - if self.session.gamemode != game_mode { + if self.session.gamemode != game_mode{ return Ok(false); } - let mm_sys_type: u32 = search_criteria - .matchmake_system_type - .parse() - .map_err(|_| Core_InvalidArgument)?; + let mm_sys_type: u32 = search_criteria.matchmake_system_type.parse().map_err(|_| Core_InvalidArgument)?; - if self.session.matchmake_system_type != mm_sys_type { + if self.session.matchmake_system_type != mm_sys_type{ return Ok(false); } + - #[cfg(feature = "splatoon")] - { - if search_criteria.attribs.get(0).is_some_and(|s| { - self.session - .attributes - .get(0) - .is_some_and(|a| s.0.contains(a)) - }) { - return Ok(false); - } - if search_criteria.attribs.get(2).is_some_and(|s| { - self.session - .attributes - .get(2) - .is_some_and(|a| s.0.contains(a)) - }) { - return Ok(false); - } - if search_criteria.attribs.get(3).is_some_and(|s| { - self.session - .attributes - .get(3) - .is_some_and(|a| s.0.contains(a)) - }) { - return Ok(false); - } + if search_criteria.attribs.get(0).map(|str| str.parse().ok()).flatten() != self.session.attributes.get(0).map(|v| *v){ + return Ok(false); + } + if search_criteria.attribs.get(2).map(|str| str.parse().ok()).flatten() != self.session.attributes.get(2).map(|v| *v){ + return Ok(false); + } + if search_criteria.attribs.get(3).map(|str| str.parse().ok()).flatten() != self.session.attributes.get(3).map(|v| *v){ + return Ok(false); } Ok(true) } - pub async fn migrate_ownership(&mut self, initiator_pid: PID) -> Result<(), ErrorCode> { - let players: Vec<_> = self - .connected_players - .iter() - .filter_map(|p| p.upgrade()) - .collect(); + pub async fn migrate_ownership(&mut self, initiator_pid: u32) -> Result<(), ErrorCode>{ + let players: Vec<_> = self.connected_players.iter().filter_map(|p| p.upgrade()).collect(); - let Some(new_owner) = players - .iter() - .find(|p| p.pid != self.session.gathering.owner_pid) - else { + let Some(new_owner) = players.iter().find(|p| p.pid != self.session.gathering.owner_pid) else { self.session.gathering.owner_pid = 0; return Ok(()); @@ -449,44 +333,36 @@ impl ExtendedMatchmakeSession { self.session.gathering.owner_pid = new_owner.pid; - self.broadcast_notification(&NotificationEvent { + self.broadcast_notification(&NotificationEvent{ pid_source: initiator_pid, notif_type: OWNERSHIP_CHANGED, - param_1: self.session.gathering.self_gid as PID, + param_1: self.session.gathering.self_gid, param_2: new_owner.pid, ..Default::default() - }) - .await; + }).await; Ok(()) } - pub async fn migrate_host(&mut self, initiator_pid: PID) -> Result<(), ErrorCode> { + pub async fn migrate_host(&mut self, initiator_pid: u32) -> Result<(), ErrorCode>{ // let players: Vec<_> = self.connected_players.iter().filter_map(|p| p.upgrade()).collect(); self.session.gathering.host_pid = self.session.gathering.owner_pid; - self.broadcast_notification(&NotificationEvent { + self.broadcast_notification(&NotificationEvent{ pid_source: initiator_pid, notif_type: HOST_CHANGED, - param_1: self.session.gathering.self_gid as PID, + param_1: self.session.gathering.self_gid, ..Default::default() - }) - .await; + }).await; Ok(()) } - pub async fn remove_player_from_session( - &mut self, - pid: PID, - message: &str, - ) -> Result<(), ErrorCode> { - self.connected_players - .retain(|u| u.upgrade().is_some_and(|u| u.pid != pid)); + pub async fn remove_player_from_session(&mut self, pid: u32, message: &str) -> Result<(), ErrorCode>{ + self.connected_players.retain(|u| u.upgrade().is_some_and(|u| u.pid != pid)); - self.session.participation_count = - (self.connected_players.len() & u32::MAX as usize) as u32; + self.session.participation_count = (self.connected_players.len() & u32::MAX as usize) as u32; if pid == self.session.gathering.owner_pid { self.migrate_ownership(pid).await?; @@ -500,20 +376,17 @@ impl ExtendedMatchmakeSession { // todo: finish the rest of this - for player in self.connected_players.iter().filter_map(|p| p.upgrade()) { - player - .remote - .process_notification_event(NotificationEvent { - notif_type: 3008, - pid_source: pid, - param_1: self.session.gathering.self_gid as PID, - param_2: pid, - str_param: message.to_owned(), - ..Default::default() - }) - .await; + for player in self.connected_players.iter().filter_map(|p| p.upgrade()){ + player.remote.process_notification_event(NotificationEvent{ + notif_type: 3008, + pid_source: pid, + param_1: self.session.gathering.self_gid, + param_2: pid, + str_param: message.to_owned(), + .. Default::default() + }).await; } Ok(()) } -} +} \ No newline at end of file diff --git a/rnex-core/src/nex/mod.rs b/rnex-core/src/nex/mod.rs index ba92c5d..76791bc 100644 --- a/rnex-core/src/nex/mod.rs +++ b/rnex-core/src/nex/mod.rs @@ -1,22 +1,5 @@ -use cfg_if::cfg_if; - pub mod account; pub mod auth_handler; -pub mod common; - -cfg_if! { - if #[cfg(feature = "friends")]{ - pub mod friends_handler; - } else { - pub mod matchmake; - pub mod remote_console; - pub mod user; - } -} - -cfg_if! { - if #[cfg(feature = "datastore")] { - pub mod s3presigner; - pub mod datastore; - } -} +pub mod user; +pub mod remote_console; +pub mod matchmake; \ No newline at end of file diff --git a/rnex-core/src/nex/s3presigner.rs b/rnex-core/src/nex/s3presigner.rs deleted file mode 100644 index afe61d4..0000000 --- a/rnex-core/src/nex/s3presigner.rs +++ /dev/null @@ -1,117 +0,0 @@ -use aws_sdk_s3::presigning::PresigningConfig; -use base64::{engine::general_purpose, Engine as _}; -use hmac::{Hmac, Mac}; -use sha2::{Sha256, Digest}; -use chrono::{Utc, Duration}; -use serde_json::json; -use rnex_core::executables::common::RNEX_DATASTORE_S3_ENDPOINT; - -pub struct S3Presigner { - endpoint: String, - bucket: String, -} - -impl S3Presigner { - pub async fn new(endpoint: &str, bucket: String) -> Self { - Self { - endpoint: endpoint.trim_end_matches('/').to_string(), - bucket, - } - } - pub async fn generate_presigned_post(&self, key: &str) -> (String, Vec<(String, String)>) { - let access_key = std::env::var("AWS_ACCESS_KEY_ID").expect("Missing Access Key"); - let secret_key = std::env::var("AWS_SECRET_ACCESS_KEY").expect("Missing Secret Key"); - let region = "us-east-1"; // hardcoded because its the default region for most s3 clones - let date_short = Utc::now().format("%Y%m%d").to_string(); - let date_full = Utc::now().format("%Y%m%dT%H%M%SZ").to_string(); - let expiration = (Utc::now() + Duration::minutes(15)).format("%Y-%m-%dT%H:%M:%SZ").to_string(); - - let credential = format!("{}/{}/{}/s3/aws4_request", access_key, date_short, region); - - let policy_json = json!({ - "expiration": expiration, - "conditions": [ - {"bucket": self.bucket}, - ["starts-with", "$key", key], - {"x-amz-credential": credential}, - {"x-amz-algorithm": "AWS4-HMAC-SHA256"}, - {"x-amz-date": date_full} - ] - }); - - let policy_base64 = general_purpose::STANDARD.encode(policy_json.to_string()); - - let signature = self.calculate_signature(&secret_key, &date_short, region, &policy_base64); - - let mut fields = vec![ - ("key".to_string(), key.to_string()), - ("X-Amz-Algorithm".to_string(), "AWS4-HMAC-SHA256".to_string()), - ("X-Amz-Credential".to_string(), credential), - ("X-Amz-Date".to_string(), date_full), - ("Policy".to_string(), policy_base64), - ("X-Amz-Signature".to_string(), signature), - ]; - - let url = format!("https://{}/{}", *RNEX_DATASTORE_S3_ENDPOINT, self.bucket); - (url, fields) - } - - pub fn generate_presigned_get(&self, key: &str) -> String { - let access_key = std::env::var("AWS_ACCESS_KEY_ID").expect("Missing Access Key"); - let secret_key = std::env::var("AWS_SECRET_ACCESS_KEY").expect("Missing Secret Key"); - let region = "us-east-1"; - let date_short = Utc::now().format("%Y%m%d").to_string(); - let date_full = Utc::now().format("%Y%m%dT%H%M%SZ").to_string(); - - let credential_scope = format!("{}/{}/s3/aws4_request", date_short, region); - - let query_string = format!( - "X-Amz-Algorithm=AWS4-HMAC-SHA256&\ - X-Amz-Credential={}%2F{}&\ - X-Amz-Date={}&\ - X-Amz-Expires=900&\ - X-Amz-SignedHeaders=host", - access_key, - urlencoding::encode(&credential_scope), - date_full - ); - - let canonical_request = format!( - "GET\n/{}/{}\n{}\nhost:{}\n\nhost\nUNSIGNED-PAYLOAD", - self.bucket, key, query_string, *RNEX_DATASTORE_S3_ENDPOINT - ); - - let hashed_request = hex::encode(Sha256::digest(canonical_request.as_bytes())); - - let string_to_sign = format!( - "AWS4-HMAC-SHA256\n{}\n{}\n{}", - date_full, credential_scope, hashed_request - ); - - let k_date = self.hmac_sha256(format!("AWS4{}", secret_key).as_bytes(), &date_short); - let k_region = self.hmac_sha256(&k_date, region); - let k_service = self.hmac_sha256(&k_region, "s3"); - let k_signing = self.hmac_sha256(&k_service, "aws4_request"); - let signature = hex::encode(self.hmac_sha256(&k_signing, &string_to_sign)); - - format!( - "https://{}/{}/{}?{}&X-Amz-Signature={}", - *RNEX_DATASTORE_S3_ENDPOINT, self.bucket, key, query_string, signature - ) - } - - fn calculate_signature(&self, secret: &str, date: &str, region: &str, policy: &str) -> String { - let k_date = self.hmac_sha256(format!("AWS4{}", secret).as_bytes(), date); - let k_region = self.hmac_sha256(&k_date, region); - let k_service = self.hmac_sha256(&k_region, "s3"); - let k_signing = self.hmac_sha256(&k_service, "aws4_request"); - - hex::encode(self.hmac_sha256(&k_signing, policy)) - } - - fn hmac_sha256(&self, key: &[u8], data: &str) -> Vec { - let mut mac = Hmac::::new_from_slice(key).expect("HMAC can take key of any size"); - mac.update(data.as_bytes()); - mac.finalize().into_bytes().to_vec() - } -} \ No newline at end of file diff --git a/rnex-core/src/nex/user.rs b/rnex-core/src/nex/user.rs index 974c869..dd30cb4 100644 --- a/rnex-core/src/nex/user.rs +++ b/rnex-core/src/nex/user.rs @@ -1,91 +1,48 @@ -use rnex_core::PID; -use rnex_core::define_rmc_proto; -use rnex_core::kerberos::KerberosDateTime; -use rnex_core::nex::common::get_station_urls; -use rnex_core::nex::matchmake::{ExtendedMatchmakeSession, MatchmakeManager}; -use rnex_core::nex::remote_console::RemoteConsole; +use crate::define_rmc_proto; +use crate::nex::matchmake::{ExtendedMatchmakeSession, MatchmakeManager}; +use crate::nex::remote_console::RemoteConsole; use rnex_core::prudp::station_url::StationUrl; use rnex_core::prudp::station_url::UrlOptions::{ - Address, NatFiltering, NatMapping, Port, RVConnectionID, + Address, NatFiltering, NatMapping, NatType, Port, PrincipalID, RVConnectionID, + }; -use rnex_core::rmc::protocols::matchmake::{ +use crate::rmc::protocols::matchmake::{ Matchmake, RawMatchmake, RawMatchmakeInfo, RemoteMatchmake, }; -use rnex_core::rmc::protocols::matchmake_ext::{ - MatchmakeExt, RawMatchmakeExt, RawMatchmakeExtInfo, RemoteMatchmakeExt, -}; +use rnex_core::rmc::protocols::ranking::{Ranking, RawRanking, RawRankingInfo, RemoteRanking}; use rnex_core::rmc::protocols::matchmake_extension::{ MatchmakeExtension, RawMatchmakeExtension, RawMatchmakeExtensionInfo, RemoteMatchmakeExtension, }; -use rnex_core::rmc::protocols::nat_traversal::{ - NatTraversal, RawNatTraversal, RawNatTraversalInfo, RemoteNatTraversal, - RemoteNatTraversalConsole, -}; -use rnex_core::rmc::protocols::notifications::notification_types::{ - END_GATHERING, REQUEST_JOIN_GATHERING, -}; -use rnex_core::rmc::protocols::ranking::{Ranking, RawRanking, RawRankingInfo, RemoteRanking}; +use crate::rmc::protocols::nat_traversal::{NatTraversal, RawNatTraversal, RawNatTraversalInfo, RemoteNatTraversal, RemoteNatTraversalConsole}; use rnex_core::rmc::protocols::secure::{RawSecure, RawSecureInfo, RemoteSecure, Secure}; -use rnex_core::rmc::protocols::util::{RawUtility, RawUtilityInfo, RemoteUtility, Utility}; +use rnex_core::rmc::protocols::matchmake_ext::{MatchmakeExt, RawMatchmakeExt, RawMatchmakeExtInfo, RemoteMatchmakeExt}; use rnex_core::rmc::response::ErrorCode; -use rnex_core::rmc::structures::any::Any; -use rnex_core::rmc::structures::matchmake::{ - AutoMatchmakeParam, CreateMatchmakeSessionParam, JoinMatchmakeSessionParam, MatchmakeSession, -}; -use serde::{Deserialize, Serialize}; -use std::env; -use std::str::FromStr; +use rnex_core::rmc::structures::matchmake::{AutoMatchmakeParam, CreateMatchmakeSessionParam, JoinMatchmakeSessionParam, MatchmakeSession}; -use cfg_if::cfg_if; -use log::{error, info}; -use macros::rmc_struct; -use rnex_core::prudp::socket_addr::PRUDPSockAddr; -use rnex_core::rmc::protocols::notifications::{NotificationEvent, RemoteNotification}; -use rnex_core::rmc::protocols::ranking::{ - CompetitionRankingGetParam, CompetitionRankingScoreData, CompetitionRankingScoreInfo, -}; -use rnex_core::rmc::response::ErrorCode::{Core_InvalidArgument, RendezVous_AccountExpired}; -use rnex_core::rmc::structures::qbuffer::QBuffer; use rnex_core::rmc::structures::qresult::QResult; -use rnex_core::rmc::structures::ranking::UploadCompetitionData; +use macros::rmc_struct; use std::sync::{Arc, Weak}; +use log::info; use tokio::sync::{Mutex, RwLock}; +use rnex_core::prudp::socket_addr::PRUDPSockAddr; +use rnex_core::prudp::station_url::nat_types::PUBLIC; +use crate::rmc::protocols::notifications::{NotificationEvent, RemoteNotification}; +use rnex_core::rmc::response::ErrorCode::{Core_Exception, Core_InvalidArgument, RendezVous_AccountExpired}; -use crate::rmc::structures::matchmake::MatchmakeSessionSearchCriteria; - -cfg_if! { - if #[cfg(feature = "datastore")] { - use rnex_core::rmc::protocols::datastore::{DataStore, RawDataStore, RawDataStoreInfo, RemoteDataStore}; - define_rmc_proto!( - proto UserProtocol{ - Secure, - MatchmakeExtension, - MatchmakeExt, - Matchmake, - NatTraversal, - Ranking, - Utility, - DataStore - } - ); - } else { - define_rmc_proto!( - proto UserProtocol{ - Secure, - MatchmakeExtension, - MatchmakeExt, - Matchmake, - NatTraversal, - Utility, - Ranking - } - ); +define_rmc_proto!( + proto UserProtocol{ + Secure, + MatchmakeExtension, + MatchmakeExt, + Matchmake, + NatTraversal, + Ranking } -} +); #[rmc_struct(UserProtocol)] pub struct User { - pub pid: PID, + pub pid: u32, pub ip: PRUDPSockAddr, pub this: Weak, pub remote: RemoteConsole, @@ -105,31 +62,99 @@ impl Secure for User { let mut users = self.matchmake_manager.users.write().await; users.insert(cid, self.this.clone()); drop(users); - let mut users = self.matchmake_manager.users_by_pid.write().await; - users.insert(self.pid, self.this.clone()); - drop(users); - let stations = get_station_urls(&station_urls, self.ip, self.pid, cid).await?; + let mut public_station: Option = None; + let mut private_station: Option = None; + + for station in station_urls { + let is_public = station.options.iter().any(|v| { + if let NatType(v) = v { + if *v & PUBLIC != 0 { + return true; + } + } + false + }); + + let Some(nat_filtering) = station.options.iter().find_map(|v| match v { + NatFiltering(v) => Some(v), + _ => None + }) else { + return Err(Core_Exception); + }; + + let Some(nat_mapping) = station.options.iter().find_map(|v| match v { + NatMapping(v) => Some(v), + _ => None + }) else { + return Err(Core_Exception); + }; + + if !is_public || (*nat_filtering == 0 && *nat_mapping == 0) { + private_station = Some(station.clone()); + } + + if is_public { + public_station = Some(station); + } + } + + let Some(mut private_station) = private_station else { + return Err(Core_Exception); + }; + + let mut public_station = if let Some(public_station) = public_station { + public_station + } else { + let mut public_station = private_station.clone(); + + public_station.options.retain(|v| { + match v { + Address(_) | Port(_) | NatFiltering(_) | NatMapping(_) | NatType(_) => false, + _ => true + } + }); + + public_station.options.push(Address(*self.ip.regular_socket_addr.ip())); + public_station.options.push(Port(self.ip.regular_socket_addr.port())); + public_station.options.push(NatFiltering(0)); + public_station.options.push(NatMapping(0)); + public_station.options.push(NatType(3)); + + public_station + }; + + let both = [&mut public_station, &mut private_station]; + + for station in both { + station.options.retain(|v| { + match v { + PrincipalID(_) | RVConnectionID(_) => false, + _ => true + } + }); + + station.options.push(PrincipalID(self.pid)); + station.options.push(RVConnectionID(cid)); + } - let first = stations.first().unwrap().clone(); let mut lock = self.station_url.write().await; - *lock = stations; + *lock = vec![ + public_station.clone(), + // private_station.clone() + ]; drop(lock); let result = QResult::success(ErrorCode::Core_Unknown); - Ok((result, cid, first)) - } + let out = public_station.to_string(); - async fn register_ex( - &self, - station_urls: Vec, - _data: Any, - ) -> Result<(QResult, u32, StationUrl), ErrorCode> { - self.register(station_urls).await + println!("out: {}", out); + + Ok((result, cid, public_station)) } async fn replace_url(&self, target_url: StationUrl, dest: StationUrl) -> Result<(), ErrorCode> { @@ -144,8 +169,8 @@ impl Secure for User { }; let Some(replacement_target) = lock.iter_mut().find(|url| { - url.options.iter().any(|o| o == target_addr) - && url.options.iter().any(|o| o == target_port) + url.options.iter().any(|o| o == target_addr) && + url.options.iter().any(|o| o == target_port) }) else { return Err(ErrorCode::Core_InvalidArgument); }; @@ -182,7 +207,6 @@ impl MatchmakeExtension for User { Ok(Vec::new()) } - #[cfg(feature = "v3-5-0")] async fn update_progress_score(&self, gid: u32, progress: u8) -> Result<(), ErrorCode> { let session = self.matchmake_manager.get_session(gid).await?; @@ -206,34 +230,22 @@ impl MatchmakeExtension for User { create_session_param.matchmake_session, &self.this.clone(), ) - .await; + .await; let mut joining_players = vec![self.this.clone()]; let users = self.matchmake_manager.users.read().await; - if let Ok(old_gathering) = self - .matchmake_manager - .get_session(create_session_param.gid_for_participation_check) - .await - { + if let Ok(old_gathering) = self.matchmake_manager.get_session(create_session_param.gid_for_participation_check).await { let old_gathering = old_gathering.lock().await; - let players = old_gathering - .connected_players - .iter() - .filter_map(|v| v.upgrade()) - .filter(|u| { - create_session_param - .additional_participants - .iter() - .any(|p| *p == u.pid) - }); + let players = old_gathering.connected_players.iter().filter_map(|v| v.upgrade()).filter(|u| create_session_param.additional_participants.iter().any(|p| *p == u.pid)); for player in players { joining_players.push(Arc::downgrade(&player)); } } + drop(users); new_session.session.participation_count = create_session_param.participation_count as u32; @@ -254,43 +266,26 @@ impl MatchmakeExtension for User { &self, join_session_param: JoinMatchmakeSessionParam, ) -> Result { - let session = self - .matchmake_manager - .get_session(join_session_param.gid) - .await?; + let session = self.matchmake_manager.get_session(join_session_param.gid).await?; let mut session = session.lock().await; - - #[cfg(feature = "v3-5-0")] - if join_session_param.user_password != session.session.user_password { - return Err(ErrorCode::RendezVous_InvalidPassword); + + if session.session.user_password_enabled{ + if join_session_param.user_password != session.session.user_password{ + return Err(ErrorCode::RendezVous_InvalidPassword) + } } - session - .connected_players - .retain(|v| v.upgrade().is_some_and(|v| v.pid != self.pid)); + session.connected_players.retain(|v| v.upgrade().is_some_and(|v| v.pid != self.pid)); let mut joining_players = vec![self.this.clone()]; let users = self.matchmake_manager.users.read().await; - if let Ok(old_gathering) = self - .matchmake_manager - .get_session(join_session_param.gid_for_participation_check) - .await - { + if let Ok(old_gathering) = self.matchmake_manager.get_session(join_session_param.gid_for_participation_check).await { let old_gathering = old_gathering.lock().await; - let players = old_gathering - .connected_players - .iter() - .filter_map(|v| v.upgrade()) - .filter(|u| { - join_session_param - .additional_participants - .iter() - .any(|p| *p == u.pid) - }); + let players = old_gathering.connected_players.iter().filter_map(|v| v.upgrade()).filter(|u| join_session_param.additional_participants.iter().any(|p| *p == u.pid)); for player in players { joining_players.push(Arc::downgrade(&player)); } @@ -307,28 +302,17 @@ impl MatchmakeExtension for User { Ok(mm_session) } - async fn auto_matchmake_with_param_postpone( - &self, - param: AutoMatchmakeParam, - ) -> Result { + async fn auto_matchmake_with_param_postpone(&self, param: AutoMatchmakeParam) -> Result { println!("{:?}", param); let mut joining_players = vec![self.this.clone()]; let users = self.matchmake_manager.users.read().await; - if let Ok(old_gathering) = self - .matchmake_manager - .get_session(param.gid_for_participation_check) - .await - { + if let Ok(old_gathering) = self.matchmake_manager.get_session(param.gid_for_participation_check).await { let old_gathering = old_gathering.lock().await; - let players = old_gathering - .connected_players - .iter() - .filter_map(|v| v.upgrade()) - .filter(|u| param.additional_participants.iter().any(|p| *p == u.pid)); + let players = old_gathering.connected_players.iter().filter_map(|v| v.upgrade()).filter(|u| param.additional_participants.iter().any(|p| *p == u.pid)); for player in players { joining_players.push(Arc::downgrade(&player)); } @@ -355,9 +339,7 @@ impl MatchmakeExtension for User { } if bool_matched_criteria { - session - .add_players(&joining_players, param.join_message) - .await; + session.add_players(&joining_players, param.join_message).await; return Ok(session.session.clone()); } @@ -383,26 +365,17 @@ impl MatchmakeExtension for User { create_matchmake_session_option: 0, matchmake_session, additional_participants, - }) - .await + }).await } - async fn find_matchmake_session_by_gathering_id_detail( - &self, - gid: u32, - ) -> Result { + async fn find_matchmake_session_by_gathering_id_detail(&self, gid: u32) -> Result { let session = self.matchmake_manager.get_session(gid).await?; let session = session.lock().await; Ok(session.session.clone()) } - async fn modify_current_game_attribute( - &self, - gid: u32, - attrib_index: u32, - attrib_val: u32, - ) -> Result<(), ErrorCode> { + async fn modify_current_game_attribute(&self, gid: u32, attrib_index: u32, attrib_val: u32) -> Result<(), ErrorCode> { let session = self.matchmake_manager.get_session(gid).await?; let mut session = session.lock().await; @@ -410,147 +383,9 @@ impl MatchmakeExtension for User { Ok(()) } - - async fn create_matchmake_session( - &self, - gathering: Any, - message: String, - ) -> Result<(u32, Vec), ErrorCode> { - info!("gathering: {:?}", gathering); - let Some(Ok(session)): Option> = gathering.try_get() else { - return Err(ErrorCode::Core_InvalidArgument); - }; - - let session = self - .create_matchmake_session_with_param(CreateMatchmakeSessionParam { - matchmake_session: session, - additional_participants: vec![], - gid_for_participation_check: 0, - create_matchmake_session_option: 0, - join_message: message, - participation_count: 1, - }) - .await?; - - Ok((session.gathering.self_gid, session.session_key)) - } - - async fn get_friend_notification_data( - &self, - _ty: i32, - ) -> Result, ErrorCode> { - Ok(vec![]) - } - async fn update_notification_data( - &self, - ty: u32, - param_1: u32, - param_2: u32, - str_param: String, - ) -> Result<(), ErrorCode> { - let recpipent = param_2; - let Some(user) = self - .matchmake_manager - .users_by_pid - .read() - .await - .get(&recpipent) - .and_then(|v| v.upgrade()) - else { - return Err(ErrorCode::Core_InvalidArgument); - }; - println!("notif ty : {}", ty); - match ty { - REQUEST_JOIN_GATHERING => { - user.remote - .process_notification_event(NotificationEvent { - pid_source: self.pid, - notif_type: REQUEST_JOIN_GATHERING * 1000, - param_1, - param_2, - #[cfg(feature = "third-notif-param")] - param_3: 0, - str_param, - }) - .await; - } - END_GATHERING => { - user.remote - .process_notification_event(NotificationEvent { - pid_source: self.pid, - notif_type: END_GATHERING * 1000, - param_1, - param_2, - #[cfg(feature = "third-notif-param")] - param_3: 0, - str_param, - }) - .await; - } - _ => { - return Err(ErrorCode::Core_InvalidArgument); - } - } - Ok(()) - } - - async fn join_matchmake_session_ex( - &self, - gid: u32, - message: String, - _dont_care_block_list: bool, - //participation_count: u16, - ) -> Result, ErrorCode> { - let sess = self.matchmake_manager.get_session(gid).await?; - let mut sess = sess.lock().await; - sess.add_players(&[self.this.clone()], message).await; - - Ok(sess.session.session_key.clone()) - } - - async fn auto_matchmake_with_search_criteria_postpone( - &self, - criteria: Vec, - gathering: Any, - join_message: String, - ) -> Result { - let session: MatchmakeSession = gathering - .try_get() - .map(|v| v.ok()) - .flatten() - .ok_or(ErrorCode::Core_InvalidArgument)?; - - println!("{:?}", criteria); - - let session = self - .auto_matchmake_with_param_postpone(AutoMatchmakeParam { - matchmake_session: session, - additional_participants: vec![], - gid_for_participation_check: 0, - auto_matchmake_option: 0, - join_message, - participation_count: 0, - search_criteria: criteria, - target_gids: vec![], - }) - .await?; - - let any = Any::new(&session).map_err(|_| ErrorCode::Core_SystemError)?; - - Ok(any) - } } impl Matchmake for User { - async fn find_by_single_id(&self, gid: u32) -> Result<(bool, Any), ErrorCode> { - let s = self.matchmake_manager.get_session(gid).await?; - let s = s.lock().await; - Ok(( - true, - Any::new(&s.session).map_err(|_| ErrorCode::Custom_Unknown)?, - )) - } - async fn unregister_gathering(&self, _gid: u32) -> Result { Ok(true) } @@ -559,30 +394,30 @@ impl Matchmake for User { let session = session.lock().await; - let urls: Vec<_> = session - .connected_players - .iter() - .filter_map(|v| v.upgrade()) - .filter(|u| u.pid == session.session.gathering.host_pid) - .map(|u| async move { u.station_url.read().await.clone() }) - .next() - .ok_or(ErrorCode::RendezVous_SessionClosed)? - .await; + let urls: Vec<_> = + session + .connected_players + .iter() + .filter_map(|v| v.upgrade()) + .filter(|u| u.pid == session.session.gathering.host_pid) + .map(|u| async move { + u.station_url.read().await.clone() + }) + .next() + .ok_or(ErrorCode::RendezVous_SessionClosed)? + .await; + println!("{:?}", urls); - - if urls.is_empty() { - return Err(ErrorCode::RendezVous_NotParticipatedGathering); + + if urls.is_empty(){ + return Err(ErrorCode::RendezVous_NotParticipatedGathering) } Ok(urls) } - async fn update_session_host( - &self, - gid: u32, - change_session_owner: bool, - ) -> Result<(), ErrorCode> { + async fn update_session_host(&self, gid: u32, change_session_owner: bool) -> Result<(), ErrorCode> { let session = self.matchmake_manager.get_session(gid).await?; let mut session = session.lock().await; @@ -593,52 +428,40 @@ impl Matchmake for User { continue; }; - player - .remote - .process_notification_event(NotificationEvent { - notif_type: 110000, - pid_source: self.pid, - param_1: gid as PID, - param_2: self.pid, - #[cfg(feature = "third-notif-param")] - param_3: 0, - str_param: "".to_string(), - }) - .await; + player.remote.process_notification_event(NotificationEvent { + notif_type: 110000, + pid_source: self.pid, + param_1: gid, + param_2: self.pid, + param_3: 0, + str_param: "".to_string(), + }).await; } if change_session_owner { session.session.gathering.owner_pid = self.pid; + for player in &session.connected_players { let Some(player) = player.upgrade() else { continue; }; - player - .remote - .process_notification_event(NotificationEvent { - notif_type: 4000, - pid_source: self.pid, - param_1: gid as PID, - param_2: self.pid, - #[cfg(feature = "third-notif-param")] - param_3: 0, - str_param: "".to_string(), - }) - .await; + player.remote.process_notification_event(NotificationEvent { + notif_type: 4000, + pid_source: self.pid, + param_1: gid, + param_2: self.pid, + param_3: 0, + str_param: "".to_string(), + }).await; } } Ok(()) } - async fn migrate_gathering_ownership( - &self, - gid: u32, - candidates: Vec, - _participants_only: bool, - ) -> Result<(), ErrorCode> { + async fn migrate_gathering_ownership(&self, gid: u32, candidates: Vec, _participants_only: bool) -> Result<(), ErrorCode> { let session = self.matchmake_manager.get_session(gid).await?; let mut session = session.lock().await; @@ -651,18 +474,14 @@ impl Matchmake for User { continue; }; - player - .remote - .process_notification_event(NotificationEvent { - notif_type: 4000, - pid_source: self.pid, - param_1: gid as PID, - param_2: *candidate as PID, - #[cfg(feature = "third-notif-param")] - param_3: 0, - str_param: "".to_string(), - }) - .await; + player.remote.process_notification_event(NotificationEvent { + notif_type: 4000, + pid_source: self.pid, + param_1: gid, + param_2: *candidate, + param_3: 0, + str_param: "".to_string(), + }).await; } Ok(()) @@ -674,12 +493,12 @@ impl MatchmakeExt for User { let session = self.matchmake_manager.get_session(gid).await?; let mut session = session.lock().await; - session - .remove_player_from_session(self.pid, &message) - .await?; + session.remove_player_from_session(self.pid, &message).await?; Ok(true) } + + } impl NatTraversal for User { @@ -694,7 +513,7 @@ impl NatTraversal for User { for station_url in urls.iter_mut() { station_url.options.retain(|o| match o { NatMapping(_) | NatFiltering(_) => false, - _ => true, + _ => true }); station_url.options.push(NatMapping(nat_mapping as u8)); @@ -704,12 +523,7 @@ impl NatTraversal for User { Ok(()) } - async fn report_nat_traversal_result( - &self, - _cid: u32, - _result: bool, - _rtt: u32, - ) -> Result<(), ErrorCode> { + async fn report_nat_traversal_result(&self, _cid: u32, _result: bool, _rtt: u32) -> Result<(), ErrorCode> { Ok(()) } @@ -718,28 +532,17 @@ impl NatTraversal for User { Err(RendezVous_AccountExpired) } - async fn request_probe_initialization_ext( - &self, - target_list: Vec, - station_to_probe: String, - ) -> Result<(), ErrorCode> { + async fn request_probe_initialization_ext(&self, target_list: Vec, station_to_probe: String) -> Result<(), ErrorCode> { let users = self.matchmake_manager.users.read().await; - println!( - "requesting station probe for {:?} to {:?}", - target_list, station_to_probe - ); + println!("requesting station probe for {:?} to {:?}", target_list, station_to_probe); for target in target_list { let Ok(url) = StationUrl::try_from(target.as_ref()) else { continue; }; - let Some(RVConnectionID(v)) = url - .options - .into_iter() - .find(|o| matches!(o, &RVConnectionID(_))) - else { + let Some(RVConnectionID(v)) = url.options.into_iter().find(|o| { matches!(o, &RVConnectionID(_)) }) else { continue; }; @@ -751,9 +554,7 @@ impl NatTraversal for User { continue; }; - user.remote - .request_probe_initiation(station_to_probe.clone()) - .await; + user.remote.request_probe_initiation(station_to_probe.clone()).await; } info!("finished probing"); @@ -762,161 +563,6 @@ impl NatTraversal for User { } } -#[derive(Serialize, Deserialize)] -pub struct CompetitionPostResults { - pub splatfest_id: u32, - pub score: u32, - pub team_id: u8, - pub team_win: u8, - pub user: PID, -} +impl Ranking for User{ -// Seperate function because I cannot give a fuck right now -fn fetch_team_votes(fest_id: u32) -> Result, ErrorCode> { - let endpoint_votes = env::var("RNEX_SPLATOON_RESULTS_VOTES_GET").map_err(|_| { - error!("RNEX_SPLATOON_RESULTS_VOTES_GET not set"); - ErrorCode::RendezVous_InvalidConfiguration - })?; - - let url_votes = format!("{}?splatfest_id={}", endpoint_votes, fest_id); - let mut response = ureq::get(&url_votes).call().map_err(|e| { - error!("GET for votes failed: {:?}", e); - ErrorCode::RendezVous_InvalidConfiguration - })?; - - let body = response.body_mut().read_to_string().map_err(|e| { - error!("failed to read votes body: {:?}", e); - ErrorCode::RendezVous_InvalidConfiguration - })?; - - let body = body.trim().trim_start_matches('[').trim_end_matches(']'); - let votes: Result, _> = body.split(',').map(|s| u32::from_str(s.trim())).collect(); - - votes.map_err(|e| { - error!("failed to parse votes: {:?}", e); - ErrorCode::RendezVous_InvalidConfiguration - }) -} - -impl Utility for User { - async fn acquire_nex_unique_id(&self) -> Result { - return Ok(rand::random()); - } -} - -impl Ranking for User { - async fn competition_ranking_get_param( - &self, - param: CompetitionRankingGetParam, - ) -> Result, ErrorCode> { - let fest_id = param.festival_ids.get(0).copied().unwrap_or(0); - - let endpoint_results = env::var("RNEX_SPLATOON_RESULTS_GET").map_err(|_| { - error!("RNEX_SPLATOON_RESULTS_GET not set"); - ErrorCode::RendezVous_InvalidConfiguration - })?; - - let url_results = format!("{}?splatfest_id={}", endpoint_results, fest_id); - let response_results = ureq::get(&url_results).call(); - - let results: Vec = match response_results { - Ok(mut res) => res.body_mut().read_json().map_err(|e| { - error!("failed to parse JSON: {:?}", e); - ErrorCode::RendezVous_InvalidConfiguration - })?, - Err(e) => { - error!("GET failed: {:?}", e); - return Err(ErrorCode::RendezVous_InvalidConfiguration); - } - }; - - let offset = param.range.offset as usize; - let size = param.range.size as usize; - - let start = offset.min(results.len()); - let end = (start + size).min(results.len()); - - let team_votes = fetch_team_votes(fest_id)?; - let mut wins = vec![0u32, 0u32]; - for r in &results { - let won_team = (r.team_id ^ (!r.team_win)) & 1; - if let Some(team) = wins.get_mut(won_team as usize) { - *team += 1 - }; - } - - let score_data: Vec = results[start..end] - .iter() - .map(|r| CompetitionRankingScoreData { - unk: 1, - pid: r.user, - score: r.score, - modified: KerberosDateTime::now(), - unk2: 1, - appdata: QBuffer(vec![]), - }) - .collect(); - - let info = CompetitionRankingScoreInfo { - fest_id, - score_data, - unk: 0, - team_wins: wins, - team_votes, - }; - - println!("range: {:?}", param.range); - - Ok(vec![info]) - } - - async fn upload_competition_ranking_score( - &self, - param: UploadCompetitionData, - ) -> Result { - info!("fest results for user {:?}:", self.pid); - info!("fest id: {:?}", param.splatfest_id); - info!("score: {:?}", param.score); - info!("team id: {:?}", param.team_id); - info!("did current team win: {:?}", param.team_win); - - let endpoint = match env::var("RNEX_SPLATOON_RESULTS_POST") { - Ok(url) => url, - Err(_) => { - error!("RNEX_SPLATOON_RESULTS_POST not set"); - return Ok(false); - } - }; - - let payload = CompetitionPostResults { - splatfest_id: param.splatfest_id, - score: param.score, - team_id: param.team_id, - team_win: param.team_win, - user: self.pid, - }; - - let json_body = match serde_json::to_string(&payload) { - Ok(j) => j, - Err(e) => { - error!("error making json_body: {:?}", e); - return Ok(false); - } - }; - - let response = ureq::post(&endpoint) - .header("Content-Type", "application/json") - .send(json_body); - - match response { - Ok(res) => { - info!("POST worked: {}", res.status()); - } - Err(e) => { - error!("POST borked: {:?}", e); - } - } - - Ok(true) - } -} +} \ No newline at end of file diff --git a/rnex-core/src/prudp/encryption.rs b/rnex-core/src/prudp/encryption.rs deleted file mode 100644 index aef3739..0000000 --- a/rnex-core/src/prudp/encryption.rs +++ /dev/null @@ -1,20 +0,0 @@ -use std::sync::LazyLock; - -use rc4::{Key, StreamCipher}; -use typenum::U5; - -pub struct EncryptionPair { - pub send: T, - pub recv: T, -} - -impl EncryptionPair { - pub fn init_both T>(func: F) -> Self { - Self { - recv: func(), - send: func(), - } - } -} - -pub static DEFAULT_KEY: LazyLock> = LazyLock::new(|| Key::from(*b"CD&ML")); diff --git a/rnex-core/src/prudp/mod.rs b/rnex-core/src/prudp/mod.rs index 501463a..093723d 100644 --- a/rnex-core/src/prudp/mod.rs +++ b/rnex-core/src/prudp/mod.rs @@ -1,6 +1,3 @@ -pub mod encryption; -pub mod socket_addr; -pub mod station_url; -pub mod ticket; -pub mod types_flags; pub mod virtual_port; +pub mod station_url; +pub mod socket_addr; \ No newline at end of file diff --git a/rnex-core/src/prudp/socket_addr.rs b/rnex-core/src/prudp/socket_addr.rs index e7cdf94..f5eb179 100644 --- a/rnex-core/src/prudp/socket_addr.rs +++ b/rnex-core/src/prudp/socket_addr.rs @@ -1,41 +1,37 @@ -use hmac::Hmac; -use macros::RmcSerialize; -use md5::digest::Mac; -use rnex_core::prudp::virtual_port::VirtualPort; use std::io::Write; -use std::net::{IpAddr, SocketAddr}; +use std::net::SocketAddrV4; +use hmac::{Hmac}; +use md5::digest::Mac; +use macros::RmcSerialize; +use rnex_core::prudp::virtual_port::VirtualPort; type Md5Hmac = Hmac; #[derive(Eq, PartialEq, Hash, Debug, Copy, Clone, Ord, PartialOrd, RmcSerialize)] #[rmc_struct(0)] -pub struct PRUDPSockAddr { - pub regular_socket_addr: SocketAddr, - pub virtual_port: VirtualPort, +pub struct PRUDPSockAddr{ + pub regular_socket_addr: SocketAddrV4, + pub virtual_port: VirtualPort } -impl PRUDPSockAddr { - pub fn new(regular_socket_addr: SocketAddr, virtual_port: VirtualPort) -> Self { - Self { + + +impl PRUDPSockAddr{ + pub fn new(regular_socket_addr: SocketAddrV4, virtual_port: VirtualPort) -> Self{ + Self{ regular_socket_addr, - virtual_port, + virtual_port } } pub fn calculate_connection_signature(&self) -> [u8; 16] { - let mut hmac = Md5Hmac::new_from_slice(&[0; 16]).expect("?"); + let mut hmac = Md5Hmac::new_from_slice(&[0; 16]).expect("fuck"); - let data = match self.regular_socket_addr.ip() { - IpAddr::V4(v) => v.octets().to_vec(), - IpAddr::V6(v) => v.octets().to_vec(), - }; + let data = self.regular_socket_addr.ip().octets().to_vec(); //data.extend_from_slice(&self.regular_socket_addr.port().to_be_bytes()); - hmac.write_all(&data) - .expect("figuring this out was complete ass"); - let result: [u8; 16] = hmac.finalize().into_bytes()[0..16] - .try_into() - .expect("fuck"); + hmac.write_all(&data).expect("figuring this out was complete ass"); + let result: [u8; 16] = hmac.finalize().into_bytes()[0..16].try_into().expect("fuck"); result } -} +} \ No newline at end of file diff --git a/rnex-core/src/prudp/station_url.rs b/rnex-core/src/prudp/station_url.rs index e2d4abf..a4665c2 100644 --- a/rnex-core/src/prudp/station_url.rs +++ b/rnex-core/src/prudp/station_url.rs @@ -1,35 +1,32 @@ -use crate::prudp::station_url::Type::{PRUDP, PRUDPS, UDP}; -use crate::prudp::station_url::UrlOptions::{ - Address, ConnectionID, NatFiltering, NatMapping, NatType, PID, PMP, Platform, Port, - PrincipalID, RVConnectionID, StreamID, StreamType, UPNP, -}; -use crate::rmc::structures::Error::StationUrlInvalid; -use crate::rmc::structures::RmcSerialize; -use crate::rmc::structures::helpers::DummyFormatWriter; +use std::net::Ipv4Addr; use log::error; use std::fmt::{Debug, Display, Formatter, Write}; use std::io::Read; -use std::net::IpAddr; +use crate::prudp::station_url::Type::{PRUDP, PRUDPS, UDP}; +use crate::prudp::station_url::UrlOptions::{Address, ConnectionID, NatFiltering, NatMapping, NatType, Platform, PMP, Port, PrincipalID, RVConnectionID, StreamID, StreamType, UPNP, PID}; +use crate::rmc::structures::Error::StationUrlInvalid; +use crate::rmc::structures::helpers::DummyFormatWriter; +use crate::rmc::structures::RmcSerialize; #[derive(Clone, Copy, PartialEq, Eq)] -pub enum Type { +pub enum Type{ UDP, PRUDP, - PRUDPS, + PRUDPS } -pub mod nat_types { +pub mod nat_types{ pub const BEHIND_NAT: u8 = 1; pub const PUBLIC: u8 = 2; } #[derive(Clone, Eq, PartialEq)] pub enum UrlOptions { - Address(IpAddr), + Address(Ipv4Addr), Port(u16), StreamType(u8), StreamID(u8), ConnectionID(u8), - PrincipalID(rnex_core::PID), + PrincipalID(u32), NatType(u8), NatMapping(u8), NatFiltering(u8), @@ -38,52 +35,82 @@ pub enum UrlOptions { Platform(u8), PMP(u8), PID(u32), + } #[derive(Clone, PartialEq, Eq)] -pub struct StationUrl { +pub struct StationUrl{ pub url_type: Type, - pub options: Vec, + pub options: Vec } -impl StationUrl { - pub fn read_options(options: &str) -> Option> { +impl StationUrl{ + pub fn read_options(options: &str) -> Option>{ let mut options_out = Vec::new(); - for option in options.split(';') { - if option == "" { - continue; - } + for option in options.split(';'){ + if option == "" { continue; } let mut option_parts = option.split('='); - let option_name = option_parts.next()?.to_ascii_lowercase(); + let option_name= option_parts.next()?.to_ascii_lowercase(); let option_value = option_parts.next()?; - match option_name.as_ref() { - "address" => options_out.push(Address(option_value.parse().ok()?)), - "port" => options_out.push(Port(option_value.parse().ok()?)), - "natf" => options_out.push(NatFiltering(option_value.parse().ok()?)), - "natm" => options_out.push(NatMapping(option_value.parse().ok()?)), - "sid" => options_out.push(StreamID(option_value.parse().ok()?)), - "upnp" => options_out.push(UPNP(option_value.parse().ok()?)), - "type" => options_out.push(NatType(option_value.parse().ok()?)), - "stream" => options_out.push(StreamType(option_value.parse().ok()?)), - "RVCID" => options_out.push(RVConnectionID(option_value.parse().ok()?)), - "rvcid" => options_out.push(RVConnectionID(option_value.parse().ok()?)), - "pl" => options_out.push(Platform(option_value.parse().ok()?)), - "pmp" => options_out.push(PMP(option_value.parse().ok()?)), - "pid" => options_out.push(PID(option_value.parse().ok()?)), - "PID" => options_out.push(PID(option_value.parse().ok()?)), + match option_name.as_ref(){ + "address" => { + options_out.push(Address(option_value.parse().ok()?)) + }, + "port" => { + options_out.push(Port(option_value.parse().ok()?)) + } + "natf" => { + options_out.push(NatFiltering(option_value.parse().ok()?)) + } + "natm" => { + options_out.push(NatMapping(option_value.parse().ok()?)) + } + "sid" => { + options_out.push(StreamID(option_value.parse().ok()?)) + } + "upnp" => { + options_out.push(UPNP(option_value.parse().ok()?)) + } + "type" => { + options_out.push(NatType(option_value.parse().ok()?)) + } + "stream" => { + options_out.push(StreamType(option_value.parse().ok()?)) + } + "RVCID" => { + options_out.push(RVConnectionID(option_value.parse().ok()?)) + } + "rvcid" => { + options_out.push(RVConnectionID(option_value.parse().ok()?)) + } + "pl" => { + options_out.push(Platform(option_value.parse().ok()?)) + } + "pmp" => { + options_out.push(PMP(option_value.parse().ok()?)) + }, + "pid" => { + options_out.push(PID(option_value.parse().ok()?)) + }, + "PID" => { + options_out.push(PID(option_value.parse().ok()?)) + }, _ => { error!("unimplemented option type, skipping: {}", option_name); } } + + + } Some(options_out) } } -impl TryFrom<&str> for StationUrl { +impl TryFrom<&str> for StationUrl{ type Error = (); fn try_from(value: &str) -> Result { @@ -91,30 +118,35 @@ impl TryFrom<&str> for StationUrl { let options = &options[2..]; - let url_type = match url_type { + let url_type = match url_type{ "udp" => UDP, "prudp" => PRUDP, "prudps" => PRUDPS, - _ => return Err(()), + _ => return Err(()) }; let options = Self::read_options(options).ok_or(())?; - Ok(Self { url_type, options }) + Ok( + Self{ + url_type, + options + } + ) } } -impl Display for StationUrl { +impl Display for StationUrl{ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - let url_type_str = match self.url_type { + let url_type_str = match self.url_type{ UDP => "udp:/", PRUDP => "prudp:/", - PRUDPS => "prudps:/", + PRUDPS => "prudps:/" }; - write!(f, "{}", url_type_str)?; + write!(f, "{}",url_type_str)?; - for option in &self.options { - match option { + for option in &self.options{ + match option{ Address(v) => write!(f, "address={}", v)?, Port(v) => write!(f, "port={}", v)?, StreamType(v) => write!(f, "stream={}", v)?, @@ -136,15 +168,15 @@ impl Display for StationUrl { } } -impl<'a> Into for &'a StationUrl { +impl<'a> Into for &'a StationUrl{ fn into(self) -> String { let url = self.to_string(); - - url[0..url.len() - 1].into() + + url[0..url.len()-1].into() } } -impl RmcSerialize for StationUrl { +impl RmcSerialize for StationUrl{ fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result { let str = String::deserialize(reader)?; @@ -165,9 +197,9 @@ impl RmcSerialize for StationUrl { } } -impl Debug for StationUrl { +impl Debug for StationUrl{ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let str: String = self.into(); f.write_str(&str) } -} +} \ No newline at end of file diff --git a/rnex-core/src/prudp/ticket.rs b/rnex-core/src/prudp/ticket.rs deleted file mode 100644 index 97dc5d5..0000000 --- a/rnex-core/src/prudp/ticket.rs +++ /dev/null @@ -1,79 +0,0 @@ -use std::io::Cursor; - -use log::{error, info}; -use rc4::{KeyInit, Rc4, Rc4Core, StreamCipher, cipher::StreamCipherCoreWrapper}; -use typenum::U16; -use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions}; - -use crate::{ - kerberos::{SESSION_KEY_LENGTH, SessionLengthTy, TicketInternalData, derive_key}, - nex::account::Account, - rmc::structures::RmcSerialize, -}; -use rnex_core::PID; - -pub fn read_secure_connection_data( - data: &[u8], - act: &Account, -) -> Option<([u8; SESSION_KEY_LENGTH], PID, u32)> { - let mut cursor = Cursor::new(data); - - let mut ticket_data: Vec = Vec::deserialize(&mut cursor).ok()?; - let mut request_data: Vec = Vec::deserialize(&mut cursor).ok()?; - info!("done request data {}", SESSION_KEY_LENGTH); - - let ticket_data_size = ticket_data.len(); - - let ticket_data = &mut ticket_data[0..ticket_data_size - 0x10]; - - let server_key = derive_key(act.pid, &act.kerbros_password[..]); - - let mut rc4: StreamCipherCoreWrapper> = - Rc4::new_from_slice(&server_key).expect("unable to init rc4 keystream"); - - rc4.apply_keystream(ticket_data); - - let ticket_data: &TicketInternalData = match bytemuck::try_from_bytes(ticket_data) { - Ok(v) => v, - Err(e) => { - error!("unable to read internal ticket data: {}", e); - return None; - } - }; - - // todo: add ticket expiration - - let TicketInternalData { - session_key, - pid: ticket_source_pid, - issued_time, - } = *ticket_data; - - // todo: add checking if tickets are signed with a valid md5-hmac - let request_data_length = request_data.len(); - let request_data = &mut request_data[0..request_data_length - 0x10]; - - let mut rc4: StreamCipherCoreWrapper> = - Rc4::new_from_slice(&session_key).expect("unable to init rc4 keystream"); - - rc4.apply_keystream(request_data); - - let mut reqest_data_cursor = Cursor::new(request_data); - - let pid: PID = reqest_data_cursor.read_struct(IS_BIG_ENDIAN).ok()?; - - if pid != ticket_source_pid { - let ticket_created_on = issued_time.to_regular_time(); - - error!( - "someone tried to spoof their pid, ticket was created on: {}", - ticket_created_on.to_rfc2822() - ); - return None; - } - - let _cid: u32 = reqest_data_cursor.read_struct(IS_BIG_ENDIAN).ok()?; - let response_check: u32 = reqest_data_cursor.read_struct(IS_BIG_ENDIAN).ok()?; - - Some((session_key, pid, response_check)) -} diff --git a/rnex-core/src/prudp/types_flags.rs b/rnex-core/src/prudp/types_flags.rs deleted file mode 100644 index e9886e4..0000000 --- a/rnex-core/src/prudp/types_flags.rs +++ /dev/null @@ -1,64 +0,0 @@ -use std::fmt::{Debug, Formatter}; - -use bytemuck::{Pod, Zeroable}; -use v_byte_helpers::SwapEndian; - -#[repr(transparent)] -#[derive(Copy, Clone, Pod, Zeroable, SwapEndian, Default, Eq, PartialEq)] -pub struct TypesFlags(pub u16); - -impl TypesFlags { - #[inline] - pub const fn get_types(self) -> u8 { - (self.0 & 0x000F) as u8 - } - #[inline] - pub const fn get_flags(self) -> u16 { - (self.0 & 0xFFF0) >> 4 - } - #[inline] - pub const fn types(self, val: u8) -> Self { - Self((self.0 & 0xFFF0) | (val as u16 & 0x000F)) - } - #[inline] - pub const fn flags(self, val: u16) -> Self { - Self((self.0 & 0x000F) | ((val << 4) & 0xFFF0)) - } - #[inline] - pub const fn set_flag(&mut self, val: u16) { - self.0 |= (val & 0xFFF) << 4; - } - #[inline] - pub const fn set_types(&mut self, val: u8) { - self.0 |= val as u16 & 0x0F; - } -} -impl Debug for TypesFlags { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - let stream_type = self.get_types(); - let port_number = self.get_flags(); - write!( - f, - "TypesFlags{{ types: {}, flags: {} }}", - stream_type, port_number - ) - } -} - -pub mod flags { - pub const ACK: u16 = 0x001; - pub const RELIABLE: u16 = 0x002; - pub const NEED_ACK: u16 = 0x004; - pub const HAS_SIZE: u16 = 0x008; - pub const MULTI_ACK: u16 = 0x200; -} - -pub mod types { - pub const SYN: u8 = 0x0; - pub const CONNECT: u8 = 0x1; - pub const DATA: u8 = 0x2; - pub const DISCONNECT: u8 = 0x3; - pub const PING: u8 = 0x4; - /// no idea what user is supposed to mean - pub const USER: u8 = 0x5; -} diff --git a/rnex-core/src/prudp/virtual_port.rs b/rnex-core/src/prudp/virtual_port.rs index b23b5d0..54d2eeb 100644 --- a/rnex-core/src/prudp/virtual_port.rs +++ b/rnex-core/src/prudp/virtual_port.rs @@ -1,5 +1,5 @@ -use bytemuck::{Pod, Zeroable}; use std::fmt::{Debug, Formatter}; +use bytemuck::{Pod, Zeroable}; use v_byte_helpers::SwapEndian; #[repr(transparent)] @@ -7,6 +7,7 @@ use v_byte_helpers::SwapEndian; pub struct VirtualPort(pub u8); impl VirtualPort { + #[inline] pub const fn get_stream_type(self) -> u8 { (self.0 & 0xF0) >> 4 @@ -37,21 +38,12 @@ impl VirtualPort { pub fn new(port: u8, stream_type: u8) -> Self { Self(0).stream_type(stream_type).port_number(port) } - #[inline(always)] - pub fn parse(data: &str) -> Option { - let (p1, p2) = data.split_once(':')?; - Some(Self::new(p1.parse().ok()?, p2.parse().ok()?)) - } } impl Debug for VirtualPort { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let stream_type = self.get_stream_type(); let port_number = self.get_port_number(); - write!( - f, - "VirtualPort{{ stream_type: {}, port_number: {} }}", - stream_type, port_number - ) + write!(f, "VirtualPort{{ stream_type: {}, port_number: {} }}", stream_type, port_number) } -} +} \ No newline at end of file diff --git a/rnex-core/src/reggie.rs b/rnex-core/src/reggie.rs index 39f12de..47bf2d2 100644 --- a/rnex-core/src/reggie.rs +++ b/rnex-core/src/reggie.rs @@ -1,13 +1,13 @@ -use crate::define_rmc_proto; -use crate::rmc::structures::RmcSerialize; -use macros::{RmcSerialize, method_id, rmc_proto}; -use rnex_core::rmc::response::ErrorCode; use std::io; use std::net::SocketAddrV4; +use macros::{method_id, rmc_proto, RmcSerialize}; use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; +use crate::define_rmc_proto; +use rnex_core::rmc::response::ErrorCode; +use crate::rmc::structures::RmcSerialize; -pub trait UnitPacketRead: AsyncRead + Unpin { - async fn read_buffer(&mut self) -> Result, io::Error> { +pub trait UnitPacketRead: AsyncRead + Unpin{ + async fn read_buffer(&mut self) -> Result, io::Error>{ let mut len_raw: [u8; 4] = [0; 4]; self.read_exact(&mut len_raw).await?; @@ -22,13 +22,12 @@ pub trait UnitPacketRead: AsyncRead + Unpin { } } -impl UnitPacketRead for T {} -pub trait UnitPacketWrite: AsyncWrite + Unpin { +impl UnitPacketRead for T{} +pub trait UnitPacketWrite: AsyncWrite + Unpin{ async fn send_buffer(&mut self, data: &[u8]) -> Result<(), io::Error> { let mut dest_data = Vec::new(); - data.serialize(&mut dest_data) - .expect("ran out of memory or something"); + data.serialize(&mut dest_data).expect("ran out of memory or something"); self.write_all(&dest_data[..]).await?; @@ -38,7 +37,9 @@ pub trait UnitPacketWrite: AsyncWrite + Unpin { } } -impl UnitPacketWrite for T {} +impl UnitPacketWrite for T{} + + #[rmc_proto(1)] pub trait EdgeNodeManagement { @@ -54,7 +55,7 @@ define_rmc_proto!( #[derive(RmcSerialize, Debug)] #[repr(u32)] -pub enum EdgeNodeHolderConnectOption { +pub enum EdgeNodeHolderConnectOption{ DontRegister = 0, - Register(SocketAddrV4) = 1, + Register(SocketAddrV4) = 1 } diff --git a/rnex-core/src/rmc/message.rs b/rnex-core/src/rmc/message.rs index 4fcdfbe..cf951bf 100644 --- a/rnex-core/src/rmc/message.rs +++ b/rnex-core/src/rmc/message.rs @@ -42,8 +42,7 @@ impl RMCMessage{ error!("received incorrect rmc packet: expected size {} but found {}", size, header_size + rest_of_data.len()); } - // println!("rmc packet: protoid: {}, method id: {}", protocol_id, method_id); - // println!("{}", hex::encode(&rest_of_data)); + //stream. Ok(Self{ diff --git a/rnex-core/src/rmc/protocols/account_management.rs b/rnex-core/src/rmc/protocols/account_management.rs deleted file mode 100644 index 8ef2d9e..0000000 --- a/rnex-core/src/rmc/protocols/account_management.rs +++ /dev/null @@ -1,30 +0,0 @@ -use macros::{RmcSerialize, method_id, rmc_proto}; - -use rnex_core::{ - PID, - rmc::{response::ErrorCode, structures::any::Any}, -}; - -use crate::{kerberos::KerberosDateTime, rmc::protocols::friends::NNAInfo}; - -#[derive(RmcSerialize, Debug, Clone)] -#[rmc_struct(0)] -pub struct NintendoCreateAccountData { - pub nna_info: NNAInfo, - pub nex_token: String, - pub birthday: KerberosDateTime, - pub unk: u64, -} - -#[rmc_proto(25)] -pub trait AccountManagement { - #[method_id(27)] - async fn nintendo_create_account( - &self, - principal_name: String, - key: String, - groups: u32, - email: String, - auth_data: Any, - ) -> Result<(PID, String), ErrorCode>; -} diff --git a/rnex-core/src/rmc/protocols/auth.rs b/rnex-core/src/rmc/protocols/auth.rs index a065418..49feb2b 100644 --- a/rnex-core/src/rmc/protocols/auth.rs +++ b/rnex-core/src/rmc/protocols/auth.rs @@ -1,47 +1,36 @@ -use crate::rmc::structures::connection_data::{ConnectionData, ConnectionDataOld}; -use cfg_if::cfg_if; -use macros::{method_id, rmc_proto}; -use rnex_core::PID; use rnex_core::rmc::response::ErrorCode; use rnex_core::rmc::structures::any::Any; +use crate::rmc::structures::connection_data::ConnectionData; use rnex_core::rmc::structures::qresult::QResult; +use macros::{method_id, rmc_proto}; -cfg_if! { - if #[cfg(feature = "nx")]{ - type LoginExRet = (QResult, PID, Vec, ConnectionData, String, String); - type RequestTicketRet = (QResult, Vec, String); - } else { - type LoginExRet = (QResult, PID, Vec, ConnectionData, String); - type RequestTicketRet = (QResult, Vec); - } -} -/// This is the representation for `Ticket Granting`(for details see the +/// This is the representation for `Ticket Granting`(for details see the /// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol)) #[rmc_proto(10)] pub trait Auth { /// representation of the `Login` method(for details see the /// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol)) #[method_id(1)] - async fn login( - &self, - name: String, - ) -> Result<(QResult, PID, Vec, ConnectionDataOld, String), ErrorCode>; + async fn login(&self, name: String) -> Result<(), ErrorCode>; /// representation of the `LoginEx` method(for details see the /// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol)) #[method_id(2)] - async fn login_ex(&self, name: String, extra_data: Any) -> Result; - - #[method_id(3)] - async fn request_ticket( + async fn login_ex( &self, - source_pid: PID, - destination_pid: PID, - ) -> Result; + name: String, + extra_data: Any, + ) -> Result<(QResult, u32, Vec, ConnectionData, String), ErrorCode>; /// representation of the `RequestTicket` method(for details see the /// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol)) + #[method_id(3)] + async fn request_ticket( + &self, + source_pid: u32, + destination_pid: u32, + ) -> Result<(QResult, Vec), ErrorCode>; /// representation of the `GetPID` method(for details see the /// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol)) @@ -51,7 +40,7 @@ pub trait Auth { /// representation of the `LoginWithContext` method(for details see the /// [kinnay wiki entry](https://github.com/kinnay/NintendoClients/wiki/Authentication-Protocol)) #[method_id(5)] - async fn get_name(&self, pid: PID) -> Result; + async fn get_name(&self, pid: u32) -> Result; // `LoginWithContext` is left out here because we don't need it right now and versioning still // needs to be figured out diff --git a/rnex-core/src/rmc/protocols/datastore.rs b/rnex-core/src/rmc/protocols/datastore.rs deleted file mode 100644 index 51d5365..0000000 --- a/rnex-core/src/rmc/protocols/datastore.rs +++ /dev/null @@ -1,266 +0,0 @@ -use macros::{RmcSerialize, method_id, rmc_proto}; -use rnex_core::PID; -use rnex_core::kerberos::KerberosDateTime; -use rnex_core::rmc::response::ErrorCode; -use rnex_core::rmc::structures::qbuffer::QBuffer; -use rnex_core::rmc::structures::qresult::QResult; -use rnex_core::rmc::structures::resultsrange::ResultsRange; - -#[derive(RmcSerialize, Clone, Debug, Default)] -#[rmc_struct(0)] -pub struct PersistenceTarget { - pub owner: PID, - pub persistence_slot_id: u16, -} - -#[derive(RmcSerialize, Clone, Debug, Default)] -#[rmc_struct(0)] -pub struct Permission { - pub permission: u8, - pub recipient_ids: Vec, -} - -#[derive(RmcSerialize, Clone)] -#[rmc_struct(0)] -pub struct RatingInfoWithSlot { - pub slot: i8, - pub rating: RatingInfo, -} - -#[derive(RmcSerialize, Clone)] -#[rmc_struct(0)] -pub struct RatingInfo { - pub total_value: i64, - pub count: u32, - pub initial_value: i64, -} - -#[derive(RmcSerialize, Clone, Default)] -#[rmc_struct(0)] -pub struct GetMetaParam { - pub dataid: u64, - pub persistence_target: PersistenceTarget, - pub result_option: u8, - pub access_password: u64, -} - -#[derive(RmcSerialize, Clone, Default)] -#[rmc_struct(0)] -pub struct GetMetaInfo { - pub dataid: u64, - pub owner: PID, - pub size: u32, - pub name: String, - pub data_type: u16, - pub meta_binary: QBuffer, - pub permission: Permission, - pub del_permission: Permission, - pub created_time: KerberosDateTime, - pub updated_time: KerberosDateTime, - pub period: u16, - pub status: u8, - pub referred_count: u32, - pub refer_dat_id: u32, - pub flag: u32, - pub referred_time: KerberosDateTime, - pub expire_time: KerberosDateTime, - pub tags: Vec, - pub ratings: Vec, -} - -#[derive(RmcSerialize, Clone)] -#[rmc_struct(0)] -pub struct RatingInitParam { - pub flag: u8, - pub internal_flag: u8, - pub lock_type: u8, - pub intial_valie: i64, - pub range_min: i32, - pub range_max: i32, - pub period_hour: i8, - pub period_duration: i16, -} - -#[derive(RmcSerialize, Clone)] -#[rmc_struct(0)] -pub struct RatingInitParamWithSlot { - pub slot: i8, - pub param: RatingInitParam, -} - -#[derive(RmcSerialize, Clone)] -#[rmc_struct(0)] -pub struct PersistenceInitParam { - pub persistence_slot_id: u16, - pub delete_last_object: bool, -} - -#[derive(RmcSerialize, Clone)] -#[rmc_struct(0)] -pub struct KeyValue { - pub key: String, - pub value: String, -} - -#[derive(RmcSerialize, Clone)] -#[rmc_struct(0)] -pub struct PreparePostParam { - pub size: u32, - pub name: String, - pub data_type: u16, - pub meta_binary: QBuffer, - pub permission: Permission, - pub del_permission: Permission, - pub flag: u32, - pub period: u16, - pub refer_data_id: u32, - pub tags: Vec, - pub rating_init_params: Vec, - pub persistence_init_param: PersistenceInitParam, - pub extra_data: Vec, -} - -#[derive(RmcSerialize, Clone)] -#[rmc_struct(0)] -pub struct ReqPostInfo { - pub dataid: u64, - pub url: String, - pub request_headers: Vec, - pub form_fields: Vec, - pub root_ca_cert: Vec, -} - -#[derive(RmcSerialize, Clone)] -#[rmc_struct(0)] -pub struct CompletePostParam { - pub dataid: u64, - pub success: bool, -} - -#[derive(RmcSerialize, Clone)] -#[rmc_struct(0)] -pub struct RateCustomRankingParam { - pub dataid: u64, - pub appid: u32, - pub score: u32, - pub period: u16, -} - -#[derive(RmcSerialize, Clone)] -#[rmc_struct(0)] -pub struct BufferQueueParam { - pub dataid: u64, - pub slot: u32, -} - -// I just realized I forgot to add "DataStore" in front of the structs. I can't be assed to change it, sucks to be you lol. - -#[derive(RmcSerialize, Clone)] -#[rmc_struct(0)] -pub struct DataStoreGetCustomRankingByDataIDParam { - pub application_id: u32, - pub data_id_list: Vec, - pub result_option: u8, -} - -#[derive(RmcSerialize, Clone)] -#[rmc_struct(0)] -pub struct DataStoreCustomRankingResult { - pub order: u32, - pub score: u32, - pub meta_info: GetMetaInfo, -} - -#[derive(RmcSerialize, Clone)] -#[rmc_struct(0)] -pub struct DataStorePrepareGetParam { - pub dataid: u64, - pub lockid: u32, - pub persistence_target: PersistenceTarget, - pub access_password: u64, - pub extra_data: Vec, -} - -#[derive(RmcSerialize, Clone)] -#[rmc_struct(0)] -pub struct DataStoreReqGetInfo { - pub url: String, - pub request_headers: Vec, - pub size: u32, - pub root_ca_cert: Vec, - pub dataid: u64, -} - -#[derive(RmcSerialize, Clone)] -#[rmc_struct(1)] -pub struct DataStoreSearchParam { - pub search_target: u8, - pub owner_ids: Vec, - pub owner_type: u8, - pub destination_ids: Vec, - pub data_type: u16, - pub created_after: KerberosDateTime, - pub created_before: KerberosDateTime, - pub updated_after: KerberosDateTime, - pub updated_before: KerberosDateTime, - pub refer_dat_id: u32, - pub tags: Vec, - pub result_order_column: u8, - pub result_order: u8, - pub result_range: ResultsRange, - pub result_option: u8, - pub minimal_rating_frequency: u32, - pub use_cache: bool, -} - -#[rmc_proto(115)] -pub trait DataStore { - #[method_id(8)] - async fn get_meta(&self, metaparam: GetMetaParam) -> Result; - #[method_id(36)] - async fn get_metas_multiple_param( - &self, - params: Vec, - ) -> Result<(Vec, Vec), ErrorCode>; - #[method_id(24)] - async fn prepare_post_object( - &self, - postparam: PreparePostParam, - ) -> Result; - #[method_id(26)] - async fn complete_post_object(&self, completeparam: CompletePostParam) - -> Result<(), ErrorCode>; - #[method_id(48)] - async fn rate_custom_ranking( - &self, - rankingparam: Vec, - ) -> Result<(), ErrorCode>; - #[method_id(61)] - async fn get_application_config(&self, appid: u32) -> Result, ErrorCode>; - #[method_id(50)] - async fn get_custom_ranking_by_data_id( - &self, - custom_ranking_param: DataStoreGetCustomRankingByDataIDParam, - ) -> Result<(Vec, Vec), ErrorCode>; - #[method_id(54)] - async fn get_buffer_queue( - &self, - bufferparam: BufferQueueParam, - ) -> Result, ErrorCode>; - #[method_id(25)] - async fn prepare_get_object( - &self, - prepare_get_param: DataStorePrepareGetParam, - ) -> Result; - #[method_id(65)] - async fn followings_latest_course_search_object( - &self, - course_search_param: DataStoreSearchParam, - extra_data: Vec, - ) -> Result, ErrorCode>; - #[method_id(74)] - async fn get_application_config_string( - &self, - application_id: u32, - ) -> Result, ErrorCode>; -} diff --git a/rnex-core/src/rmc/protocols/friends.rs b/rnex-core/src/rmc/protocols/friends.rs deleted file mode 100644 index d25ea9e..0000000 --- a/rnex-core/src/rmc/protocols/friends.rs +++ /dev/null @@ -1,183 +0,0 @@ -use macros::{RmcSerialize, method_id, rmc_proto}; - -use rnex_core::{kerberos::KerberosDateTime, rmc::response::ErrorCode}; - -use rnex_core::rmc::structures::data::Data; - -#[derive(RmcSerialize, Debug, Clone)] -#[rmc_struct(0)] -pub struct MiiV2 { - #[extends] - pub data: Data, - pub name: String, - pub unk: u8, - pub unk2: u8, - pub mii_data: Vec, - pub date_time: KerberosDateTime, -} - -#[derive(RmcSerialize, Debug, Clone)] -#[rmc_struct(0)] -pub struct PrincipalBasicInfo { - #[extends] - pub data: Data, - pub pid: u32, - pub nnid: String, - pub mii: MiiV2, - pub unk: u8, -} - -#[derive(RmcSerialize, Debug, Clone)] -#[rmc_struct(0)] -pub struct NNAInfo { - #[extends] - pub data: Data, - pub principal_basic_info: PrincipalBasicInfo, - pub unk: u8, - pub unk2: u8, -} - -#[derive(RmcSerialize, Clone, Copy, Debug)] -#[rmc_struct(0)] -pub struct GameKey { - #[extends] - pub data: Data, - pub tid: u64, - pub version: u16, -} - -#[derive(RmcSerialize, Clone, Debug)] -#[rmc_struct(0)] -pub struct NintendoPresenceV2 { - #[extends] - pub data: Data, - pub changed_flags: u32, - pub is_online: bool, - pub game_key: GameKey, - pub unk: u8, - pub message: String, - pub unk2: u32, - pub unk3: u8, - pub game_server_id: u32, - pub unk4: u32, - pub pid: u32, - pub gid: u32, - pub app_data: Vec, - pub unk5: u8, - pub unk6: u8, - pub unk7: u8, -} -#[derive(RmcSerialize, Clone, Debug)] -#[rmc_struct(0)] -pub struct PrincipalPreference { - #[extends] - pub data: Data, - pub show_online: bool, - pub show_playing_title: bool, - pub block_friend_request: bool, -} - -#[derive(RmcSerialize)] -#[rmc_struct(0)] -pub struct Comment { - #[extends] - pub data: Data, - pub unk: u8, - pub message: String, - pub last_changed: KerberosDateTime, -} - -#[derive(RmcSerialize)] -#[rmc_struct(0)] -pub struct FriendInfo { - #[extends] - pub data: Data, - pub nna_info: NNAInfo, - pub presence: NintendoPresenceV2, - pub comment: Comment, - pub became_friends: KerberosDateTime, - pub last_online: KerberosDateTime, - pub unk: u64, -} - -#[derive(RmcSerialize)] -#[rmc_struct(0)] -pub struct FriendRequestMessage { - #[extends] - pub data: Data, - pub friend_request_id: u64, - pub is_recieved: u8, - pub unk: u8, - pub message: String, - pub unk2: u8, - pub unk3: String, - pub game_key: GameKey, - pub unk4: KerberosDateTime, - pub expires_on: KerberosDateTime, -} - -#[derive(RmcSerialize)] -#[rmc_struct(0)] -pub struct FriendRequest { - #[extends] - pub data: Data, - pub basic_info: PrincipalBasicInfo, - pub request_message: FriendRequestMessage, - pub sent_on: KerberosDateTime, -} - -#[derive(RmcSerialize)] -#[rmc_struct(0)] -pub struct BlacklistedPrincipal { - #[extends] - pub data: Data, - pub basic_info: PrincipalBasicInfo, - pub game_key: GameKey, - pub since: KerberosDateTime, -} -#[derive(RmcSerialize)] -#[rmc_struct(0)] -pub struct PersistentNotification { - #[extends] - pub data: Data, - pub unk1: u64, - pub unk2: u32, - pub unk3: u32, - pub unk4: u32, - pub unk5: String, -} - -#[rmc_proto(102)] -pub trait Friends { - #[method_id(1)] - async fn update_and_get_all_information( - &self, - info: NNAInfo, - presence: NintendoPresenceV2, - date_time: KerberosDateTime, - ) -> Result< - ( - PrincipalPreference, - Comment, - Vec, - Vec, - Vec, - Vec, - bool, - Vec, - bool, - ), - ErrorCode, - >; - #[method_id(13)] - async fn update_presence(&self, presence: NintendoPresenceV2) -> Result<(), ErrorCode>; - #[method_id(16)] - async fn update_preference(&self, preference: PrincipalPreference) -> Result<(), ErrorCode>; - #[method_id(18)] - async fn delete_persistent_notification( - &self, - notifs: Vec, - ) -> Result<(), ErrorCode>; - #[method_id(19)] - async fn check_setting_status(&self) -> Result; -} diff --git a/rnex-core/src/rmc/protocols/matchmake.rs b/rnex-core/src/rmc/protocols/matchmake.rs index d1c43b9..595127a 100644 --- a/rnex-core/src/rmc/protocols/matchmake.rs +++ b/rnex-core/src/rmc/protocols/matchmake.rs @@ -2,25 +2,14 @@ use macros::{method_id, rmc_proto}; use rnex_core::prudp::station_url::StationUrl; use rnex_core::rmc::response::ErrorCode; -use rnex_core::PID; - -use crate::rmc::structures::any::Any; - #[rmc_proto(21)] -pub trait Matchmake { +pub trait Matchmake{ #[method_id(2)] async fn unregister_gathering(&self, gid: u32) -> Result; - #[method_id(21)] - async fn find_by_single_id(&self, gid: u32) -> Result<(bool, Any), ErrorCode>; #[method_id(41)] async fn get_session_urls(&self, gid: u32) -> Result, ErrorCode>; #[method_id(42)] async fn update_session_host(&self, gid: u32, change_owner: bool) -> Result<(), ErrorCode>; #[method_id(44)] - async fn migrate_gathering_ownership( - &self, - gid: u32, - candidates: Vec, - participants_only: bool, - ) -> Result<(), ErrorCode>; -} + async fn migrate_gathering_ownership(&self, gid: u32, candidates: Vec, participants_only: bool) -> Result<(), ErrorCode>; +} \ No newline at end of file diff --git a/rnex-core/src/rmc/protocols/matchmake_extension.rs b/rnex-core/src/rmc/protocols/matchmake_extension.rs index 7e7a00d..fff5252 100644 --- a/rnex-core/src/rmc/protocols/matchmake_extension.rs +++ b/rnex-core/src/rmc/protocols/matchmake_extension.rs @@ -1,94 +1,32 @@ use macros::{method_id, rmc_proto}; use rnex_core::rmc::response::ErrorCode; -use rnex_core::rmc::structures::matchmake::{ - AutoMatchmakeParam, CreateMatchmakeSessionParam, JoinMatchmakeSessionParam, MatchmakeSession, -}; - -use crate::rmc::protocols::notifications::NotificationEvent; -use crate::rmc::structures::any::Any; -use crate::rmc::structures::matchmake::MatchmakeSessionSearchCriteria; +use rnex_core::rmc::structures::matchmake::{AutoMatchmakeParam, CreateMatchmakeSessionParam, JoinMatchmakeSessionParam, MatchmakeSession}; #[rmc_proto(109)] -pub trait MatchmakeExtension { +pub trait MatchmakeExtension{ #[method_id(1)] async fn close_participation(&self, gid: u32) -> Result<(), ErrorCode>; #[method_id(2)] async fn open_participation(&self, gid: u32) -> Result<(), ErrorCode>; - #[method_id(6)] - async fn create_matchmake_session( - &self, - gathering: Any, - message: String, - ) -> Result<(u32, Vec), ErrorCode>; - - #[method_id(9)] - async fn update_notification_data( - &self, - ty: u32, - param1: u32, - param2: u32, - str_param: String, - ) -> Result<(), ErrorCode>; - - #[method_id(10)] - async fn get_friend_notification_data( - &self, - ty: i32, - ) -> Result, ErrorCode>; - #[method_id(15)] - async fn auto_matchmake_with_search_criteria_postpone( - &self, - criteria: Vec, - gathering: Any, - join_msg: String, - ) -> Result; - - #[method_id(30)] - async fn join_matchmake_session_ex( - &self, - gid: u32, - message: String, - dont_care_block_list: bool, - // this is to cheat support for v3-3-0 - //participation_count: u16, - ) -> Result, ErrorCode>; #[method_id(8)] - async fn modify_current_game_attribute( - &self, - gid: u32, - attrib_index: u32, - attrib_val: u32, - ) -> Result<(), ErrorCode>; + async fn modify_current_game_attribute(&self, gid: u32, attrib_index: u32, attrib_val: u32) -> Result<(), ErrorCode>; #[method_id(16)] async fn get_playing_session(&self, pids: Vec) -> Result, ErrorCode>; #[method_id(34)] - #[cfg(feature = "v3-5-0")] async fn update_progress_score(&self, gid: u32, progress: u8) -> Result<(), ErrorCode>; #[method_id(38)] - async fn create_matchmake_session_with_param( - &self, - session: CreateMatchmakeSessionParam, - ) -> Result; + async fn create_matchmake_session_with_param(&self, session: CreateMatchmakeSessionParam) -> Result; #[method_id(39)] - async fn join_matchmake_session_with_param( - &self, - session: JoinMatchmakeSessionParam, - ) -> Result; + async fn join_matchmake_session_with_param(&self, session: JoinMatchmakeSessionParam) -> Result; #[method_id(40)] - async fn auto_matchmake_with_param_postpone( - &self, - session: AutoMatchmakeParam, - ) -> Result; + async fn auto_matchmake_with_param_postpone(&self, session: AutoMatchmakeParam) -> Result; #[method_id(41)] - async fn find_matchmake_session_by_gathering_id_detail( - &self, - gid: u32, - ) -> Result; -} + async fn find_matchmake_session_by_gathering_id_detail(&self, gid: u32) -> Result; +} \ No newline at end of file diff --git a/rnex-core/src/rmc/protocols/mod.rs b/rnex-core/src/rmc/protocols/mod.rs index 411ae28..0b6fc65 100644 --- a/rnex-core/src/rmc/protocols/mod.rs +++ b/rnex-core/src/rmc/protocols/mod.rs @@ -1,26 +1,20 @@ #![allow(async_fn_in_trait)] -pub mod account_management; pub mod auth; -pub mod datastore; -pub mod friends; +pub mod secure; +pub mod notifications; pub mod matchmake; -pub mod matchmake_ext; pub mod matchmake_extension; pub mod nat_traversal; -pub mod nintendo_notification; -pub mod notifications; +pub mod matchmake_ext; pub mod ranking; -pub mod secure; -pub mod util; -use crate::result::ResultExtension; +use crate::util::{SendingBufferConnection, SplittableBufferConnection}; use crate::rmc::message::RMCMessage; use crate::rmc::protocols::RemoteCallError::ConnectionBroke; use crate::rmc::response::{ErrorCode, RMCResponse, RMCResponseResult}; use crate::rmc::structures; use crate::rmc::structures::RmcSerialize; -use crate::util::{SendingBufferConnection, SplittableBufferConnection}; use log::{error, info}; use std::collections::HashMap; use std::future::Future; @@ -30,7 +24,8 @@ use std::sync::Arc; use std::time::Duration; use thiserror::Error; use tokio::sync::{Mutex, Notify}; -use tokio::time::{Instant, sleep, sleep_until}; +use tokio::time::{sleep, sleep_until, Instant}; +use crate::result::ResultExtension; #[derive(Error, Debug)] pub enum RemoteCallError { @@ -73,7 +68,7 @@ impl RmcConnection { Ok(()) } - pub async fn disconnect(&self) { + pub async fn disconnect(&self){ self.0.disconnect().await; } } @@ -97,11 +92,15 @@ impl RmcResponseReceiver { let mut locked = self.1.lock().await; if let Some(v) = locked.remove(&call_id) { - match v.response_result { - RMCResponseResult::Success { data, .. } => return Ok(data), - RMCResponseResult::Error { error_code, .. } => { - return Err(RemoteCallError::ServerError(error_code)); - } + match v.response_result{ + RMCResponseResult::Success { + data, + .. + } => return Ok(data), + RMCResponseResult::Error { + error_code, + .. + } => return Err(RemoteCallError::ServerError(error_code)) } } @@ -168,14 +167,10 @@ macro_rules! define_rmc_proto { pub struct [](rnex_core::rmc::protocols::RmcConnection); - impl rnex_core::rmc::protocols::RmcPureRemoteObject for []{ + impl rnex_core::rmc::protocols::RemoteInstantiatable for []{ fn new(conn: rnex_core::rmc::protocols::RmcConnection) -> Self{ Self(conn) } - } - - impl rnex_core::rmc::protocols::RemoteDisconnectable for []{ - async fn disconnect(&self){ self.0.disconnect().await; } @@ -208,23 +203,14 @@ impl RmcCallable for () { } } -pub trait RmcPureRemoteObject { +pub trait RemoteInstantiatable{ fn new(conn: RmcConnection) -> Self; -} - -pub trait RemoteDisconnectable { async fn disconnect(&self); } -pub struct OnlyRemote(T); +pub struct OnlyRemote(T); -impl OnlyRemote { - pub fn new(conn: RmcConnection) -> Self { - Self(T::new(conn)) - } -} - -impl Deref for OnlyRemote { +impl Deref for OnlyRemote{ type Target = T; fn deref(&self) -> &Self::Target { @@ -232,23 +218,20 @@ impl Deref for OnlyRemote { } } -impl OnlyRemote { +impl OnlyRemote{ + pub fn new(conn: RmcConnection) -> Self{ + Self(T::new(conn)) + } + pub async fn disconnect(&self) { self.0.disconnect().await; } } -impl RmcCallable for OnlyRemote { - fn rmc_call( - &self, - _responder: &SendingBufferConnection, - _protocol_id: u16, - _method_id: u32, - _call_id: u32, - _rest: Vec, - ) -> impl Future + Send { +impl RmcCallable for OnlyRemote{ + fn rmc_call(&self, _responder: &SendingBufferConnection, _protocol_id: u16, _method_id: u32, _call_id: u32, _rest: Vec) -> impl Future + Send { // maybe respond with not implemented or something - async {} + async{} } } @@ -260,23 +243,23 @@ async fn handle_incoming( ) { let sending_conn = connection.duplicate_sender(); - while let Some(v) = connection.recv().await { + while let Some(v) = connection.recv().await{ let Some(proto_id) = v.get(4) else { error!("received too small rmc message."); error!("ending rmc gateway."); - return; + return }; // protocol 0 is hardcoded to be the no protocol protocol aka keepalive protocol - if *proto_id == 0 { + if *proto_id == 0{ println!("got keepalive"); continue; } - if (proto_id & 0x80) == 0 { + if (proto_id & 0x80) == 0{ let Some(response) = RMCResponse::new(&mut Cursor::new(v)).display_err_or_some() else { error!("ending rmc gateway."); - return; + return }; info!("got rmc response"); @@ -288,34 +271,28 @@ async fn handle_incoming( } else { let Some(message) = RMCMessage::new(&mut Cursor::new(v)).display_err_or_some() else { error!("ending rmc gateway."); - return; + return }; - let RMCMessage { + let RMCMessage{ protocol_id, method_id, call_id, - rest_of_data, + rest_of_data } = message; - info!( - "RMC REQUEST: Proto: {}; Method: {}; cid: {}", - protocol_id, method_id, call_id - ); + info!("RMC REQUEST: Proto: {}; Method: {};", protocol_id, method_id); - remote - .rmc_call(&sending_conn, protocol_id, method_id, call_id, rest_of_data) - .await; + remote.rmc_call(&sending_conn, protocol_id, method_id, call_id, rest_of_data).await; + + } } - + info!("rmc disconnected") } -pub fn new_rmc_gateway_connection( - conn: SplittableBufferConnection, - create_internal: F, -) -> Arc +pub fn new_rmc_gateway_connection(conn: SplittableBufferConnection, create_internal: F) -> Arc where F: FnOnce(RmcConnection) -> Arc, { @@ -335,12 +312,18 @@ where { let exposed_object = exposed_object.clone(); tokio::spawn(async move { - handle_incoming(conn, exposed_object, notify, incoming).await; + handle_incoming( + conn, + exposed_object, + notify, + incoming + ).await; }); + tokio::spawn(async move { - while sending_conn.is_alive() { - sending_conn.send([0, 0, 0, 0, 0].to_vec()).await; + while sending_conn.is_alive(){ + sending_conn.send([0,0,0,0,0].to_vec()).await; sleep(Duration::from_secs(10)).await; } }); @@ -349,20 +332,12 @@ where exposed_object } -impl RmcCallable for Arc { - fn rmc_call( - &self, - responder: &SendingBufferConnection, - protocol_id: u16, - method_id: u32, - call_id: u32, - rest: Vec, - ) -> impl Future + Send { - self.as_ref() - .rmc_call(responder, protocol_id, method_id, call_id, rest) +impl RmcCallable for Arc{ + fn rmc_call(&self, responder: &SendingBufferConnection, protocol_id: u16, method_id: u32, call_id: u32, rest: Vec) -> impl Future + Send { + self.as_ref().rmc_call(responder, protocol_id, method_id, call_id, rest) } } define_rmc_proto! { proto NoProto{} -} +} \ No newline at end of file diff --git a/rnex-core/src/rmc/protocols/nintendo_notification.rs b/rnex-core/src/rmc/protocols/nintendo_notification.rs deleted file mode 100644 index ae31467..0000000 --- a/rnex-core/src/rmc/protocols/nintendo_notification.rs +++ /dev/null @@ -1,39 +0,0 @@ -use macros::{RmcSerialize, method_id, rmc_proto}; - -use rnex_core::PID; -use rnex_core::rmc::structures::any::Any; - -#[derive(RmcSerialize)] -#[rmc_struct(0)] -pub struct NintendoNotificationEvent { - pub event_type: u32, - pub sender: PID, - pub data: Any, -} - -#[derive(RmcSerialize)] -#[rmc_struct(0)] -pub struct NintendoNotificationEventGeneral { - pub param1: u32, - pub param2: u64, - pub param3: u64, - pub str_param: String, -} - -#[derive(RmcSerialize)] -#[rmc_struct(0)] -pub struct NintendoNotificationEventProfile { - pub region: u8, - pub country: u8, - pub area: u8, - pub language: u8, - pub platform: u8, -} - -#[rmc_proto(100, NoReturn)] -pub trait NintendoNotification { - #[method_id(1)] - async fn process_nintendo_notification_event_1(&self, notif: NintendoNotificationEvent); - #[method_id(2)] - async fn process_nintendo_notification_event_2(&self, notif: NintendoNotificationEvent); -} diff --git a/rnex-core/src/rmc/protocols/notifications.rs b/rnex-core/src/rmc/protocols/notifications.rs index e66f8fe..164bf83 100644 --- a/rnex-core/src/rmc/protocols/notifications.rs +++ b/rnex-core/src/rmc/protocols/notifications.rs @@ -1,37 +1,19 @@ -use macros::{RmcSerialize, method_id, rmc_proto}; +use macros::{method_id, rmc_proto, rmc_struct, RmcSerialize}; -use rnex_core::PID; - -pub mod notification_types { +pub mod notification_types{ pub const OWNERSHIP_CHANGED: u32 = 4000; pub const HOST_CHANGED: u32 = 110000; - pub const REQUEST_JOIN_GATHERING: u32 = 101; - pub const END_GATHERING: u32 = 102; } -cfg_if::cfg_if! { - if #[cfg(feature = "third-notif-param")]{ - #[derive(RmcSerialize, Debug, Default, Clone)] - #[rmc_struct(0)] - pub struct NotificationEvent { - pub pid_source: PID, - pub notif_type: u32, - pub param_1: PID, - pub param_2: PID, - pub str_param: String, - pub param_3: PID, - } - } else { - #[derive(RmcSerialize, Debug, Default, Clone)] - #[rmc_struct(0)] - pub struct NotificationEvent { - pub pid_source: PID, - pub notif_type: u32, - pub param_1: PID, - pub param_2: PID, - pub str_param: String, - } - } +#[derive(RmcSerialize, Debug, Default, Clone)] +#[rmc_struct(0)] +pub struct NotificationEvent{ + pub pid_source: u32, + pub notif_type: u32, + pub param_1: u32, + pub param_2: u32, + pub str_param: String, + pub param_3: u32, } #[rmc_proto(14, NoReturn)] @@ -39,3 +21,4 @@ pub trait Notification { #[method_id(1)] async fn process_notification_event(&self, event: NotificationEvent); } + diff --git a/rnex-core/src/rmc/protocols/ranking.rs b/rnex-core/src/rmc/protocols/ranking.rs index 68be98f..93dcb87 100644 --- a/rnex-core/src/rmc/protocols/ranking.rs +++ b/rnex-core/src/rmc/protocols/ranking.rs @@ -1,50 +1,33 @@ -use macros::{RmcSerialize, method_id, rmc_proto}; +use macros::{rmc_struct, rmc_proto, RmcSerialize}; -use rnex_core::kerberos::KerberosDateTime; -use rnex_core::rmc::structures::qbuffer::QBuffer; -use rnex_core::rmc::structures::resultsrange::ResultsRange; -use rnex_core::rmc::response::ErrorCode; -use rnex_core::rmc::structures::ranking::UploadCompetitionData; +#[derive(RmcSerialize, Debug, Default, Clone)] +struct ResultsRange{ + offset: u32, + size: u32 +} #[derive(RmcSerialize, Debug, Default, Clone)] #[rmc_struct(1)] -pub struct CompetitionRankingGetParam { - pub unk: u32, - pub range: ResultsRange, - pub festival_ids: Vec, +struct CompetitionRankingGetParam{ + unk: u32, + range: ResultsRange, + festival_ids: Vec, } #[derive(RmcSerialize, Debug, Default, Clone)] #[rmc_struct(0)] -pub struct CompetitionRankingScoreInfo { - pub fest_id: u32, - pub score_data: Vec, - pub unk: u32, - pub team_wins: Vec, - pub team_votes: Vec, +struct CompetitionRankingScoreInfo{ + fest_id: u32, + score_data: Vec, + unk: u32, + team_wins: Vec, + team_votes: Vec } -#[derive(RmcSerialize, Debug, Clone)] -#[rmc_struct(0)] -pub struct CompetitionRankingScoreData { - pub unk: u32, - pub pid: u32, - pub score: u32, - pub modified: KerberosDateTime, - pub unk2: u8, - pub appdata: QBuffer, -} + #[rmc_proto(112)] -pub trait Ranking { - #[method_id(16)] - async fn competition_ranking_get_param( - &self, - param: CompetitionRankingGetParam, - ) -> Result, ErrorCode>; - #[method_id(18)] - async fn upload_competition_ranking_score( - &self, - param: UploadCompetitionData, - ) -> Result; -} +pub trait Ranking{ + //#[method_id(16)] + //async fn competition_ranking_get_param(&self, param: CompetitionRankingGetParam) -> Result,ErrorCode>; +} \ No newline at end of file diff --git a/rnex-core/src/rmc/protocols/secure.rs b/rnex-core/src/rmc/protocols/secure.rs index 503bf93..50afb5b 100644 --- a/rnex-core/src/rmc/protocols/secure.rs +++ b/rnex-core/src/rmc/protocols/secure.rs @@ -3,22 +3,10 @@ use rnex_core::prudp::station_url::StationUrl; use rnex_core::rmc::response::ErrorCode; use rnex_core::rmc::structures::qresult::QResult; -use crate::rmc::structures::any::Any; - #[rmc_proto(11)] pub trait Secure { #[method_id(1)] - async fn register( - &self, - station_urls: Vec, - ) -> Result<(QResult, u32, StationUrl), ErrorCode>; - - #[method_id(4)] - async fn register_ex( - &self, - station_urls: Vec, - data: Any, - ) -> Result<(QResult, u32, StationUrl), ErrorCode>; + async fn register(&self, station_urls: Vec) -> Result<(QResult, u32, StationUrl), ErrorCode>; #[method_id(7)] async fn replace_url(&self, target: StationUrl, dest: StationUrl) -> Result<(), ErrorCode>; } diff --git a/rnex-core/src/rmc/protocols/util.rs b/rnex-core/src/rmc/protocols/util.rs deleted file mode 100644 index a89c79b..0000000 --- a/rnex-core/src/rmc/protocols/util.rs +++ /dev/null @@ -1,9 +0,0 @@ -use macros::{method_id, rmc_proto}; - -use rnex_core::rmc::response::ErrorCode; - -#[rmc_proto(110)] -pub trait Utility { - #[method_id(1)] - async fn acquire_nex_unique_id(&self) -> Result; -} diff --git a/rnex-core/src/rmc/response.rs b/rnex-core/src/rmc/response.rs index d401892..c994f8b 100644 --- a/rnex-core/src/rmc/response.rs +++ b/rnex-core/src/rmc/response.rs @@ -2,18 +2,17 @@ // attributes but this gets it to not complain anymore #![allow(unused_parens)] -use crate::rmc::response::ErrorCode::Core_Exception; -use crate::rmc::structures::qresult::ERROR_MASK; -use crate::util::SendingBufferConnection; -use bytemuck::bytes_of; -use log::{error, warn}; use std::io; use std::io::{Read, Seek, Write}; use std::mem::transmute; +use bytemuck::bytes_of; +use log::error; use v_byte_helpers::EnumTryInto; -use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions}; +use v_byte_helpers::{ReadExtensions, IS_BIG_ENDIAN}; +use crate::rmc::response::ErrorCode::Core_Exception; +use crate::rmc::structures::qresult::ERROR_MASK; +use crate::util::SendingBufferConnection; -#[derive(Debug, Clone)] pub enum RMCResponseResult { Success { call_id: u32, @@ -26,14 +25,13 @@ pub enum RMCResponseResult { }, } -#[derive(Debug, Clone)] pub struct RMCResponse { pub protocol_id: u8, pub response_result: RMCResponseResult, } impl RMCResponse { - pub fn new(stream: &mut (impl Seek + Read)) -> io::Result { + pub fn new(stream: &mut (impl Seek + Read)) -> io::Result{ // ignore the size for now this will only be used for checking let size: u32 = stream.read_struct(IS_BIG_ENDIAN)?; @@ -48,7 +46,7 @@ impl RMCResponse { let is_success: u8 = stream.read_struct(IS_BIG_ENDIAN)?; - let response_result = if is_success == 0x01 { + let response_result = if is_success == 0x01{ let call_id: u32 = stream.read_struct(IS_BIG_ENDIAN)?; let method_id: u32 = stream.read_struct(IS_BIG_ENDIAN)?; let method_id = method_id & (!0x8000); @@ -57,10 +55,11 @@ impl RMCResponse { stream.read(&mut data)?; + RMCResponseResult::Success { call_id, method_id, - data, + data } } else { let error_code: u32 = stream.read_struct(IS_BIG_ENDIAN)?; @@ -69,7 +68,7 @@ impl RMCResponse { RMCResponseResult::Error { error_code: { - match ErrorCode::try_from(error_code) { + match ErrorCode::try_from(error_code){ Ok(v) => v, Err(()) => { error!("invalid error code {:#010x}", error_code); @@ -78,35 +77,36 @@ impl RMCResponse { } }, call_id, + } }; - Ok(Self { + Ok(Self{ protocol_id, - response_result, + response_result }) } - pub fn get_call_id(&self) -> u32 { - match &self.response_result { - RMCResponseResult::Success { call_id, .. } => *call_id, - RMCResponseResult::Error { call_id, .. } => *call_id, + pub fn get_call_id(&self) -> u32{ + match &self.response_result{ + RMCResponseResult::Success { call_id, ..} => *call_id, + RMCResponseResult::Error { call_id, .. } => *call_id } } pub fn to_data(self) -> Vec { - generate_response(self.protocol_id, self.response_result) - .expect("failed to generate response") + generate_response(self.protocol_id, self.response_result).expect("failed to generate response") } } pub fn generate_response(protocol_id: u8, response: RMCResponseResult) -> io::Result> { - let size = 1 - + 1 - + match &response { - RMCResponseResult::Success { data, .. } => 4 + 4 + data.len(), - RMCResponseResult::Error { .. } => 4 + 4, - }; + let size = 1 + 1 + match &response { + RMCResponseResult::Success { + data, + .. + } => 4 + 4 + data.len(), + RMCResponseResult::Error { .. } => 4 + 4, + }; let mut data_out = Vec::with_capacity(size + 4); @@ -119,7 +119,7 @@ pub fn generate_response(protocol_id: u8, response: RMCResponseResult) -> io::Re RMCResponseResult::Success { call_id, method_id, - data, + data } => { data_out.push(1); data_out.write_all(bytes_of(&call_id))?; @@ -129,7 +129,7 @@ pub fn generate_response(protocol_id: u8, response: RMCResponseResult) -> io::Re } RMCResponseResult::Error { call_id, - error_code, + error_code } => { data_out.push(0); let error_code_val: u32 = error_code.into(); @@ -151,24 +151,23 @@ pub async fn send_result( method_id: u32, call_id: u32, ) { + let response_result = match result { Ok(v) => RMCResponseResult::Success { call_id, method_id, - data: v, + data: v }, - Err(e) => { - warn!("error occurred during call: {:?}", e); + Err(e) => RMCResponseResult::Error { call_id, - error_code: e.into(), + error_code: e.into() } - } }; - let response = RMCResponse { + let response = RMCResponse{ response_result, - protocol_id, + protocol_id }; send_response(connection, response).await @@ -178,6 +177,7 @@ pub async fn send_response(connection: &SendingBufferConnection, rmcresponse: RM connection.send(rmcresponse.to_data()).await; } + //taken from kinnays error list directly #[allow(nonstandard_style)] #[repr(u32)] @@ -464,23 +464,25 @@ impl Into for ErrorCode { #[cfg(test)] mod test { - use crate::rmc::response::ErrorCode; - use hmac::digest::KeyInit; use hmac::digest::consts::U5; + use hmac::digest::KeyInit; use rc4::{Rc4, StreamCipher}; + use crate::rmc::response::ErrorCode; #[test] fn test() { let data_orig = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 69, 4, 20]; let mut data = data_orig; - let mut rc4: Rc4 = Rc4::new_from_slice("FUCKE".as_bytes().into()).expect("invalid key"); + let mut rc4: Rc4 = + Rc4::new_from_slice("FUCKE".as_bytes().into()).expect("invalid key"); rc4.apply_keystream(&mut data); assert_ne!(data_orig, data); - let mut rc4: Rc4 = Rc4::new_from_slice("FUCKE".as_bytes().into()).expect("invalid key"); + let mut rc4: Rc4 = + Rc4::new_from_slice("FUCKE".as_bytes().into()).expect("invalid key"); rc4.apply_keystream(&mut data); @@ -492,4 +494,4 @@ mod test { let val: u32 = ErrorCode::Core_Unknown.into(); assert_eq!(val, 0x00010001) } -} +} \ No newline at end of file diff --git a/rnex-core/src/rmc/structures/any.rs b/rnex-core/src/rmc/structures/any.rs index 0f531d8..b60ca8a 100644 --- a/rnex-core/src/rmc/structures/any.rs +++ b/rnex-core/src/rmc/structures/any.rs @@ -1,19 +1,22 @@ -use rnex_core::rmc::structures::{Result, RmcSerialize}; -use std::io::{Cursor, Read, Write}; +use std::io::{Read, Write}; use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions}; +use super::{Result, RmcSerialize}; -#[derive(Debug, Default, Clone)] -pub struct Any { +#[derive(Debug, Default)] +pub struct Any{ pub name: String, - pub data: Vec, + pub data: Vec } -impl RmcSerialize for Any { +impl RmcSerialize for Any{ fn serialize(&self, writer: &mut impl Write) -> Result<()> { self.name.serialize(writer)?; let u32_len = self.data.len() as u32; - (u32_len + 4).serialize(writer)?; + + u32_len.serialize(writer)?; + u32_len.serialize(writer)?; + self.data.serialize(writer)?; Ok(()) @@ -23,23 +26,17 @@ impl RmcSerialize for Any { // also length ? let _len2: u32 = reader.read_struct(IS_BIG_ENDIAN)?; - let data = Vec::deserialize(reader)?; + let length: u32 = reader.read_struct(IS_BIG_ENDIAN)?; - Ok(Any { name, data }) - } -} + let mut data = vec![0; length as usize]; -impl Any { - pub fn try_get(&self) -> Option> { - if self.name != T::name() { - return None; - } - return Some(T::deserialize(&mut Cursor::new(&self.data[..]))); + reader.read_exact(&mut data)?; + + Ok( + Any{ + name, + data + } + ) } - pub fn new(val: &T) -> Result { - return Ok(Self { - name: T::name().to_owned(), - data: val.to_data()?, - }); - } -} +} \ No newline at end of file diff --git a/rnex-core/src/rmc/structures/buffer.rs b/rnex-core/src/rmc/structures/buffer.rs index c147133..085f053 100644 --- a/rnex-core/src/rmc/structures/buffer.rs +++ b/rnex-core/src/rmc/structures/buffer.rs @@ -1,9 +1,10 @@ -use crate::rmc::structures::Result; -use crate::rmc::structures::RmcSerialize; use std::io::{Read, Write}; +use crate::rmc::structures::RmcSerialize; -impl<'a> RmcSerialize for &'a [u8] { - fn serialize(&self, writer: &mut impl Write) -> Result<()> { + + +impl<'a> RmcSerialize for &'a [u8]{ + fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { let u32_size = self.len() as u32; writer.write(bytemuck::bytes_of(&u32_size))?; writer.write(self)?; @@ -12,25 +13,25 @@ impl<'a> RmcSerialize for &'a [u8] { } /// DO NOT USE (also maybe split off the serialize and deserialize functions at some point) - fn deserialize(_reader: &mut impl Read) -> Result { + fn deserialize(_reader: &mut impl Read) -> crate::rmc::structures::Result { panic!("cannot deserialize to a u8 slice reference (use this ONLY for writing)") } - fn serialize_write_size(&self) -> Result { + fn serialize_write_size(&self) -> crate::rmc::structures::Result { Ok(4 + self.len() as u32) } } -impl RmcSerialize for Box<[u8]> { - fn serialize(&self, writer: &mut impl Write) -> Result<()> { +impl RmcSerialize for Box<[u8]>{ + fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { (&self[..]).serialize(writer) } - fn deserialize(reader: &mut impl Read) -> Result { + fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result { Vec::deserialize(reader).map(|v| v.into_boxed_slice()) } - fn serialize_write_size(&self) -> Result { + fn serialize_write_size(&self) -> crate::rmc::structures::Result { (&self[..]).serialize_write_size() } -} +} \ No newline at end of file diff --git a/rnex-core/src/rmc/structures/connection_data.rs b/rnex-core/src/rmc/structures/connection_data.rs index d134e85..da6a17b 100644 --- a/rnex-core/src/rmc/structures/connection_data.rs +++ b/rnex-core/src/rmc/structures/connection_data.rs @@ -1,19 +1,13 @@ + use macros::RmcSerialize; use rnex_core::kerberos::KerberosDateTime; #[derive(Debug, RmcSerialize)] #[rmc_struct(1)] -pub struct ConnectionData { +pub struct ConnectionData{ pub station_url: String, pub special_protocols: Vec, pub special_station_url: String, - pub date_time: KerberosDateTime, + pub date_time: KerberosDateTime } -#[derive(Debug, RmcSerialize)] -#[rmc_struct(1)] -pub struct ConnectionDataOld { - pub station_url: String, - pub special_protocols: Vec, - pub special_station_url: String, -} diff --git a/rnex-core/src/rmc/structures/data.rs b/rnex-core/src/rmc/structures/data.rs deleted file mode 100644 index c6064ae..0000000 --- a/rnex-core/src/rmc/structures/data.rs +++ /dev/null @@ -1,5 +0,0 @@ -use macros::RmcSerialize; - -#[derive(RmcSerialize, Debug, Clone, Copy)] -#[rmc_struct(0)] -pub struct Data {} diff --git a/rnex-core/src/rmc/structures/list.rs b/rnex-core/src/rmc/structures/list.rs index 7c7db8e..890be9a 100644 --- a/rnex-core/src/rmc/structures/list.rs +++ b/rnex-core/src/rmc/structures/list.rs @@ -1,17 +1,19 @@ -use crate::rmc::structures::RmcSerialize; -use bytemuck::bytes_of; use std::io::{Read, Write}; use std::mem::MaybeUninit; +use bytemuck::bytes_of; use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions}; +use crate::rmc::structures::RmcSerialize; -// this is also for implementing `Buffer` this is tecnically not the same as its handled internaly + + +// this is also for implementing `Buffer` this is tecnically not the same as its handled internaly // probably but as it has the same mapping it doesn't matter and simplifies things -impl RmcSerialize for Vec { +impl RmcSerialize for Vec{ fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { let u32_len = self.len() as u32; writer.write_all(bytes_of(&u32_len))?; - for e in self { + for e in self{ e.serialize(writer)?; } @@ -19,31 +21,27 @@ impl RmcSerialize for Vec { } fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result { - println!("reading list"); let len: u32 = reader.read_struct(IS_BIG_ENDIAN)?; - println!("readijg list: {:?}", len); //let mut vec = Vec::with_capacity(len as usize); - let vec: Vec = (0..len) - .map(|_| T::deserialize(reader)) - .collect::, _>>()?; + let vec = (0..len).map(|_| T::deserialize(reader)).collect::, _>>()?; Ok(vec) } - + fn serialize_write_size(&self) -> crate::rmc::structures::Result { let mut val = 0u32; - for i in self { + for i in self{ val += i.serialize_write_size()?; } Ok(4 + val) } } -impl RmcSerialize for [T; LEN] { +impl RmcSerialize for [T; LEN]{ fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { - for i in 0..LEN { + for i in 0..LEN{ self[i].serialize(writer)?; } @@ -53,20 +51,20 @@ impl RmcSerialize for [T; LEN] { fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result { let mut arr = [const { MaybeUninit::::uninit() }; LEN]; - for i in 0..LEN { + for i in 0..LEN{ arr[i] = MaybeUninit::new(T::deserialize(reader)?); } // all of the elements are now initialized so it is safe to assume they are initialized - let arr = arr.map(|v| unsafe { v.assume_init() }); + let arr = arr.map(|v| unsafe{ v.assume_init() }); Ok(arr) } #[inline(always)] fn serialize_write_size(&self) -> crate::rmc::structures::Result { let mut val = 0u32; - for i in self { + for i in self{ val += i.serialize_write_size()?; } Ok(val) diff --git a/rnex-core/src/rmc/structures/matchmake.rs b/rnex-core/src/rmc/structures/matchmake.rs index 88deea0..9194b97 100644 --- a/rnex-core/src/rmc/structures/matchmake.rs +++ b/rnex-core/src/rmc/structures/matchmake.rs @@ -1,19 +1,14 @@ -use cfg_if::cfg_if; -use macros::RmcSerialize; use rnex_core::kerberos::KerberosDateTime; use rnex_core::rmc::structures::variant::Variant; - -use rnex_core::PID; - -use crate::rmc::structures::string_set::StringSet; +use macros::RmcSerialize; // rmc structure -#[derive(RmcSerialize, Debug, Clone, Default, PartialEq)] +#[derive(RmcSerialize, Debug, Clone, Default)] #[rmc_struct(0)] pub struct Gathering { pub self_gid: u32, - pub owner_pid: PID, - pub host_pid: PID, + pub owner_pid: u32, + pub host_pid: u32, pub minimum_participants: u16, pub maximum_participants: u16, pub participant_policy: u32, @@ -24,60 +19,41 @@ pub struct Gathering { } // rmc structure -#[derive(RmcSerialize, Debug, Clone, Default, PartialEq)] +#[derive(RmcSerialize, Debug, Clone, Default)] #[rmc_struct(0)] pub struct MatchmakeParam { pub params: Vec<(String, Variant)>, } -cfg_if! { - if #[cfg(feature = "v3-5-0")]{ - #[derive(RmcSerialize, Debug, Clone, Default, PartialEq)] - #[rmc_struct(3)] - pub struct MatchmakeSession { - //inherits from - #[extends] - pub gathering: Gathering, +// rmc structure +#[derive(RmcSerialize, Debug, Clone, Default)] +#[rmc_struct(3)] +pub struct MatchmakeSession { + //inherits from + #[extends] + pub gathering: Gathering, - pub gamemode: u32, - pub attributes: Vec, - pub open_participation: bool, - pub matchmake_system_type: u32, - pub application_buffer: Vec, - pub participation_count: u32, - pub progress_score: u8, - pub session_key: Vec, - pub option0: u32, - pub matchmake_param: MatchmakeParam, - pub datetime: KerberosDateTime, - pub user_password: String, - pub refer_gid: u32, - pub user_password_enabled: bool, - pub system_password_enabled: bool, - } - } else { - #[derive(RmcSerialize, Debug, Clone, Default, PartialEq)] - #[rmc_struct(0)] - pub struct MatchmakeSession { - //inherits from - #[extends] - pub gathering: Gathering, - - pub gamemode: u32, - pub attributes: Vec, - pub open_participation: bool, - pub matchmake_system_type: u32, - pub application_buffer: Vec, - pub participation_count: u32, - pub session_key: Vec, - } - } + pub gamemode: u32, + pub attributes: Vec, + pub open_participation: bool, + pub matchmake_system_type: u32, + pub application_buffer: Vec, + pub participation_count: u32, + pub progress_score: u8, + pub session_key: Vec, + pub option0: u32, + pub matchmake_param: MatchmakeParam, + pub datetime: KerberosDateTime, + pub user_password: String, + pub refer_gid: u32, + pub user_password_enabled: bool, + pub system_password_enabled: bool, } #[derive(RmcSerialize, Debug, Clone)] #[rmc_struct(3)] pub struct MatchmakeSessionSearchCriteria { - pub attribs: Vec>, + pub attribs: Vec, pub game_mode: String, pub minimum_participants: String, pub maximum_participants: String, @@ -97,7 +73,7 @@ pub struct MatchmakeSessionSearchCriteria { #[rmc_struct(0)] pub struct AutoMatchmakeParam { pub matchmake_session: MatchmakeSession, - pub additional_participants: Vec, + pub additional_participants: Vec, pub gid_for_participation_check: u32, pub auto_matchmake_option: u32, pub join_message: String, @@ -110,7 +86,7 @@ pub struct AutoMatchmakeParam { #[rmc_struct(0)] pub struct CreateMatchmakeSessionParam { pub matchmake_session: MatchmakeSession, - pub additional_participants: Vec, + pub additional_participants: Vec, pub gid_for_participation_check: u32, pub create_matchmake_session_option: u32, pub join_message: String, @@ -123,40 +99,20 @@ pub struct MatchmakeBlockListParam { option_flag: u32, } -cfg_if! { - if #[cfg(feature = "v3-10-22")] { - #[derive(RmcSerialize, Debug, Clone)] - #[rmc_struct(1)] - pub struct JoinMatchmakeSessionParam { - pub gid: u32, - pub additional_participants: Vec, - pub gid_for_participation_check: u32, - pub join_matchmake_session_open: u32, - pub join_matchmake_session_behavior: u8, - pub user_password: String, - pub system_password: String, - pub join_message: String, - pub participation_count: u16, - pub extra_participant: u16, - //pub block_list_param: MatchmakeBlockListParam - } - } else { - #[derive(RmcSerialize, Debug, Clone)] - #[rmc_struct(0)] - pub struct JoinMatchmakeSessionParam { - pub gid: u32, - pub additional_participants: Vec, - pub gid_for_participation_check: u32, - pub join_matchmake_session_open: u32, - pub join_matchmake_session_behavior: u8, - pub user_password: String, - pub system_password: String, - pub join_message: String, - pub participation_count: u16, - //pub extra_participant: u16, - //pub block_list_param: MatchmakeBlockListParam - } - } +#[derive(RmcSerialize, Debug, Clone)] +#[rmc_struct(0)] +pub struct JoinMatchmakeSessionParam { + pub gid: u32, + pub additional_participants: Vec, + pub gid_for_participation_check: u32, + pub join_matchmake_session_open: u32, + pub join_matchmake_session_behavior: u8, + pub user_password: String, + pub system_password: String, + pub join_message: String, + pub participation_count: u16, + //pub extra_participant: u16, + //pub block_list_param: MatchmakeBlockListParam } pub mod gathering_flags { diff --git a/rnex-core/src/rmc/structures/mod.rs b/rnex-core/src/rmc/structures/mod.rs index 63ae484..7a1610c 100644 --- a/rnex-core/src/rmc/structures/mod.rs +++ b/rnex-core/src/rmc/structures/mod.rs @@ -1,81 +1,68 @@ -use crate::rmc::structures::helpers::DummyWriter; +use std::{fmt, io}; use std::io::{Read, Write}; use std::string::FromUtf8Error; -use std::{fmt, io}; use thiserror::Error; +use crate::rmc::structures::helpers::DummyWriter; //ideas for the future: make a proc macro library which allows generation of struct reads #[derive(Error, Debug)] -pub enum Error { +pub enum Error{ #[error("Io Error: {0}")] Io(#[from] io::Error), #[error("UTF8 conversion Error: {0}")] Utf8(#[from] FromUtf8Error), #[error("unexpected value: {0}")] UnexpectedValue(u64), - #[cfg(feature = "rmc_struct_header")] #[error("version mismatch: {0}")] VersionMismatch(u8), #[error("an error occurred reading the station url")] StationUrlInvalid, #[error("error formatting text: {0}")] - FormatError(#[from] fmt::Error), - #[error("uncategorized rmc error occurred: {0}")] - Other(Box), + FormatError(#[from] fmt::Error) } pub type Result = std::result::Result; +pub mod string; pub mod any; +pub mod qresult; pub mod buffer; pub mod connection_data; -pub mod data; -pub mod helpers; -pub mod list; -pub mod matchmake; -pub mod networking; -pub mod primitives; -pub mod qbuffer; -pub mod qresult; -pub mod ranking; -pub mod resultsrange; pub mod rmc_struct; -pub mod string; -pub mod string_set; +pub mod list; +pub mod qbuffer; +pub mod primitives; +pub mod matchmake; pub mod variant; +pub mod ranking; +pub mod networking; +pub mod helpers; -pub trait RmcSerialize { +pub trait RmcSerialize{ fn serialize(&self, writer: &mut impl Write) -> Result<()>; - fn serialize_write_size(&self) -> Result { + fn serialize_write_size(&self) -> Result{ let mut dummy = DummyWriter::new(); self.serialize(&mut dummy)?; Ok(dummy.get_total_len()) } - fn deserialize(reader: &mut impl Read) -> Result - where - Self: Sized; + fn deserialize(reader: &mut impl Read) -> Result where Self: Sized; - fn to_data(&self) -> Result> { - let expected_size = self.serialize_write_size()?; - let mut data = Vec::with_capacity(expected_size as usize); + fn to_data(&self) -> Result>{ + let mut data = Vec::with_capacity( + self.serialize_write_size()? as usize + ); self.serialize(&mut data)?; - debug_assert_eq!(expected_size, data.len() as u32); + debug_assert_eq!(self.serialize_write_size().unwrap(), data.len() as u32); Ok(data) } - fn name() -> &'static str { - "NoNameSpecified" - } - fn version() -> Option { - None - } } -impl RmcSerialize for () { +impl RmcSerialize for (){ fn serialize(&self, _writer: &mut impl Write) -> Result<()> { Ok(()) } @@ -85,4 +72,6 @@ impl RmcSerialize for () { fn serialize_write_size(&self) -> Result { Ok(0) } -} + + +} \ No newline at end of file diff --git a/rnex-core/src/rmc/structures/networking.rs b/rnex-core/src/rmc/structures/networking.rs index bc95b9e..03627af 100644 --- a/rnex-core/src/rmc/structures/networking.rs +++ b/rnex-core/src/rmc/structures/networking.rs @@ -1,37 +1,9 @@ -use crate::rmc::structures::{Error, Result, RmcSerialize}; -use rnex_core::prudp::virtual_port::VirtualPort; use std::io::{Read, Write}; -use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; -use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions}; +use std::net::{Ipv4Addr, SocketAddrV4}; +use rnex_core::prudp::virtual_port::VirtualPort; +use crate::rmc::structures::RmcSerialize; -impl RmcSerialize for SocketAddr { - fn deserialize(reader: &mut impl std::io::Read) -> Result - where - Self: Sized, - { - let val: u8 = reader.read_struct(IS_BIG_ENDIAN)?; - match val { - 4 => Ok(SocketAddr::V4(SocketAddrV4::deserialize(reader)?)), - 6 => Ok(SocketAddr::V6(SocketAddrV6::deserialize(reader)?)), - v => Err(Error::UnexpectedValue(v as u64)), - } - } - fn serialize(&self, writer: &mut impl Write) -> Result<()> { - match self { - SocketAddr::V4(v) => { - writer.write_all(&[4])?; - v.serialize(writer)?; - } - SocketAddr::V6(v) => { - writer.write_all(&[6])?; - v.serialize(writer)?; - } - } - Ok(()) - } -} - -impl RmcSerialize for SocketAddrV4 { +impl RmcSerialize for SocketAddrV4{ fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { self.ip().to_bits().serialize(writer)?; self.port().serialize(writer)?; @@ -49,35 +21,9 @@ impl RmcSerialize for SocketAddrV4 { Ok(6) } } -impl RmcSerialize for SocketAddrV6 { - fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { - self.ip().to_bits().serialize(writer)?; - self.port().serialize(writer)?; - self.flowinfo().serialize(writer)?; - self.scope_id().serialize(writer)?; - Ok(()) - } - fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result { - let ip = u128::deserialize(reader)?; - let port = u16::deserialize(reader)?; - let flowinfo = u32::deserialize(reader)?; - let scope_id = u32::deserialize(reader)?; - - Ok(SocketAddrV6::new( - Ipv6Addr::from_bits(ip), - port, - flowinfo, - scope_id, - )) - } - fn serialize_write_size(&self) -> crate::rmc::structures::Result { - Ok(6) - } -} - -impl RmcSerialize for VirtualPort { +impl RmcSerialize for VirtualPort{ fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { self.0.serialize(writer)?; @@ -90,4 +36,4 @@ impl RmcSerialize for VirtualPort { fn serialize_write_size(&self) -> crate::rmc::structures::Result { Ok(1) } -} +} \ No newline at end of file diff --git a/rnex-core/src/rmc/structures/primitives.rs b/rnex-core/src/rmc/structures/primitives.rs index 6ce1c2f..8918968 100644 --- a/rnex-core/src/rmc/structures/primitives.rs +++ b/rnex-core/src/rmc/structures/primitives.rs @@ -1,9 +1,9 @@ -use crate::rmc::structures::RmcSerialize; -use bytemuck::{bytes_of, bytes_of_mut}; use std::io::{Read, Write}; +use bytemuck::bytes_of; use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions}; +use crate::rmc::structures::RmcSerialize; -impl RmcSerialize for u8 { +impl RmcSerialize for u8{ #[inline(always)] fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { Ok(writer.write_all(bytes_of(self))?) @@ -19,7 +19,7 @@ impl RmcSerialize for u8 { } } -impl RmcSerialize for i8 { +impl RmcSerialize for i8{ #[inline(always)] fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { Ok(writer.write_all(bytes_of(self))?) @@ -35,7 +35,7 @@ impl RmcSerialize for i8 { } } -impl RmcSerialize for u16 { +impl RmcSerialize for u16{ #[inline(always)] fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { Ok(writer.write_all(bytes_of(self))?) @@ -50,7 +50,7 @@ impl RmcSerialize for u16 { } } -impl RmcSerialize for i16 { +impl RmcSerialize for i16{ #[inline(always)] fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { Ok(writer.write_all(bytes_of(self))?) @@ -65,7 +65,7 @@ impl RmcSerialize for i16 { } } -impl RmcSerialize for u32 { +impl RmcSerialize for u32{ #[inline(always)] fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { Ok(writer.write_all(bytes_of(self))?) @@ -80,7 +80,7 @@ impl RmcSerialize for u32 { } } -impl RmcSerialize for i32 { +impl RmcSerialize for i32{ #[inline(always)] fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { Ok(writer.write_all(bytes_of(self))?) @@ -95,7 +95,7 @@ impl RmcSerialize for i32 { } } -impl RmcSerialize for u64 { +impl RmcSerialize for u64{ #[inline(always)] fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { Ok(writer.write_all(bytes_of(self))?) @@ -110,24 +110,7 @@ impl RmcSerialize for u64 { } } -impl RmcSerialize for u128 { - #[inline(always)] - fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { - Ok(writer.write_all(bytes_of(self))?) - } - #[inline(always)] - fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result { - let mut data = 0u128; - reader.read_exact(&mut bytes_of_mut(&mut data))?; - Ok(data) - } - #[inline(always)] - fn serialize_write_size(&self) -> crate::rmc::structures::Result { - Ok(8) - } -} - -impl RmcSerialize for i64 { +impl RmcSerialize for i64{ #[inline(always)] fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { Ok(writer.write_all(bytes_of(self))?) @@ -142,7 +125,7 @@ impl RmcSerialize for i64 { } } -impl RmcSerialize for f64 { +impl RmcSerialize for f64{ #[inline(always)] fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { Ok(writer.write_all(bytes_of(self))?) @@ -158,10 +141,10 @@ impl RmcSerialize for f64 { } } -impl RmcSerialize for bool { +impl RmcSerialize for bool{ #[inline(always)] fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { - match self { + match self{ true => writer.write_all(&[1])?, false => writer.write_all(&[0])?, } @@ -178,7 +161,8 @@ impl RmcSerialize for bool { } } -impl RmcSerialize for (T, U) { + +impl RmcSerialize for (T, U){ #[inline(always)] fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { self.0.serialize(writer)?; @@ -194,11 +178,14 @@ impl RmcSerialize for (T, U) { } #[inline(always)] fn serialize_write_size(&self) -> crate::rmc::structures::Result { - Ok(self.0.serialize_write_size()? + self.1.serialize_write_size()?) + Ok( + self.0.serialize_write_size()? + + self.1.serialize_write_size()? + ) } } -impl RmcSerialize for (T, U, V) { +impl RmcSerialize for (T, U, V){ #[inline(always)] fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { self.0.serialize(writer)?; @@ -216,15 +203,15 @@ impl RmcSerialize for (T, U, } #[inline(always)] fn serialize_write_size(&self) -> crate::rmc::structures::Result { - Ok(self.0.serialize_write_size()? - + self.1.serialize_write_size()? - + self.2.serialize_write_size()?) + Ok( + self.0.serialize_write_size()? + + self.1.serialize_write_size()? + + self.2.serialize_write_size()? + ) } } -impl RmcSerialize - for (T, U, V, W) -{ +impl RmcSerialize for (T, U, V, W){ #[inline(always)] fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { self.0.serialize(writer)?; @@ -244,16 +231,16 @@ impl RmcSeri } #[inline(always)] fn serialize_write_size(&self) -> crate::rmc::structures::Result { - Ok(self.0.serialize_write_size()? - + self.1.serialize_write_size()? - + self.2.serialize_write_size()? - + self.3.serialize_write_size()?) + Ok( + self.0.serialize_write_size()? + + self.1.serialize_write_size()? + + self.2.serialize_write_size()? + + self.3.serialize_write_size()? + ) } } -impl - RmcSerialize for (T, U, V, W, X) -{ +impl RmcSerialize for (T, U, V, W, X){ #[inline(always)] fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { self.0.serialize(writer)?; @@ -277,23 +264,17 @@ impl crate::rmc::structures::Result { - Ok(self.0.serialize_write_size()? - + self.1.serialize_write_size()? - + self.2.serialize_write_size()? - + self.3.serialize_write_size()? - + self.4.serialize_write_size()?) + Ok( + self.0.serialize_write_size()? + + self.1.serialize_write_size()? + + self.2.serialize_write_size()? + + self.2.serialize_write_size()? + + self.3.serialize_write_size()? + ) } } -impl< - T: RmcSerialize, - U: RmcSerialize, - V: RmcSerialize, - W: RmcSerialize, - X: RmcSerialize, - Y: RmcSerialize, -> RmcSerialize for (T, U, V, W, X, Y) -{ +impl RmcSerialize for (T, U, V, W, X, Y){ #[inline(always)] fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { self.0.serialize(writer)?; @@ -319,25 +300,18 @@ impl< } #[inline(always)] fn serialize_write_size(&self) -> crate::rmc::structures::Result { - Ok(self.0.serialize_write_size()? - + self.1.serialize_write_size()? - + self.2.serialize_write_size()? - + self.3.serialize_write_size()? - + self.4.serialize_write_size()? - + self.5.serialize_write_size()?) + Ok( + self.0.serialize_write_size()? + + self.1.serialize_write_size()? + + self.2.serialize_write_size()? + + self.3.serialize_write_size()? + + self.4.serialize_write_size()? + + self.5.serialize_write_size()? + ) } } -impl< - T: RmcSerialize, - U: RmcSerialize, - V: RmcSerialize, - W: RmcSerialize, - X: RmcSerialize, - Y: RmcSerialize, - Z: RmcSerialize, -> RmcSerialize for (T, U, V, W, X, Y, Z) -{ +impl RmcSerialize for (T, U, V, W, X, Y, Z){ #[inline(always)] fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { self.0.serialize(writer)?; @@ -364,123 +338,19 @@ impl< } #[inline(always)] fn serialize_write_size(&self) -> crate::rmc::structures::Result { - Ok(self.0.serialize_write_size()? - + self.1.serialize_write_size()? - + self.2.serialize_write_size()? - + self.3.serialize_write_size()? - + self.4.serialize_write_size()? - + self.5.serialize_write_size()? - + self.6.serialize_write_size()?) + Ok( + self.0.serialize_write_size()? + + self.1.serialize_write_size()? + + self.2.serialize_write_size()? + + self.3.serialize_write_size()? + + self.4.serialize_write_size()? + + self.5.serialize_write_size()? + + self.6.serialize_write_size()? + ) } } -impl< - T: RmcSerialize, - U: RmcSerialize, - V: RmcSerialize, - W: RmcSerialize, - X: RmcSerialize, - Y: RmcSerialize, - Z: RmcSerialize, - A: RmcSerialize, -> RmcSerialize for (T, U, V, W, X, Y, Z, A) -{ - #[inline(always)] - fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { - self.0.serialize(writer)?; - self.1.serialize(writer)?; - self.2.serialize(writer)?; - self.3.serialize(writer)?; - self.4.serialize(writer)?; - self.5.serialize(writer)?; - self.6.serialize(writer)?; - self.7.serialize(writer)?; - - Ok(()) - } - #[inline(always)] - fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result { - let first = T::deserialize(reader)?; - let second = U::deserialize(reader)?; - let third = V::deserialize(reader)?; - let fourth = W::deserialize(reader)?; - let fifth = X::deserialize(reader)?; - let sixth = Y::deserialize(reader)?; - let seventh = Z::deserialize(reader)?; - let eighth = A::deserialize(reader)?; - - Ok((first, second, third, fourth, fifth, sixth, seventh, eighth)) - } - #[inline(always)] - fn serialize_write_size(&self) -> crate::rmc::structures::Result { - Ok(self.0.serialize_write_size()? - + self.1.serialize_write_size()? - + self.2.serialize_write_size()? - + self.3.serialize_write_size()? - + self.4.serialize_write_size()? - + self.5.serialize_write_size()? - + self.6.serialize_write_size()? - + self.7.serialize_write_size()?) - } -} - -impl< - T: RmcSerialize, - U: RmcSerialize, - V: RmcSerialize, - W: RmcSerialize, - X: RmcSerialize, - Y: RmcSerialize, - Z: RmcSerialize, - A: RmcSerialize, - B: RmcSerialize, -> RmcSerialize for (T, U, V, W, X, Y, Z, A, B) -{ - #[inline(always)] - fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { - self.0.serialize(writer)?; - self.1.serialize(writer)?; - self.2.serialize(writer)?; - self.3.serialize(writer)?; - self.4.serialize(writer)?; - self.5.serialize(writer)?; - self.6.serialize(writer)?; - self.7.serialize(writer)?; - self.8.serialize(writer)?; - - Ok(()) - } - #[inline(always)] - fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result { - let first = T::deserialize(reader)?; - let second = U::deserialize(reader)?; - let third = V::deserialize(reader)?; - let fourth = W::deserialize(reader)?; - let fifth = X::deserialize(reader)?; - let sixth = Y::deserialize(reader)?; - let seventh = Z::deserialize(reader)?; - let eighth = A::deserialize(reader)?; - let nineth = B::deserialize(reader)?; - - Ok(( - first, second, third, fourth, fifth, sixth, seventh, eighth, nineth, - )) - } - #[inline(always)] - fn serialize_write_size(&self) -> crate::rmc::structures::Result { - Ok(self.0.serialize_write_size()? - + self.1.serialize_write_size()? - + self.2.serialize_write_size()? - + self.3.serialize_write_size()? - + self.4.serialize_write_size()? - + self.5.serialize_write_size()? - + self.6.serialize_write_size()? - + self.7.serialize_write_size()? - + self.8.serialize_write_size()?) - } -} - -impl RmcSerialize for Box { +impl RmcSerialize for Box{ #[inline(always)] fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { self.as_ref().serialize(writer) @@ -493,4 +363,4 @@ impl RmcSerialize for Box { fn serialize_write_size(&self) -> crate::rmc::structures::Result { T::serialize_write_size(self.as_ref()) } -} +} \ No newline at end of file diff --git a/rnex-core/src/rmc/structures/qbuffer.rs b/rnex-core/src/rmc/structures/qbuffer.rs index 7f2aa7b..fb30e64 100644 --- a/rnex-core/src/rmc/structures/qbuffer.rs +++ b/rnex-core/src/rmc/structures/qbuffer.rs @@ -3,7 +3,8 @@ use bytemuck::bytes_of; use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions}; use crate::rmc::structures::{Result, RmcSerialize}; -#[derive(Clone, Debug, Default)] + +#[derive(Debug)] pub struct QBuffer(pub Vec); impl RmcSerialize for QBuffer{ diff --git a/rnex-core/src/rmc/structures/qresult.rs b/rnex-core/src/rmc/structures/qresult.rs index 13b79d7..312540a 100644 --- a/rnex-core/src/rmc/structures/qresult.rs +++ b/rnex-core/src/rmc/structures/qresult.rs @@ -1,42 +1,37 @@ -use crate::rmc::response::ErrorCode; -use crate::rmc::structures::{Result, RmcSerialize}; -use bytemuck::{Pod, Zeroable, bytes_of}; use std::io::{Read, Write}; +use bytemuck::{bytes_of, Pod, Zeroable}; use v_byte_helpers::SwapEndian; use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions}; +use crate::rmc::response::ErrorCode; +use crate::rmc::structures::{RmcSerialize, Result}; -pub const ERROR_MASK: u32 = 1 << 31; +pub const ERROR_MASK: u32 = 1 << 31; #[derive(Pod, Zeroable, Copy, Clone, SwapEndian, Debug)] #[repr(transparent)] pub struct QResult(u32); -impl QResult { - pub fn success(error_code: ErrorCode) -> Self { +impl QResult{ + pub fn success(error_code: ErrorCode) -> Self{ let val: u32 = error_code.into(); Self(val & (!ERROR_MASK)) } - pub fn error(error_code: ErrorCode) -> Self { + pub fn error(error_code: ErrorCode) -> Self{ let val: u32 = error_code.into(); Self(val | ERROR_MASK) } } -impl RmcSerialize for QResult { +impl RmcSerialize for QResult{ fn serialize(&self, writer: &mut impl Write) -> Result<()> { writer.write(bytes_of(self))?; Ok(()) } fn deserialize(reader: &mut impl Read) -> Result { - let result: Self = reader.read_struct(IS_BIG_ENDIAN)?; - println!("reading qresult: {:x}", result.0); - Ok(result) + Ok(reader.read_struct(IS_BIG_ENDIAN)?) } - fn serialize_write_size(&self) -> Result { - Ok(4) - } -} +} \ No newline at end of file diff --git a/rnex-core/src/rmc/structures/ranking.rs b/rnex-core/src/rmc/structures/ranking.rs index 773889d..9602553 100644 --- a/rnex-core/src/rmc/structures/ranking.rs +++ b/rnex-core/src/rmc/structures/ranking.rs @@ -4,19 +4,65 @@ use rnex_core::rmc::structures::qbuffer::QBuffer; #[derive(RmcSerialize, Debug)] #[rmc_struct(0)] -pub struct UploadCompetitionData{ - pub unk_1/*?*/: u32, - pub splatfest_id: u32, - pub unk_2/*?*/: u32, - pub score: u32, - pub team_id: u8, - pub team_win: u8, - pub is_first_upload: bool, - pub appdata: QBuffer, +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 { +struct UserData{ name: [u16; 0x10], } + +#[cfg(test)] +mod test{ + use std::io::Cursor; + use bytemuck::from_bytes; + use crate::rmc::structures::ranking::{UploadCompetitionData, UserData}; + use rnex_core::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/rnex-core/src/rmc/structures/resultsrange.rs b/rnex-core/src/rmc/structures/resultsrange.rs deleted file mode 100644 index ba62e49..0000000 --- a/rnex-core/src/rmc/structures/resultsrange.rs +++ /dev/null @@ -1,8 +0,0 @@ -use macros::RmcSerialize; - -#[derive(RmcSerialize, Debug, Default, Clone)] -#[rmc_struct(0)] -pub struct ResultsRange{ - pub offset: u32, - pub size: u32 -} \ No newline at end of file diff --git a/rnex-core/src/rmc/structures/rmc_struct.rs b/rnex-core/src/rmc/structures/rmc_struct.rs index 7660f96..52184bb 100644 --- a/rnex-core/src/rmc/structures/rmc_struct.rs +++ b/rnex-core/src/rmc/structures/rmc_struct.rs @@ -1,13 +1,15 @@ -use crate::rmc::structures::Result; + use std::cmp::max; use std::fmt::Arguments; use std::io; use std::io::{ErrorKind, IoSlice, Read, Write}; +use crate::rmc::structures::Result; + #[repr(C, packed)] -struct StructureHeader { +struct StructureHeader{ version: u8, - length: u32, + length: u32 } #[cfg(feature = "rmc_struct_header")] @@ -36,12 +38,7 @@ impl Write for OnlyWriteVec<'_> { } #[cfg(feature = "rmc_struct_header")] -pub fn write_struct( - writer: &mut T, - version: u8, - inner_size: u32, - pred: impl FnOnce(&mut T) -> Result<()>, -) -> Result<()> { +pub fn write_struct(writer: &mut T, version: u8, inner_size: u32, pred: impl FnOnce(&mut T) -> Result<()> ) -> Result<()> { use bytemuck::bytes_of; writer.write_all(&[version])?; @@ -53,31 +50,29 @@ pub fn write_struct( Ok(()) } + + #[cfg(not(feature = "rmc_struct_header"))] -pub fn write_struct( - writer: &mut T, - _version: u8, - _inner_size: u32, - pred: impl FnOnce(&mut T) -> Result<()>, -) -> Result<()> { +pub fn write_struct(writer: &mut T, _version: u8, _inner_size: u32, pred: impl FnOnce(&mut T) -> Result<()> ) -> Result<()> { pred(writer) } -pub struct SubRead<'a, T: Read> { + +pub struct SubRead<'a, T: Read>{ left_to_read: usize, - origin: &'a mut T, + origin: &'a mut T } -impl<'a, T: Read> SubRead<'a, T> { - pub const fn new(origin: &'a mut T, left_to_read: usize) -> Self { - Self { +impl<'a, T: Read> SubRead<'a, T>{ + pub const fn new(origin: &'a mut T, left_to_read: usize) -> Self{ + Self{ left_to_read, - origin, + origin } } } -impl Read for SubRead<'_, T> { +impl Read for SubRead<'_, T>{ #[inline(always)] fn read(&mut self, buf: &mut [u8]) -> io::Result { let max_read = max(self.left_to_read, buf.len()); @@ -88,11 +83,8 @@ impl Read for SubRead<'_, T> { #[inline(always)] fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { - if buf.len() > self.left_to_read { - return Err(io::Error::new( - ErrorKind::UnexpectedEof, - "Would run over end of SubRead", - )); + if buf.len() > self.left_to_read{ + return Err(io::Error::new(ErrorKind::UnexpectedEof, "Would run over end of SubRead")); } self.left_to_read -= buf.len(); self.origin.read_exact(buf) @@ -100,14 +92,10 @@ impl Read for SubRead<'_, T> { } #[cfg(feature = "rmc_struct_header")] -pub fn read_struct( - reader: &mut R, - version: u8, - pred: impl FnOnce(&mut SubRead) -> Result, -) -> Result { +pub fn read_struct(reader: &mut R, version: u8, pred: impl FnOnce(&mut SubRead) -> Result) -> Result { use crate::rmc::structures::Error::VersionMismatch; - use v_byte_helpers::IS_BIG_ENDIAN; use v_byte_helpers::ReadExtensions; + use v_byte_helpers::IS_BIG_ENDIAN; let ver: u8 = reader.read_struct(IS_BIG_ENDIAN)?; if ver != version { @@ -120,10 +108,6 @@ pub fn read_struct( } #[cfg(not(feature = "rmc_struct_header"))] -pub fn read_struct( - mut reader: &mut R, - _version: u8, - pred: impl FnOnce(&mut R) -> Result, -) -> Result { +pub fn read_struct(mut reader: &mut R, _version: u8, pred: impl FnOnce(&mut R) -> Result) -> Result { Ok(pred(&mut reader)?) } diff --git a/rnex-core/src/rmc/structures/string.rs b/rnex-core/src/rmc/structures/string.rs index 8830822..1231956 100644 --- a/rnex-core/src/rmc/structures/string.rs +++ b/rnex-core/src/rmc/structures/string.rs @@ -1,18 +1,18 @@ -use super::{Result, RmcSerialize}; +use std::io::{Read, Write}; use bytemuck::bytes_of; use log::error; -use std::io::{Read, Write}; use v_byte_helpers::{IS_BIG_ENDIAN, ReadExtensions}; +use super::{Result, RmcSerialize}; -impl RmcSerialize for String { +impl RmcSerialize for String{ fn deserialize(reader: &mut impl Read) -> Result { let len: u16 = reader.read_struct(IS_BIG_ENDIAN)?; - if len == 0 { + if len == 0{ return Ok("".to_string()); } let mut data = vec![0; len as usize]; reader.read_exact(&mut data)?; - if *data.last().unwrap() != 0 { + if *data.last().unwrap() != 0{ error!("unable to find null terminator... continuing anyways"); } data.pop(); @@ -27,7 +27,7 @@ impl RmcSerialize for String { } } -impl RmcSerialize for &str { +impl RmcSerialize for &str{ fn deserialize(_reader: &mut impl Read) -> Result { panic!("cannot serialize to &str") } @@ -45,3 +45,4 @@ impl RmcSerialize for &str { Ok(2 + self.as_bytes().len() as u32 + 1) } } + diff --git a/rnex-core/src/rmc/structures/string_set.rs b/rnex-core/src/rmc/structures/string_set.rs deleted file mode 100644 index efb6c05..0000000 --- a/rnex-core/src/rmc/structures/string_set.rs +++ /dev/null @@ -1,95 +0,0 @@ -use std::{collections::HashSet, hash::Hash, str::FromStr, string::ToString}; - -use rnex_core::rmc::structures::RmcSerialize; - -#[derive(Debug, Clone)] -pub struct StringSet(pub HashSet) -where - ::Err: std::error::Error + Send + Sync + 'static; - -impl PartialEq for StringSet -where - ::Err: std::error::Error + Send + Sync + 'static, -{ - fn eq(&self, other: &Self) -> bool { - self.0.iter().eq(&other.0) - } -} - -impl ToString for StringSet -where - ::Err: std::error::Error + Send + Sync + 'static, -{ - fn to_string(&self) -> String { - self.0 - .iter() - .map(ToString::to_string) - .reduce(|a, b| format!("{}|{}", a, b)) - .unwrap_or(String::new()) - } -} - -impl FromStr for StringSet -where - ::Err: std::error::Error + Send + Sync + 'static, -{ - type Err = Box; - - fn from_str(s: &str) -> Result { - Ok(Self( - s.split("|") - .filter(|v| !v.is_empty()) - .map(T::from_str) - .try_fold( - HashSet::new(), - |mut a, b| -> Result, Self::Err> { - a.insert(b.map_err(Box::new)?); - Ok(a) - }, - )?, - )) - } -} - -impl RmcSerialize for StringSet -where - ::Err: std::error::Error + Send + Sync + 'static, -{ - fn deserialize(reader: &mut impl std::io::prelude::Read) -> super::Result - where - Self: Sized, - { - Self::from_str(&String::deserialize(reader)?).map_err(super::Error::Other) - } - fn serialize(&self, writer: &mut impl std::io::prelude::Write) -> super::Result<()> { - self.to_string().serialize(writer) - } - fn serialize_write_size(&self) -> super::Result { - self.to_string().serialize_write_size() - } -} - -#[cfg(test)] -mod test { - use std::str::FromStr; - - use crate::rmc::structures::string_set::StringSet; - - #[test] - fn test() { - let str_val = "0|100|200|10|110|210|20|120|220|30|130|230"; - let set: StringSet = StringSet::from_str(str_val).unwrap(); - let string_2 = set.to_string(); - let reset: StringSet = StringSet::from_str(&string_2).unwrap(); - - for val in &set.0 { - if !reset.0.contains(&val) { - panic!("sets arent equivalent"); - } - } - - let _: StringSet = StringSet::from_str("").unwrap(); - - let _: StringSet = StringSet::from_str("10").unwrap(); - } -} diff --git a/rnex-core/src/rmc/structures/variant.rs b/rnex-core/src/rmc/structures/variant.rs index c5c41b0..6056f3f 100644 --- a/rnex-core/src/rmc/structures/variant.rs +++ b/rnex-core/src/rmc/structures/variant.rs @@ -1,10 +1,10 @@ -use rnex_core::kerberos::KerberosDateTime; -use rnex_core::rmc::structures; -use rnex_core::rmc::structures::{Result, RmcSerialize}; use std::io::{Read, Write}; +use crate::kerberos::KerberosDateTime; +use crate::rmc::structures; +use crate::rmc::structures::RmcSerialize; -#[derive(Debug, Clone, Default, PartialEq)] -pub enum Variant { +#[derive(Debug, Clone, Default)] +pub enum Variant{ #[default] None, SInt64(i64), @@ -15,9 +15,9 @@ pub enum Variant { UInt64(u64), } -impl RmcSerialize for Variant { - fn serialize(&self, writer: &mut impl Write) -> Result<()> { - match self { +impl RmcSerialize for Variant{ + fn serialize(&self, writer: &mut impl Write) -> crate::rmc::structures::Result<()> { + match self{ Variant::None => { writer.write_all(&[0])?; } @@ -50,8 +50,8 @@ impl RmcSerialize for Variant { Ok(()) } - fn deserialize(reader: &mut impl Read) -> Result { - match u8::deserialize(reader)? { + fn deserialize(reader: &mut impl Read) -> crate::rmc::structures::Result { + match u8::deserialize(reader)?{ 0 => Ok(Variant::None), 1 => Ok(Variant::SInt64(i64::deserialize(reader)?)), 2 => Ok(Variant::Double(f64::deserialize(reader)?)), @@ -59,7 +59,7 @@ impl RmcSerialize for Variant { 4 => Ok(Variant::String(String::deserialize(reader)?)), 5 => Ok(Variant::DateTime(KerberosDateTime::deserialize(reader)?)), 6 => Ok(Variant::UInt64(u64::deserialize(reader)?)), - v => Err(structures::Error::UnexpectedValue(v as u64)), + v => Err(structures::Error::UnexpectedValue(v as u64)) } } -} +} \ No newline at end of file diff --git a/rnex-core/src/rnex_proxy_common.rs b/rnex-core/src/rnex_proxy_common.rs index 54de962..29cb161 100644 --- a/rnex-core/src/rnex_proxy_common.rs +++ b/rnex-core/src/rnex_proxy_common.rs @@ -1,40 +1,11 @@ -use crate::{PID, prudp::socket_addr::PRUDPSockAddr}; use macros::RmcSerialize; +use crate::prudp::socket_addr::PRUDPSockAddr; -#[derive(Debug, RmcSerialize, PartialEq, Eq)] +#[derive(Debug, RmcSerialize)] #[rmc_struct(0)] -pub struct ConnectionInitData { +pub struct ConnectionInitData{ pub prudpsock_addr: PRUDPSockAddr, - pub pid: PID, + pub pid: u32, + } -#[cfg(test)] -mod test { - use std::{ - io::Cursor, - net::{Ipv4Addr, SocketAddr, SocketAddrV4}, - }; - - use crate::{ - prudp::{socket_addr::PRUDPSockAddr, virtual_port::VirtualPort}, - rmc::structures::RmcSerialize, - rnex_proxy_common::ConnectionInitData, - }; - - #[test] - fn test() { - let data = ConnectionInitData { - prudpsock_addr: PRUDPSockAddr { - regular_socket_addr: SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::BROADCAST, 19293)), - virtual_port: VirtualPort::new(10, 2), - }, - pid: 100, - }; - - let ser = data.to_data().unwrap(); - - let de = ConnectionInitData::deserialize(&mut Cursor::new(ser)).unwrap(); - - assert_eq!(data, de); - } -} diff --git a/rnex-core/src/util.rs b/rnex-core/src/util.rs index 2bcf87b..ff0150c 100644 --- a/rnex-core/src/util.rs +++ b/rnex-core/src/util.rs @@ -1,25 +1,24 @@ -use crate::reggie::{UnitPacketRead, UnitPacketWrite}; -use log::{error, info}; use std::ops::Deref; -use std::sync::{Arc, Weak}; -use std::vec; +use std::sync::Arc; +use log::{error, info}; use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt}; +use tokio::sync::mpsc::{channel, Receiver, Sender}; use tokio::sync::Notify; -use tokio::sync::mpsc::{Receiver, Sender, channel}; use tokio::task; +use crate::reggie::{UnitPacketRead, UnitPacketWrite}; #[derive(Clone)] pub struct SendingBufferConnection(Sender>, Arc); pub struct SplittableBufferConnection(SendingBufferConnection, Receiver>); -impl AsRef for SplittableBufferConnection { +impl AsRef for SplittableBufferConnection{ fn as_ref(&self) -> &SendingBufferConnection { &self.0 } } -impl Deref for SplittableBufferConnection { +impl Deref for SplittableBufferConnection{ type Target = SendingBufferConnection; fn deref(&self) -> &Self::Target { @@ -27,7 +26,9 @@ impl Deref for SplittableBufferConnection { } } -impl From for SplittableBufferConnection { + + +impl From for SplittableBufferConnection{ fn from(value: T) -> Self { Self::new(value) } @@ -47,6 +48,7 @@ impl SplittableBufferConnection { let mut recver = inside_recv; let mut stream = stream; + loop { tokio::select! { data = recver.recv() => { @@ -79,7 +81,7 @@ impl SplittableBufferConnection { } } } - if let Err(e) = stream.shutdown().await { + if let Err(e) = stream.shutdown().await{ error!("failed to shut down stream: {}", e); } }); @@ -89,11 +91,11 @@ impl SplittableBufferConnection { } } -impl SendingBufferConnection { - pub async fn send(&self, buffer: Vec) -> Option<()> { +impl SendingBufferConnection{ + pub async fn send(&self, buffer: Vec) -> Option<()>{ self.0.send(buffer).await.ok() } - pub fn is_alive(&self) -> bool { + pub fn is_alive(&self) -> bool{ !self.0.is_closed() } pub async fn disconnect(&self) { @@ -104,34 +106,12 @@ impl SendingBufferConnection { } } -impl SplittableBufferConnection { - pub async fn recv(&mut self) -> Option> { +impl SplittableBufferConnection{ + pub async fn recv(&mut self) -> Option>{ self.1.recv().await } - pub fn duplicate_sender(&self) -> SendingBufferConnection { + pub fn duplicate_sender(&self) -> SendingBufferConnection{ self.0.clone() } } - -struct WeakVec(Vec>); - -impl WeakVec { - pub fn new() -> Self { - Self(vec![]) - } - - pub fn from_vec(vec: Vec>) -> Self { - Self(vec) - } - - pub fn push(&mut self, val: Weak) { - self.0.retain(|v| v.upgrade().is_some()); - - self.0.push(val); - } - - pub fn iter(&self) -> impl Iterator> { - self.0.iter().filter_map(|w| w.upgrade()) - } -} diff --git a/rnex-core/src/versions.rs b/rnex-core/src/versions.rs index 03b71b5..7b5ec30 100644 --- a/rnex-core/src/versions.rs +++ b/rnex-core/src/versions.rs @@ -3,93 +3,95 @@ use std::ops::{BitAnd, BitOr}; use typenum::{Cmp, IsEqual, IsLess, IsLessOrEqual, Unsigned}; /// This trait represents a version at compile time -trait Version { +trait Version{ type Major: Unsigned; type Minor: Unsigned; } /// This struct contains nothing and is used to represent specific versions as an instance of /// [`Version`]. It is instances as `Ver` -struct Ver { - _phantom: PhantomData<(MAJ, MIN)>, +struct Ver{ + _phantom: PhantomData<(MAJ, MIN)> } -impl Version for Ver { +impl Version for Ver{ type Major = MAJ; type Minor = MIN; } /// Represents two versions which can be compared -trait ComparableVersion: Version { +trait ComparableVersion: Version{ type IsAtLeast: SameOrUnit; } -impl ComparableVersion for U -where +impl ComparableVersion for U where ::Major: Cmp, ::Minor: IsLessOrEqual, - ::Major: - IsEqual>>, - ::Major: IsLess< - Self::Major, - Output: BitOr< - typenum::And< - typenum::Eq, - typenum::LeEq, - >, - Output: SameOrUnit, - >, + ::Major: IsEqual< + Self::Major, + Output: BitAnd< + typenum::LeEq >, -{ + >, + ::Major: IsLess< + Self::Major, + Output: BitOr< + typenum::And< + typenum::Eq, + typenum::LeEq, + >, + Output: SameOrUnit + > + > { + type IsAtLeast = typenum::Or< typenum::Le, - typenum::And, typenum::LeEq>, + typenum::And< + typenum::Eq, + typenum::LeEq, + > >; } + /// Simple check for testing if the `TEST` version is at least `REQ` or higher. type VersionAbove = >::IsAtLeast; -trait VersionIsAtLeast {} +trait VersionIsAtLeast{} + +impl> VersionIsAtLeast for T{} -impl> VersionIsAtLeast - for T -{ -} /// Trait for containing the result of elements which only conditionally exist -trait CondElemResult { +trait CondElemResult{ type Output; } /// Empty helper struct which only servers to give a concrete type when creating fields in rmc /// structs which have a version requirement. This is not meant to be used directly, use /// [`MinVersion`] instead. -struct MinVersionElementHelper> { - _phantom: PhantomData<(T, REQUIRED, VER)>, +struct MinVersionElementHelper>{ + _phantom: PhantomData<(T, REQUIRED, VER)> } /// This should be used either with [`typenum::True`] or [`typenum::False`]. When `True` the [`Self::Output`] /// will be the same as the `T` you put into Output. When `False` it will always be `()` -trait SameOrUnit { +trait SameOrUnit{ type Output; } -impl SameOrUnit for typenum::True { +impl SameOrUnit for typenum::True{ type Output = T; } -impl SameOrUnit for typenum::False { +impl SameOrUnit for typenum::False{ type Output = (); } -impl> CondElemResult - for MinVersionElementHelper -{ +impl> CondElemResult for MinVersionElementHelper where { type Output = <>::IsAtLeast as SameOrUnit>::Output; } /// When the version condition is met the field will exist and will simply be `T` if not it will be /// replaced by `()`. Use this when you need to add versioning to rmc structs. -type MinVersion = - as CondElemResult>::Output; +type MinVersion = as CondElemResult>::Output; \ No newline at end of file diff --git a/setup-hook.sh b/setup-hook.sh deleted file mode 100755 index 04774d6..0000000 --- a/setup-hook.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -cp buildscripts/pre-commit .git/hooks/ diff --git a/shell.nix b/shell.nix deleted file mode 100644 index 3ac2963..0000000 --- a/shell.nix +++ /dev/null @@ -1,18 +0,0 @@ -{ - pkgs ? import { }, - pkg ? pkgs.callPackage ./. { }, -}: -pkgs.mkShell { - # Get dependencies from the main package - # inputsFrom = [ pkg ]; - # Additional tooling - buildInputs = with pkgs; [ - cargo - rust-analyzer # LSP Server - rustfmt # Formatter - clippy # Linter - podman - yq - jq - ]; -} diff --git a/test-all.sh b/test-all.sh deleted file mode 100755 index 989b74f..0000000 --- a/test-all.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -EDITIONS=$(yq ea "." editions.yaml | yq 'keys[]') -IFS=$'\n' -while IFS=$'\n' read -r EDITION; do - if [[ $(yq ea ".$EDITION.include-in-checkall" editions.yaml) == "true" ]] - then - export EDITION - ./test-edition.sh $EDITION - fi -done <<< "$EDITIONS" diff --git a/test-edition.sh b/test-edition.sh index aaafad6..d483592 100755 --- a/test-edition.sh +++ b/test-edition.sh @@ -1,7 +1,4 @@ #!/usr/bin/env bash - -set -euo pipefail - if [ -z ${EDITION+x} ]; then EDITION=$1 fi @@ -10,7 +7,5 @@ fi source ./buildscripts/common.sh echo FEATURES: echo $EDITION_FEATURES -echo ENV SETTINGS: -env -OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include/openssl OPENSSL_STATIC=1 RUSTFLAGS="-C relocation-model=static -C linker=ld.lld" cargo test --features "$EDITION_FEATURES" --target x86_64-unknown-linux-musl +OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include/openssl OPENSSL_STATIC=1 RUSTFLAGS="-C relocation-model=static -C linker=ld.lld" cargo test --features "$EDITION_FEATURES" --target x86_64-unknown-linux-musl \ No newline at end of file