diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile deleted file mode 100644 index 3b95d846b..000000000 --- a/.devcontainer/Dockerfile +++ /dev/null @@ -1,2 +0,0 @@ -ARG VARIANT="6.0-bullseye-slim" -FROM mcr.microsoft.com/vscode/devcontainers/dotnet:0-${VARIANT} \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json deleted file mode 100644 index 901133e4d..000000000 --- a/.devcontainer/devcontainer.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "C# (.NET)", - "build": { - "dockerfile": "Dockerfile", - "args": { - "VARIANT": "6.0" - } - }, - "settings": {}, - "extensions": [ - "ms-dotnettools.csharp" - ], - "appPort": [ - 29910, - 6667, - 29920, - 10086, - 27901, - 29900, - 29901, - 27900, - 28910, - 28900, - 80 - ], - "remoteUser": "vscode" -} \ No newline at end of file diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 3729ff0cd..000000000 --- a/.dockerignore +++ /dev/null @@ -1,25 +0,0 @@ -**/.classpath -**/.dockerignore -**/.env -**/.git -**/.gitignore -**/.project -**/.settings -**/.toolstarget -**/.vs -**/.vscode -**/*.*proj.user -**/*.dbmdl -**/*.jfm -**/azds.yaml -**/bin -**/charts -**/docker-compose* -**/Dockerfile* -**/node_modules -**/npm-debug.log -**/obj -**/secrets.dev.yaml -**/values.dev.yaml -LICENSE -README.md \ No newline at end of file diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 43097e7f3..000000000 --- a/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -*.cs linguist-language=C# diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index a8e3b3d75..000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: bug -assignees: '' - ---- - -------------- Have you found a bug in UniSpy? ----------------- -**DO NOT FILL A BUG REPORT FOR AN UNSUPPORTED GAME, PLEASE USE THE APPROPRIATE TEMPLATE FOR UNSUPPORTED GAMES** -1. Verify that the issue is still present in the last development version of UniSpy -2. Set your logging to "Verbose" and reproduce the issue (this will help us tracking which data has been sent or received from the server) -3. Fill the template below ------------- Remove this initial lines -------------------------- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Server information (please complete the following information):** - - OS where the server is being hosted: [e.g. CentOS 7, Debian 10, Generic Linux 5.2] - - Channel: [e.g. Candidate, Development, or Master] - - Version: [e.g. 0.5.1, 0.5.1-RC2 or the git commit number for development channel] - -**Game information (if a game has triggered a specific error or issue):** -- Name: [e.g. Crysis 2, Worms 3D] -- Platform: [e.g. Windows, PS2] -- Version: [e.g. Steam version or 1.4] - -**Server logs** -Logs of the client connection and the data which the server sends or receives, or the exception log. - -MAKE SURE TO REMOVE ANY SENSIBLE DATA (such as password, username, response or challenge strings) - -**Additional context** -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/custom.md b/.github/ISSUE_TEMPLATE/custom.md deleted file mode 100644 index 30ead30eb..000000000 --- a/.github/ISSUE_TEMPLATE/custom.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -name: Game compatibility -about: Fill an issue about a missing game compatibility -title: Game name -labels: compat -assignees: '' - ---- - ------ Have you found an uncompatible game in RetroSpy? ----- -1. Verify that the game does not work in the last development version -2. Make sure to enable debugging logs and reproduce the issue -3. Fill the form below -------- Delete this extra lines --------------- - -** Game information ** -Name: [e.g. Crysis 2] -Platform: [e.g. Windows, PS2] -Version: [e.g. 1.2, Steam] - -** Special game information ** -(This informations can be found while looking at the logs, for example when the game tries to login or request a server. Write "?" if the game does not send that information) -Namespace id: [e.g. 0] -Partner id: [e.g. 0, 10] -Internal game name: [e.g. capricorn or gmtest] -SDK version: [e.g. 20] - -** Server information ** -Git commit: -Logs: Make sure to hide or remove sensible informations (like username, email, respose, password) - -** Additional information ** -Any addition information that might help the issue diff --git a/.github/README.MD b/.github/README.MD deleted file mode 100644 index 6824d0632..000000000 --- a/.github/README.MD +++ /dev/null @@ -1,26 +0,0 @@ -# UniSpy Server - -[![license](https://img.shields.io/github/license/GameProgressive/UniSpyServer.svg)](../LICENSE) -![CIPass](https://github.com/GameProgressive/UniSpyServer/workflows/CI/badge.svg)\ -![platforms](https://img.shields.io/badge/platform-win32%20%7C%20win64%20%7C%20linux%20%7C%20osx-brightgreen.svg)\ -[![discord-banner](https://discord.com/api/guilds/512314008079171615/widget.png?style=banner2)](https://discord.gg/NpggYaD) - -UniSpy is a GameSpy Project that aims to create GameSpy services. - -The server is written in C# and is inspired by the old OpenSpy project. - -## Information & Documentation -See the [wiki](https://github.com/GameProgressive/UniSpyServer/wiki) for more information about project and the UniSpy Server. -You can also use our Software Development Kit to create games or learn about the [UniSpySDK](https://github.com/GameProgressive/UniSpySDK). - -Technical papers and documentation about the GameSpy protocol and the games that use it, [GameSpyDocs](https://github.com/GameProgressive/GameSpyDocs). - -## Credits -* The [contributors](https://github.com/GameProgressive/UniSpyServer/graphs/contributors) of the project -* [Luigi Auriemma](https://aluigi.altervista.org/papers.htm#distrust) for his gamespy papers that were used as a reference -* [BattleSpy](https://github.com/BF2Statistics/BattleSpy) for their library, that we used as a base for UniSpy -* [NetCoreServer](https://github.com/chronoxor/NetCoreServer) for their TCP and UDP server - - -## License -This project is licensed under the [GNU Affero General Public License v3.0](../LICENSE). diff --git a/.github/README.md b/.github/README.md new file mode 100644 index 000000000..1f019c1e5 --- /dev/null +++ b/.github/README.md @@ -0,0 +1,41 @@ +# UniSpy Server +[![license](https://img.shields.io/github/license/GameProgressive/UniSpyServer.svg)](../LICENSE) +![CIPass](https://github.com/GameProgressive/UniSpyServer/workflows/CI/badge.svg)\ +![platforms](https://img.shields.io/badge/platform-win32%20%7C%20win64%20%7C%20linux%20%7C%20osx-brightgreen.svg)\ +[![discord-banner](https://discord.com/api/guilds/512314008079171615/widget.png?style=banner2)](https://discord.gg/NpggYaD) + +UniSpy is a GameSpy Project that aims to create GameSpy services. + +The server is written in C# and is inspired by the old OpenSpy project. + +## Information & Documentation +See the [wiki](https://github.com/GameProgressive/UniSpyServer/wiki) for more information about project and the UniSpy Server. +You can also use our Software Development Kit to create games or learn about the [UniSpySDK](https://github.com/GameProgressive/UniSpySDK). + +Technical papers and documentation about the GameSpy protocol and the games that use it, [GameSpyDocs](https://github.com/GameProgressive/GameSpyDocs). + +## Credits +* The [contributors](https://github.com/GameProgressive/UniSpyServer/graphs/contributors) of the project +* [Luigi Auriemma](https://aluigi.altervista.org/papers.htm#distrust) for his gamespy papers that were used as a reference +* [BattleSpy](https://github.com/BF2Statistics/BattleSpy) for their library, that we used as a base for UniSpy +* [NetCoreServer](https://github.com/chronoxor/NetCoreServer) for their TCP and UDP server + + +## License +This project is licensed under the [GNU Affero General Public License v3.0](../LICENSE). + + +## Why rewrite C# to python +* The vscode extensions for C# development is become more and more hard to use, and microsoft abandoned the open-source OmniSharp project and replacing it with it's own closed source language server. +* The c# project seems hard to run by users, it require a lot of deploy knowledge and hard for collaborations, for the future of the gamespy emulator, I choose to rewrite this into a opensource and easy high level language - python. + + +## How to run +* Run ```docker network create unispy``` to setup a network for unispy +* Run ```docker compose -f docker-compose-unispy-env.yml up -d``` to setup postgresql and redis +* Run ```export UNISPY_CONFIG=''``` to setup env config file path, remember replace symbol `````` with config file path +* Open with vscode: + * Use vscode to open the src folder and reopen in devcontainer (make sure your vscode have devcontainer extension) +* open with github codespace: + * add ```unispy_config = ""``` after the line of ```unispy_config = os.environ.get("UNISPY_CONFIG")``` in config.py (for unittest working) + * github codespace vscode web can not install devcontainer, the project can not running in docker network ```unispy```. Therefore, replace ```"server": "unispy_postgresql"``` and ```"server": "unispy_redis"``` to ```"server": "localhost"``` in config.json to use localhost postgres and redis in docker (we already setup) diff --git a/.github/labeler.yml b/.github/labeler.yml deleted file mode 100644 index 74da29e0e..000000000 --- a/.github/labeler.yml +++ /dev/null @@ -1,24 +0,0 @@ -CDKey: - - "src/Servers/CDKey/**" - -Chat: - - "src/Servers/Chat/**" - -Game Status: - - "src/Servers/GameStatus/**" - -Nat Negotation: - - "src/Servers/NatNegotiation/**" - -Presence System: - - "src/Servers/PresenceConnectionManager/**" - - "src/Servers/PresenceSearchPlayer/**" - -Query Report: - - "src/Servers/QueryReport/**" - -Server Browser: - - "src/Servers/ServerBrowser/**" - -Web Services: - - "src/Servers/WebServices/**" \ No newline at end of file diff --git a/.github/workflows/cd-cdkey.yml b/.github/workflows/cd-cdkey.yml deleted file mode 100644 index 0f6cbed02..000000000 --- a/.github/workflows/cd-cdkey.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: CD - CDKey - -on: - push: - branches: - - master - - candidate - paths: - - "src/Servers/CDKey/src/**" - - "src/Libraries/Core/src/**" - -jobs: - push: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Deploy to staging - if: github.event_name == 'push' && github.ref == 'refs/heads/candidate' - uses: elgohr/Publish-Docker-Github-Action@3.01 - with: - name: gameprogressive/cdkey - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_KEY }} - tagging: true - dockerfile: ./src/Servers/CDKey/src/Dockerfile - - name: Deploy to production - if: github.event_name == 'push' && github.ref == 'refs/heads/master' - uses: elgohr/Publish-Docker-Github-Action@3.01 - with: - name: gameprogressive/cdkey - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_KEY }} - tagging: true - dockerfile: ./src/Servers/CDKey/src/Dockerfile \ No newline at end of file diff --git a/.github/workflows/cd-chat.yml b/.github/workflows/cd-chat.yml deleted file mode 100644 index 781f9c002..000000000 --- a/.github/workflows/cd-chat.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: CD - Chat - -on: - push: - branches: - - master - - candidate - paths: - - "src/Servers/Chat/src/**" - - "src/Libraries/Core/src/**" - -jobs: - push: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Deploy to staging - if: github.event_name == 'push' && github.ref == 'refs/heads/candidate' - uses: elgohr/Publish-Docker-Github-Action@3.01 - with: - name: gameprogressive/chat - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_KEY }} - tagging: true - dockerfile: ./src/Servers/Chat/src/Dockerfile - - name: Deploy to production - if: github.event_name == 'push' && github.ref == 'refs/heads/master' - uses: elgohr/Publish-Docker-Github-Action@3.01 - with: - name: gameprogressive/chat - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_KEY }} - tagging: true - dockerfile: ./src/Servers/Chat/src/Dockerfile \ No newline at end of file diff --git a/.github/workflows/cd-gs.yml b/.github/workflows/cd-gs.yml deleted file mode 100644 index 06bd736c7..000000000 --- a/.github/workflows/cd-gs.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: CD - GS - -on: - push: - branches: - - master - - candidate - paths: - - "src/Servers/GameStatus/src/**" - - "src/Libraries/Core/src/**" - -jobs: - push: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Deploy to staging - if: github.event_name == 'push' && github.ref == 'refs/heads/candidate' - uses: elgohr/Publish-Docker-Github-Action@3.01 - with: - name: gameprogressive/gs - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_KEY }} - tagging: true - dockerfile: ./src/Servers/GameStatus/src/Dockerfile - - name: Deploy to production - if: github.event_name == 'push' && github.ref == 'refs/heads/master' - uses: elgohr/Publish-Docker-Github-Action@3.01 - with: - name: gameprogressive/gs - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_KEY }} - tagging: true - dockerfile: ./src/Servers/GameStatus/src/Dockerfile \ No newline at end of file diff --git a/.github/workflows/cd-gtr.yml b/.github/workflows/cd-gtr.yml deleted file mode 100644 index 98fa68ebc..000000000 --- a/.github/workflows/cd-gtr.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: CD - GTR - -on: - push: - branches: - - master - - candidate - paths: - - "src/Servers/GameTrafficRelay/src/**" - - "src/Libraries/Core/src/**" - -jobs: - push: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Deploy to staging - if: github.event_name == 'push' && github.ref == 'refs/heads/candidate' - uses: elgohr/Publish-Docker-Github-Action@3.01 - with: - name: gameprogressive/gtr - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_KEY }} - tagging: true - dockerfile: ./src/Servers/GameTrafficRelay/src/Dockerfile - - name: Deploy to production - if: github.event_name == 'push' && github.ref == 'refs/heads/master' - uses: elgohr/Publish-Docker-Github-Action@3.01 - with: - name: gameprogressive/gtr - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_KEY }} - tagging: true - dockerfile: ./src/Servers/GameTrafficRelay/src/Dockerfile \ No newline at end of file diff --git a/.github/workflows/cd-nn.yml b/.github/workflows/cd-nn.yml deleted file mode 100644 index 05ea071f2..000000000 --- a/.github/workflows/cd-nn.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: CD - NN - -on: - push: - branches: - - master - - candidate - paths: - - "src/Servers/NatNegotiation/src/**" - - "src/Libraries/Core/src/**" - -jobs: - push: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Deploy to staging - if: github.event_name == 'push' && github.ref == 'refs/heads/candidate' - uses: elgohr/Publish-Docker-Github-Action@3.01 - with: - name: gameprogressive/nn - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_KEY }} - tagging: true - dockerfile: ./src/Servers/NatNegotiation/src/Dockerfile - - name: Deploy to production - if: github.event_name == 'push' && github.ref == 'refs/heads/master' - uses: elgohr/Publish-Docker-Github-Action@3.01 - with: - name: gameprogressive/nn - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_KEY }} - tagging: true - dockerfile: ./src/Servers/NatNegotiation/src/Dockerfile \ No newline at end of file diff --git a/.github/workflows/cd-pcm.yml b/.github/workflows/cd-pcm.yml deleted file mode 100644 index e0449af8b..000000000 --- a/.github/workflows/cd-pcm.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: CD - PCM - -on: - push: - branches: - - master - - candidate - paths: - - "src/Servers/PresenceConnectionManager/src/**" - - "src/Libraries/Core/src/**" - -jobs: - push: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Deploy to staging - if: github.event_name == 'push' && github.ref == 'refs/heads/candidate' - uses: elgohr/Publish-Docker-Github-Action@3.01 - with: - name: gameprogressive/pcm - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_KEY }} - tagging: true - dockerfile: ./src/Servers/PresenceConnectionManager/src/Dockerfile - - name: Deploy to production - if: github.event_name == 'push' && github.ref == 'refs/heads/master' - uses: elgohr/Publish-Docker-Github-Action@3.01 - with: - name: gameprogressive/pcm - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_KEY }} - tagging: true - dockerfile: ./src/Servers/PresenceConnectionManager/src/Dockerfile \ No newline at end of file diff --git a/.github/workflows/cd-psp.yml b/.github/workflows/cd-psp.yml deleted file mode 100644 index 9d82fcc88..000000000 --- a/.github/workflows/cd-psp.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: CD - PSP - -on: - push: - branches: - - master - - candidate - paths: - - "src/Servers/PresenceSearchPlayer/src/**" - - "src/Libraries/Core/src/**" - -jobs: - push: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Deploy to staging - if: github.event_name == 'push' && github.ref == 'refs/heads/candidate' - uses: elgohr/Publish-Docker-Github-Action@3.01 - with: - name: gameprogressive/psp - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_KEY }} - tagging: true - dockerfile: ./src/Servers/PresenceSearchPlayer/src/Dockerfile - - name: Deploy to production - if: github.event_name == 'push' && github.ref == 'refs/heads/master' - uses: elgohr/Publish-Docker-Github-Action@3.01 - with: - name: gameprogressive/psp - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_KEY }} - tagging: true - dockerfile: ./src/Servers/PresenceSearchPlayer/src/Dockerfile \ No newline at end of file diff --git a/.github/workflows/cd-qr.yml b/.github/workflows/cd-qr.yml deleted file mode 100644 index cb3e7ad0c..000000000 --- a/.github/workflows/cd-qr.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: CD - QR - -on: - push: - branches: - - master - - candidate - paths: - - "src/Servers/QueryReport/src/**" - - "src/Libraries/Core/src/**" - -jobs: - push: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Deploy to staging - if: github.event_name == 'push' && github.ref == 'refs/heads/candidate' - uses: elgohr/Publish-Docker-Github-Action@3.01 - with: - name: gameprogressive/qr - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_KEY }} - tagging: true - dockerfile: ./src/Servers/QueryReport/src/Dockerfile - - name: Deploy to production - if: github.event_name == 'push' && github.ref == 'refs/heads/master' - uses: elgohr/Publish-Docker-Github-Action@3.01 - with: - name: gameprogressive/qr - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_KEY }} - tagging: true - dockerfile: ./src/Servers/QueryReport/src/Dockerfile \ No newline at end of file diff --git a/.github/workflows/cd-sb.yml b/.github/workflows/cd-sb.yml deleted file mode 100644 index eca47db04..000000000 --- a/.github/workflows/cd-sb.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: CD - SB - -on: - push: - branches: - - master - - candidate - paths: - - "src/Servers/ServerBrowser/src/**" - - "src/Libraries/Core/src/**" - -jobs: - push: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Deploy to staging - if: github.event_name == 'push' && github.ref == 'refs/heads/candidate' - uses: elgohr/Publish-Docker-Github-Action@3.01 - with: - name: gameprogressive/sb - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_KEY }} - tagging: true - dockerfile: ./src/Servers/ServerBrowser/src/Dockerfile - - name: Deploy to production - if: github.event_name == 'push' && github.ref == 'refs/heads/master' - uses: elgohr/Publish-Docker-Github-Action@3.01 - with: - name: gameprogressive/sb - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_KEY }} - tagging: true - dockerfile: ./src/Servers/ServerBrowser/src/Dockerfile \ No newline at end of file diff --git a/.github/workflows/cd-ws.yml b/.github/workflows/cd-ws.yml deleted file mode 100644 index efa024577..000000000 --- a/.github/workflows/cd-ws.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: CD - WS - -on: - push: - branches: - - master - - candidate - paths: - - "src/Servers/WebServer/src/**" - - "src/Libraries/Core/src/**" - -jobs: - push: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Deploy to staging - if: github.event_name == 'push' && github.ref == 'refs/heads/candidate' - uses: elgohr/Publish-Docker-Github-Action@3.01 - with: - name: gameprogressive/ws - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_KEY }} - tagging: true - dockerfile: ./src/Servers/WebServer/src/Dockerfile - - name: Deploy to production - if: github.event_name == 'push' && github.ref == 'refs/heads/master' - uses: elgohr/Publish-Docker-Github-Action@3.01 - with: - name: gameprogressive/ws - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_KEY }} - tagging: true - dockerfile: ./src/Servers/WebServer/src/Dockerfile \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index dc0c99d97..000000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: CI - -on: - push: - branches: - - master - - candidate - - develop - pull_request: - -jobs: - unispy: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ ubuntu-latest, windows-latest, macos-latest ] - - steps: - - uses: actions/checkout@v2 - - name: Setup .NET - uses: actions/setup-dotnet@v1 - with: - dotnet-version: '6.0.100' - - name: Install dependencies - run: dotnet restore - - name: Build - run: dotnet build --no-restore \ No newline at end of file diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml deleted file mode 100644 index 0d40ed334..000000000 --- a/.github/workflows/labeler.yml +++ /dev/null @@ -1,12 +0,0 @@ -name: "Pull Request Labeler" -on: -- pull_request_target - -jobs: - triage: - runs-on: ubuntu-latest - steps: - - uses: actions/labeler@v3 - with: - repo-token: "${{ secrets.GITHUB_TOKEN }}" - sync-labels: true \ No newline at end of file diff --git a/.gitignore b/.gitignore index 9839b2ad8..18630a37c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,378 +1,170 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. -## -## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore - -# User-specific files -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ +# Byte-compiled / optimized / DLL files +**/__pycache__/ +*.py[cod] +*$py.class +*.pyc +# C extensions +*.so +.ruff_cache/ +# Distribution / packaging +.Python build/ - -# Visual Studio 2015/2017 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# Visual Studio 2017 auto generated files -Generated\ Files/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUNIT -*.VisualState.xml -TestResult.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# Benchmark Results -BenchmarkDotNet.Artifacts/ - -# .NET Core -project.lock.json -project.fragment.lock.json -artifacts/ -**/Properties/launchSettings.json - -# StyleCop -StyleCopReport.xml - -# Files built by Visual Studio -*_i.c -*_p.c -*_i.h -*.ilk -*.meta -*.obj -*.iobj -*.pch -*.pdb -*.ipdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: *.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# Visual Studio Trace Files -*.e2e - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# JustCode is a .NET coding add-in -.JustCode - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# AxoCover is a Code Coverage Tool -.axoCover/* -!.axoCover/settings.json - -# Visual Studio code coverage results -*.coverage -*.coveragexml - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# Note: Comment the next line if you want to checkin your web deploy settings, -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# The packages folder can be ignored because of Package Restore -**/[Pp]ackages/* -# except build/, which is used as an MSBuild target. -!**/[Pp]ackages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/[Pp]ackages/repositories.config -# NuGet v3's project.json files produces more ignorable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt -*.appx +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +# log files +*.log.* -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -orleans.codegen.cs - -# Including strong name files can present a security risk -# (https://github.com/github/gitignore/pull/2483#issue-259490424) -#*.snk - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm -ServiceFabricBackup/ -*.rptproj.bak - -# SQL Server files -*.mdf -*.ldf -*.ndf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings -*.rptproj.rsuser - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat -node_modules/ - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) -*.vbw - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# JetBrains Rider -.idea/ -*.sln.iml - -# CodeRush -.cr/ - -# Python Tools for Visual Studio (PTVS) -__pycache__/ *.pyc +*.txt +!requirements.txt -# Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config - -# Tabs Studio -*.tss - -# Telerik's JustMock configuration file -*.jmconfig - -# BizTalk build output -*.btp.cs -*.btm.cs -*.odx.cs -*.xsd.cs - -# OpenCover UI analysis results -OpenCover/ - -# Azure Stream Analytics local run output -ASALocalRun/ - -# MSBuild Binary and Structured Log -*.binlog - -# NVidia Nsight GPU debugger configuration file -*.nvuser - -# MFractors (Xamarin productivity tool) working folder -.mfractor/ - -# retrospy -logs\ - -# linq2db -.tools/ -db/ - -# Prerequisites -*.d - -# Compiled Object files -*.slo -*.lo -*.o -*.obj - -# Precompiled Headers -*.gch -*.pch - -# Compiled Dynamic libraries -*.so -*.dylib -*.dll - -# Fortran module files -*.mod -*.smod - -# Compiled Static libraries -*.lai -*.la -*.a -*.lib - -# Executables -*.exe -*.out -*.app - -*.db -Logs\ -Logs/ -logs/ -.DS_Store +src/unispy \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 27e6c71eb..000000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,195 +0,0 @@ -{ - // Use IntelliSense to find out which attributes exist for C# debugging - // Use hover for the description of the existing attributes - // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md - "version": "0.2.0", - "configurations": [ - { - "name": "PCM", - "type": "coreclr", - "request": "launch", - "program": "${workspaceRoot}/build/Debug/net6.0/UniSpy.Server.PresenceConnectionManager.dll", - "args": [], - "cwd": "${workspaceRoot}/build/Debug/net6.0/", - "stopAtEntry": false, - "console": "integratedTerminal", - "internalConsoleOptions": "neverOpen", - }, - { - "name": "PSP", - "type": "coreclr", - "request": "launch", - "program": "${workspaceRoot}/build/Debug/net6.0/UniSpy.Server.PresenceSearchPlayer.dll", - "args": [], - "cwd": "${workspaceRoot}/build/Debug/net6.0/", - "console": "integratedTerminal", - "internalConsoleOptions": "neverOpen", - "stopAtEntry": false - }, - { - "name": "NatNeg", - "type": "coreclr", - "request": "launch", - "program": "${workspaceRoot}/build/Debug/net6.0/UniSpy.Server.NatNegotiation.dll", - "args": [], - "cwd": "${workspaceRoot}/build/Debug/net6.0/", - "console": "integratedTerminal", - "internalConsoleOptions": "neverOpen", - "stopAtEntry": false - }, - { - "name": "GTR", - "type": "coreclr", - "request": "launch", - "program": "${workspaceRoot}/build/Debug/net6.0/UniSpy.Server.GameTrafficRelay.dll", - "args": [], - "cwd": "${workspaceRoot}/build/Debug/net6.0/", - "console": "integratedTerminal", - "internalConsoleOptions": "neverOpen", - "env": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "stopAtEntry": false - }, - { - "name": "Chat", - "type": "coreclr", - "request": "launch", - "program": "${workspaceRoot}/build/Debug/net6.0/UniSpy.Server.Chat.dll", - "args": [], - "cwd": "${workspaceRoot}/build/Debug/net6.0/", - "console": "integratedTerminal", - "internalConsoleOptions": "neverOpen", - "stopAtEntry": false - }, - { - "name": "QR", - "type": "coreclr", - "request": "launch", - "program": "${workspaceRoot}/build/Debug/net6.0/UniSpy.Server.QueryReport.dll", - "args": [], - "cwd": "${workspaceRoot}/build/Debug/net6.0/", - "console": "integratedTerminal", - "internalConsoleOptions": "neverOpen", - "stopAtEntry": false - }, - { - "name": "SB", - "type": "coreclr", - "request": "launch", - "program": "${workspaceRoot}/build/Debug/net6.0/UniSpy.Server.ServerBrowser.dll", - "args": [], - "cwd": "${workspaceRoot}/build/Debug/net6.0/", - "console": "integratedTerminal", - "internalConsoleOptions": "neverOpen", - "stopAtEntry": false - }, - { - "name": "GS", - "type": "coreclr", - "request": "launch", - "program": "${workspaceRoot}/build/Debug/net6.0/UniSpy.Server.GameStatus.dll", - "args": [], - "cwd": "${workspaceRoot}/build/Debug/net6.0/", - "console": "integratedTerminal", - "internalConsoleOptions": "neverOpen", - "stopAtEntry": false - }, - { - "name": "Web", - "type": "coreclr", - "request": "launch", - "program": "${workspaceRoot}/build/Debug/net6.0/UniSpy.Server.WebServer.dll", - "args": [], - "cwd": "${workspaceRoot}/build/Debug/net6.0/", - "console": "integratedTerminal", - "internalConsoleOptions": "neverOpen", - "stopAtEntry": false - } - ], - "compounds": [ - { - "name": "PCM, PSP", - "configurations": [ - "PCM", - "PSP" - ] - }, - { - "name": "NatNeg, GTR", - "configurations": [ - "NatNeg", - "GTR" - ] - }, - { - "name": "QR, SB, NatNeg, GTR", - "configurations": [ - "QR", - "SB", - "NatNeg", - "GTR" - ] - }, - { - "name": "GS, PSP", - "configurations": [ - "PSP", - "GS" - ] - }, - { - "name": "SAKE, PCM", - "configurations": [ - "Web", - "PCM" - ] - }, - { - "name": "Chat QR SB", - "configurations": [ - "Chat", - "QR", - "SB", - ] - }, - { - "name": "Legacy servers", - "configurations": [ - "PCM", - "PSP", - "NatNeg", - "Chat", - "QR", - "SB", - "GS" - ] - }, - { - "name": "New servers", - "configurations": [ - "PCM", - "PSP", - "NatNeg", - "Chat", - "QR", - "SB", - "Web" - ] - }, - { - "name": "All servers", - "configurations": [ - "PCM", - "PSP", - "NatNeg", - "GTR", - "Chat", - "QR", - "SB", - "GS", - "Web" - ] - } - ] -} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index 8264b4072..000000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,155 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "label": "build_library", - "command": "dotnet", - "type": "process", - "args": [ - "build", - "--no-restore", - "${workspaceFolder}/src/Libraries/Core/src/UniSpy.Server.Core.csproj", - "-o", - "${workspaceFolder}/build/Debug/net6.0/", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build_chat", - "command": "dotnet", - "type": "process", - "args": [ - "build", - "--no-restore", - "${workspaceFolder}/src/Servers/Chat/src/UniSpy.Server.Chat.csproj", - "-o", - "${workspaceFolder}/build/Debug/net6.0/", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build_pcm", - "command": "dotnet", - "type": "process", - "args": [ - "build", - "--no-restore", - "${workspaceFolder}/src/Servers/PresenceConnectionManager/src/UniSpy.Server.PresenceConnectionManager.csproj", - "-o", - "${workspaceFolder}/build/Debug/net6.0/", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build_psp", - "command": "dotnet", - "type": "process", - "args": [ - "build", - "--no-restore", - "${workspaceFolder}/src/Servers/PresenceSearchPlayer/src/UniSpy.Server.PresenceSearchPlayer.csproj", - "-o", - "${workspaceFolder}/build/Debug/net6.0/", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build_gs", - "command": "dotnet", - "type": "process", - "args": [ - "build", - "--no-restore", - "${workspaceFolder}/src/Servers/GameStatus/src/UniSpy.Server.GameStatus.csproj", - "-o", - "${workspaceFolder}/build/Debug/net6.0/", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile", - }, - { - "label": "build_gtr", - "command": "dotnet", - "type": "process", - "args": [ - "build", - "--no-restore", - "${workspaceFolder}/src/Servers/GameTrafficRelay/src/UniSpy.Server.GameTrafficRelay.csproj", - "-o", - "${workspaceFolder}/build/Debug/net6.0/", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build_natneg", - "command": "dotnet", - "type": "process", - "args": [ - "build", - "--no-restore", - "${workspaceFolder}/src/Servers/NatNegotiation/src/UniSpy.Server.NatNegotiation.csproj", - "-o", - "${workspaceFolder}/build/Debug/net6.0/", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build_qr", - "command": "dotnet", - "type": "process", - "args": [ - "build", - "--no-restore", - "${workspaceFolder}/src/Servers/QueryReport/src/UniSpy.Server.QueryReport.csproj", - "-o", - "${workspaceFolder}/build/Debug/net6.0/", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build_sb", - "command": "dotnet", - "type": "process", - "args": [ - "build", - "--no-restore", - "${workspaceFolder}/src/Servers/ServerBrowser/src/UniSpy.Server.ServerBrowser.csproj", - "-o", - "${workspaceFolder}/build/Debug/net6.0/", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "build_web", - "command": "dotnet", - "type": "process", - "args": [ - "build", - "--no-restore", - "${workspaceFolder}/src/Servers/WebServer/src/UniSpy.Server.WebServer.csproj", - "-o", - "${workspaceFolder}/build/Debug/net6.0/", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - ] -} \ No newline at end of file diff --git a/BuildUniSpyServer.bat b/BuildUniSpyServer.bat deleted file mode 100644 index 04b28e20e..000000000 --- a/BuildUniSpyServer.bat +++ /dev/null @@ -1,4 +0,0 @@ -@ECHO OFF -ECHO Building UniSpyServer! -cd %0 -dotnet build \ No newline at end of file diff --git a/BuildUniSpyServer.sh b/BuildUniSpyServer.sh deleted file mode 100755 index cf0f1fd8c..000000000 --- a/BuildUniSpyServer.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -echo "Building UniSpyServer!" -cd "$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" -dotnet build -echo "Copy UniSpyServer.cfg to build directory" -cp ./common/UniSpyServer.cfg ./build/Debug/net5.0/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..2e6031987 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +# Use the official Python image from the Docker Hub +FROM python:3.12-slim + +# Set the working directory in the container +WORKDIR /unispy-server + +# Copy the requirements file into the container +COPY src/requirements.txt . + +# Install the dependencies +RUN pip install --no-cache-dir -r requirements.txt + +RUN apt update +RUN apt install -y curl \ No newline at end of file diff --git a/UniSpy.Server.sln b/UniSpy.Server.sln deleted file mode 100644 index 3e606cd21..000000000 --- a/UniSpy.Server.sln +++ /dev/null @@ -1,393 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.32228.343 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Servers", "Servers", "{EBF19CC8-39E4-490E-8BAB-4B0C2FADAC98}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Chat", "Chat", "{BC1F1EF3-7152-4284-9EDA-AAE8825388A3}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniSpy.Server.Chat", "src\Servers\Chat\src\UniSpy.Server.Chat.csproj", "{29BDDFB0-54FA-4057-BEC5-5B3DCD1DE212}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NatNegotiation", "NatNegotiation", "{09E88199-24C9-45BC-B043-7D636D4BCDF0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniSpy.Server.NatNegotiation", "src\Servers\NatNegotiation\src\UniSpy.Server.NatNegotiation.csproj", "{8FCED8D1-D6CC-44BC-9CDA-9F0C1C786453}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GameStatus", "GameStatus", "{79343A9E-5F1A-490C-AA3F-68B1F03A8CEF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniSpy.Server.GameStatus", "src\Servers\GameStatus\src\UniSpy.Server.GameStatus.csproj", "{DCB6AB5F-4B6F-4B2D-83CB-F539DA614A5E}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PresenceConnectionManager", "PresenceConnectionManager", "{945EB98D-95C4-415B-8C00-C7682683FAA3}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniSpy.Server.PresenceConnectionManager", "src\Servers\PresenceConnectionManager\src\UniSpy.Server.PresenceConnectionManager.csproj", "{23683C7C-23E6-443C-AB41-3F28EA1B2FC0}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PresenceSearchPlayer", "PresenceSearchPlayer", "{17ABC2A8-9E3B-4CE1-AD13-A3780B0B07F0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniSpy.Server.PresenceSearchPlayer", "src\Servers\PresenceSearchPlayer\src\UniSpy.Server.PresenceSearchPlayer.csproj", "{0B1AA7F3-09C4-4D8B-AB54-D500BF0B2537}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "QueryReport", "QueryReport", "{D9FA7414-F8AB-4195-A483-474BF96467E6}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniSpy.Server.QueryReport", "src\Servers\QueryReport\src\UniSpy.Server.QueryReport.csproj", "{2EE9F419-409D-4F43-A541-BBBAD6FEDCA2}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ServerBrowser", "ServerBrowser", "{520D01A8-B487-4B27-B33A-8ACB97F57BA5}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniSpy.Server.ServerBrowser", "src\Servers\ServerBrowser\src\UniSpy.Server.ServerBrowser.csproj", "{B4049A31-CEC8-4310-957D-1FBCBBDEC413}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebServer", "WebServer", "{79E8F708-7806-4EF5-A8D9-22AE31053124}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniSpy.Server.WebServer", "src\Servers\WebServer\src\UniSpy.Server.WebServer.csproj", "{4D8EA982-3285-4637-9010-310FCA5B254A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniSpy.Server.Chat.Test", "src\Servers\Chat\test\UniSpy.Server.Chat.Test.csproj", "{D065CD06-4296-416A-B47D-274D0B5F82E9}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniSpy.Server.NatNegotiation.Test", "src\Servers\NatNegotiation\test\UniSpy.Server.NatNegotiation.Test.csproj", "{381A72E9-DD7B-45CE-BCEC-D70DC3BEAAEC}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniSpy.Server.PresenceConnectionManager.Test", "src\Servers\PresenceConnectionManager\test\UniSpy.Server.PresenceConnectionManager.Test.csproj", "{EEDF9F97-98D4-465E-B8FB-0DDAE9219F72}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniSpy.Server.PresenceSearchPlayer.Test", "src\Servers\PresenceSearchPlayer\test\UniSpy.Server.PresenceSearchPlayer.Test.csproj", "{456B57D9-E3F7-46DF-AA27-5518C7647FD1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniSpy.Server.GameStatus.Test", "src\Servers\GameStatus\test\UniSpy.Server.GameStatus.Test.csproj", "{B267E37A-96A5-418D-9A86-76C19564D205}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniSpy.Server.QueryReport.Test", "src\Servers\QueryReport\test\UniSpy.Server.QueryReport.Test.csproj", "{370CBE6A-76A2-4F49-BCD9-68FC79ED4171}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniSpy.Server.ServerBrowser.Test", "src\Servers\ServerBrowser\test\UniSpy.Server.ServerBrowser.Test.csproj", "{6017E174-2FC3-4BE9-9279-855BA7481AF3}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniSpy.Server.WebServer.Test", "src\Servers\WebServer\test\UniSpy.Server.WebServer.Test.csproj", "{E10E3BFC-F5C8-4E70-AC3C-1DC6743BD4D8}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{FD5B4D88-8BDA-4513-BBA1-9F31B9D64BB5}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniSpy.Server.Core", "src\Libraries\Core\src\UniSpy.Server.Core.csproj", "{D902FBA8-5B07-452E-9A0B-3381D49ABB9B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniSpy.LinqToRedis", "src\Libraries\LinqToRedis\src\UniSpy.LinqToRedis.csproj", "{7780907C-CABF-4CCD-9039-7C17CC7391F9}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GameTrafficRelay", "GameTrafficRelay", "{EF1CA185-B3C8-4F0A-B134-1114CB51E97D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniSpy.Server.GameTrafficRelay", "src\Servers\GameTrafficRelay\src\UniSpy.Server.GameTrafficRelay.csproj", "{555A87B1-5FFE-4F24-B665-160693901D25}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UniSpy.Server.GameTrafficRelay.Test", "src\Servers\GameTrafficRelay\test\UniSpy.Server.GameTrafficRelay.Test.csproj", "{FD4B4018-7283-41DB-AC57-AB62760269FB}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B46172F1-8E97-4934-9969-3957B9129736}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{8B1B77AA-ED59-4B6F-8926-A65AAF28A713}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LinqToRedis", "LinqToRedis", "{98525275-1CA4-421F-AF18-12E906536814}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniSpy.Server.Test", "src\test\UniSpy.Server.Test.csproj", "{8A98B2B8-92E6-4649-92D7-77FB11E3C9C8}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Servers", "Servers", "{3E629C69-B021-4899-9A61-C3696310706D}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {29BDDFB0-54FA-4057-BEC5-5B3DCD1DE212}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {29BDDFB0-54FA-4057-BEC5-5B3DCD1DE212}.Debug|Any CPU.Build.0 = Debug|Any CPU - {29BDDFB0-54FA-4057-BEC5-5B3DCD1DE212}.Debug|x64.ActiveCfg = Debug|Any CPU - {29BDDFB0-54FA-4057-BEC5-5B3DCD1DE212}.Debug|x64.Build.0 = Debug|Any CPU - {29BDDFB0-54FA-4057-BEC5-5B3DCD1DE212}.Debug|x86.ActiveCfg = Debug|Any CPU - {29BDDFB0-54FA-4057-BEC5-5B3DCD1DE212}.Debug|x86.Build.0 = Debug|Any CPU - {29BDDFB0-54FA-4057-BEC5-5B3DCD1DE212}.Release|Any CPU.ActiveCfg = Release|Any CPU - {29BDDFB0-54FA-4057-BEC5-5B3DCD1DE212}.Release|Any CPU.Build.0 = Release|Any CPU - {29BDDFB0-54FA-4057-BEC5-5B3DCD1DE212}.Release|x64.ActiveCfg = Release|Any CPU - {29BDDFB0-54FA-4057-BEC5-5B3DCD1DE212}.Release|x64.Build.0 = Release|Any CPU - {29BDDFB0-54FA-4057-BEC5-5B3DCD1DE212}.Release|x86.ActiveCfg = Release|Any CPU - {29BDDFB0-54FA-4057-BEC5-5B3DCD1DE212}.Release|x86.Build.0 = Release|Any CPU - {8FCED8D1-D6CC-44BC-9CDA-9F0C1C786453}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8FCED8D1-D6CC-44BC-9CDA-9F0C1C786453}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8FCED8D1-D6CC-44BC-9CDA-9F0C1C786453}.Debug|x64.ActiveCfg = Debug|Any CPU - {8FCED8D1-D6CC-44BC-9CDA-9F0C1C786453}.Debug|x64.Build.0 = Debug|Any CPU - {8FCED8D1-D6CC-44BC-9CDA-9F0C1C786453}.Debug|x86.ActiveCfg = Debug|Any CPU - {8FCED8D1-D6CC-44BC-9CDA-9F0C1C786453}.Debug|x86.Build.0 = Debug|Any CPU - {8FCED8D1-D6CC-44BC-9CDA-9F0C1C786453}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8FCED8D1-D6CC-44BC-9CDA-9F0C1C786453}.Release|Any CPU.Build.0 = Release|Any CPU - {8FCED8D1-D6CC-44BC-9CDA-9F0C1C786453}.Release|x64.ActiveCfg = Release|Any CPU - {8FCED8D1-D6CC-44BC-9CDA-9F0C1C786453}.Release|x64.Build.0 = Release|Any CPU - {8FCED8D1-D6CC-44BC-9CDA-9F0C1C786453}.Release|x86.ActiveCfg = Release|Any CPU - {8FCED8D1-D6CC-44BC-9CDA-9F0C1C786453}.Release|x86.Build.0 = Release|Any CPU - {DCB6AB5F-4B6F-4B2D-83CB-F539DA614A5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DCB6AB5F-4B6F-4B2D-83CB-F539DA614A5E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DCB6AB5F-4B6F-4B2D-83CB-F539DA614A5E}.Debug|x64.ActiveCfg = Debug|Any CPU - {DCB6AB5F-4B6F-4B2D-83CB-F539DA614A5E}.Debug|x64.Build.0 = Debug|Any CPU - {DCB6AB5F-4B6F-4B2D-83CB-F539DA614A5E}.Debug|x86.ActiveCfg = Debug|Any CPU - {DCB6AB5F-4B6F-4B2D-83CB-F539DA614A5E}.Debug|x86.Build.0 = Debug|Any CPU - {DCB6AB5F-4B6F-4B2D-83CB-F539DA614A5E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DCB6AB5F-4B6F-4B2D-83CB-F539DA614A5E}.Release|Any CPU.Build.0 = Release|Any CPU - {DCB6AB5F-4B6F-4B2D-83CB-F539DA614A5E}.Release|x64.ActiveCfg = Release|Any CPU - {DCB6AB5F-4B6F-4B2D-83CB-F539DA614A5E}.Release|x64.Build.0 = Release|Any CPU - {DCB6AB5F-4B6F-4B2D-83CB-F539DA614A5E}.Release|x86.ActiveCfg = Release|Any CPU - {DCB6AB5F-4B6F-4B2D-83CB-F539DA614A5E}.Release|x86.Build.0 = Release|Any CPU - {23683C7C-23E6-443C-AB41-3F28EA1B2FC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {23683C7C-23E6-443C-AB41-3F28EA1B2FC0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {23683C7C-23E6-443C-AB41-3F28EA1B2FC0}.Debug|x64.ActiveCfg = Debug|Any CPU - {23683C7C-23E6-443C-AB41-3F28EA1B2FC0}.Debug|x64.Build.0 = Debug|Any CPU - {23683C7C-23E6-443C-AB41-3F28EA1B2FC0}.Debug|x86.ActiveCfg = Debug|Any CPU - {23683C7C-23E6-443C-AB41-3F28EA1B2FC0}.Debug|x86.Build.0 = Debug|Any CPU - {23683C7C-23E6-443C-AB41-3F28EA1B2FC0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {23683C7C-23E6-443C-AB41-3F28EA1B2FC0}.Release|Any CPU.Build.0 = Release|Any CPU - {23683C7C-23E6-443C-AB41-3F28EA1B2FC0}.Release|x64.ActiveCfg = Release|Any CPU - {23683C7C-23E6-443C-AB41-3F28EA1B2FC0}.Release|x64.Build.0 = Release|Any CPU - {23683C7C-23E6-443C-AB41-3F28EA1B2FC0}.Release|x86.ActiveCfg = Release|Any CPU - {23683C7C-23E6-443C-AB41-3F28EA1B2FC0}.Release|x86.Build.0 = Release|Any CPU - {0B1AA7F3-09C4-4D8B-AB54-D500BF0B2537}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0B1AA7F3-09C4-4D8B-AB54-D500BF0B2537}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0B1AA7F3-09C4-4D8B-AB54-D500BF0B2537}.Debug|x64.ActiveCfg = Debug|Any CPU - {0B1AA7F3-09C4-4D8B-AB54-D500BF0B2537}.Debug|x64.Build.0 = Debug|Any CPU - {0B1AA7F3-09C4-4D8B-AB54-D500BF0B2537}.Debug|x86.ActiveCfg = Debug|Any CPU - {0B1AA7F3-09C4-4D8B-AB54-D500BF0B2537}.Debug|x86.Build.0 = Debug|Any CPU - {0B1AA7F3-09C4-4D8B-AB54-D500BF0B2537}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0B1AA7F3-09C4-4D8B-AB54-D500BF0B2537}.Release|Any CPU.Build.0 = Release|Any CPU - {0B1AA7F3-09C4-4D8B-AB54-D500BF0B2537}.Release|x64.ActiveCfg = Release|Any CPU - {0B1AA7F3-09C4-4D8B-AB54-D500BF0B2537}.Release|x64.Build.0 = Release|Any CPU - {0B1AA7F3-09C4-4D8B-AB54-D500BF0B2537}.Release|x86.ActiveCfg = Release|Any CPU - {0B1AA7F3-09C4-4D8B-AB54-D500BF0B2537}.Release|x86.Build.0 = Release|Any CPU - {2EE9F419-409D-4F43-A541-BBBAD6FEDCA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2EE9F419-409D-4F43-A541-BBBAD6FEDCA2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2EE9F419-409D-4F43-A541-BBBAD6FEDCA2}.Debug|x64.ActiveCfg = Debug|Any CPU - {2EE9F419-409D-4F43-A541-BBBAD6FEDCA2}.Debug|x64.Build.0 = Debug|Any CPU - {2EE9F419-409D-4F43-A541-BBBAD6FEDCA2}.Debug|x86.ActiveCfg = Debug|Any CPU - {2EE9F419-409D-4F43-A541-BBBAD6FEDCA2}.Debug|x86.Build.0 = Debug|Any CPU - {2EE9F419-409D-4F43-A541-BBBAD6FEDCA2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2EE9F419-409D-4F43-A541-BBBAD6FEDCA2}.Release|Any CPU.Build.0 = Release|Any CPU - {2EE9F419-409D-4F43-A541-BBBAD6FEDCA2}.Release|x64.ActiveCfg = Release|Any CPU - {2EE9F419-409D-4F43-A541-BBBAD6FEDCA2}.Release|x64.Build.0 = Release|Any CPU - {2EE9F419-409D-4F43-A541-BBBAD6FEDCA2}.Release|x86.ActiveCfg = Release|Any CPU - {2EE9F419-409D-4F43-A541-BBBAD6FEDCA2}.Release|x86.Build.0 = Release|Any CPU - {B4049A31-CEC8-4310-957D-1FBCBBDEC413}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B4049A31-CEC8-4310-957D-1FBCBBDEC413}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B4049A31-CEC8-4310-957D-1FBCBBDEC413}.Debug|x64.ActiveCfg = Debug|Any CPU - {B4049A31-CEC8-4310-957D-1FBCBBDEC413}.Debug|x64.Build.0 = Debug|Any CPU - {B4049A31-CEC8-4310-957D-1FBCBBDEC413}.Debug|x86.ActiveCfg = Debug|Any CPU - {B4049A31-CEC8-4310-957D-1FBCBBDEC413}.Debug|x86.Build.0 = Debug|Any CPU - {B4049A31-CEC8-4310-957D-1FBCBBDEC413}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B4049A31-CEC8-4310-957D-1FBCBBDEC413}.Release|Any CPU.Build.0 = Release|Any CPU - {B4049A31-CEC8-4310-957D-1FBCBBDEC413}.Release|x64.ActiveCfg = Release|Any CPU - {B4049A31-CEC8-4310-957D-1FBCBBDEC413}.Release|x64.Build.0 = Release|Any CPU - {B4049A31-CEC8-4310-957D-1FBCBBDEC413}.Release|x86.ActiveCfg = Release|Any CPU - {B4049A31-CEC8-4310-957D-1FBCBBDEC413}.Release|x86.Build.0 = Release|Any CPU - {4D8EA982-3285-4637-9010-310FCA5B254A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4D8EA982-3285-4637-9010-310FCA5B254A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4D8EA982-3285-4637-9010-310FCA5B254A}.Debug|x64.ActiveCfg = Debug|Any CPU - {4D8EA982-3285-4637-9010-310FCA5B254A}.Debug|x64.Build.0 = Debug|Any CPU - {4D8EA982-3285-4637-9010-310FCA5B254A}.Debug|x86.ActiveCfg = Debug|Any CPU - {4D8EA982-3285-4637-9010-310FCA5B254A}.Debug|x86.Build.0 = Debug|Any CPU - {4D8EA982-3285-4637-9010-310FCA5B254A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4D8EA982-3285-4637-9010-310FCA5B254A}.Release|Any CPU.Build.0 = Release|Any CPU - {4D8EA982-3285-4637-9010-310FCA5B254A}.Release|x64.ActiveCfg = Release|Any CPU - {4D8EA982-3285-4637-9010-310FCA5B254A}.Release|x64.Build.0 = Release|Any CPU - {4D8EA982-3285-4637-9010-310FCA5B254A}.Release|x86.ActiveCfg = Release|Any CPU - {4D8EA982-3285-4637-9010-310FCA5B254A}.Release|x86.Build.0 = Release|Any CPU - {D065CD06-4296-416A-B47D-274D0B5F82E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D065CD06-4296-416A-B47D-274D0B5F82E9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D065CD06-4296-416A-B47D-274D0B5F82E9}.Debug|x64.ActiveCfg = Debug|Any CPU - {D065CD06-4296-416A-B47D-274D0B5F82E9}.Debug|x64.Build.0 = Debug|Any CPU - {D065CD06-4296-416A-B47D-274D0B5F82E9}.Debug|x86.ActiveCfg = Debug|Any CPU - {D065CD06-4296-416A-B47D-274D0B5F82E9}.Debug|x86.Build.0 = Debug|Any CPU - {D065CD06-4296-416A-B47D-274D0B5F82E9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D065CD06-4296-416A-B47D-274D0B5F82E9}.Release|Any CPU.Build.0 = Release|Any CPU - {D065CD06-4296-416A-B47D-274D0B5F82E9}.Release|x64.ActiveCfg = Release|Any CPU - {D065CD06-4296-416A-B47D-274D0B5F82E9}.Release|x64.Build.0 = Release|Any CPU - {D065CD06-4296-416A-B47D-274D0B5F82E9}.Release|x86.ActiveCfg = Release|Any CPU - {D065CD06-4296-416A-B47D-274D0B5F82E9}.Release|x86.Build.0 = Release|Any CPU - {381A72E9-DD7B-45CE-BCEC-D70DC3BEAAEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {381A72E9-DD7B-45CE-BCEC-D70DC3BEAAEC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {381A72E9-DD7B-45CE-BCEC-D70DC3BEAAEC}.Debug|x64.ActiveCfg = Debug|Any CPU - {381A72E9-DD7B-45CE-BCEC-D70DC3BEAAEC}.Debug|x64.Build.0 = Debug|Any CPU - {381A72E9-DD7B-45CE-BCEC-D70DC3BEAAEC}.Debug|x86.ActiveCfg = Debug|Any CPU - {381A72E9-DD7B-45CE-BCEC-D70DC3BEAAEC}.Debug|x86.Build.0 = Debug|Any CPU - {381A72E9-DD7B-45CE-BCEC-D70DC3BEAAEC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {381A72E9-DD7B-45CE-BCEC-D70DC3BEAAEC}.Release|Any CPU.Build.0 = Release|Any CPU - {381A72E9-DD7B-45CE-BCEC-D70DC3BEAAEC}.Release|x64.ActiveCfg = Release|Any CPU - {381A72E9-DD7B-45CE-BCEC-D70DC3BEAAEC}.Release|x64.Build.0 = Release|Any CPU - {381A72E9-DD7B-45CE-BCEC-D70DC3BEAAEC}.Release|x86.ActiveCfg = Release|Any CPU - {381A72E9-DD7B-45CE-BCEC-D70DC3BEAAEC}.Release|x86.Build.0 = Release|Any CPU - {EEDF9F97-98D4-465E-B8FB-0DDAE9219F72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EEDF9F97-98D4-465E-B8FB-0DDAE9219F72}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EEDF9F97-98D4-465E-B8FB-0DDAE9219F72}.Debug|x64.ActiveCfg = Debug|Any CPU - {EEDF9F97-98D4-465E-B8FB-0DDAE9219F72}.Debug|x64.Build.0 = Debug|Any CPU - {EEDF9F97-98D4-465E-B8FB-0DDAE9219F72}.Debug|x86.ActiveCfg = Debug|Any CPU - {EEDF9F97-98D4-465E-B8FB-0DDAE9219F72}.Debug|x86.Build.0 = Debug|Any CPU - {EEDF9F97-98D4-465E-B8FB-0DDAE9219F72}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EEDF9F97-98D4-465E-B8FB-0DDAE9219F72}.Release|Any CPU.Build.0 = Release|Any CPU - {EEDF9F97-98D4-465E-B8FB-0DDAE9219F72}.Release|x64.ActiveCfg = Release|Any CPU - {EEDF9F97-98D4-465E-B8FB-0DDAE9219F72}.Release|x64.Build.0 = Release|Any CPU - {EEDF9F97-98D4-465E-B8FB-0DDAE9219F72}.Release|x86.ActiveCfg = Release|Any CPU - {EEDF9F97-98D4-465E-B8FB-0DDAE9219F72}.Release|x86.Build.0 = Release|Any CPU - {456B57D9-E3F7-46DF-AA27-5518C7647FD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {456B57D9-E3F7-46DF-AA27-5518C7647FD1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {456B57D9-E3F7-46DF-AA27-5518C7647FD1}.Debug|x64.ActiveCfg = Debug|Any CPU - {456B57D9-E3F7-46DF-AA27-5518C7647FD1}.Debug|x64.Build.0 = Debug|Any CPU - {456B57D9-E3F7-46DF-AA27-5518C7647FD1}.Debug|x86.ActiveCfg = Debug|Any CPU - {456B57D9-E3F7-46DF-AA27-5518C7647FD1}.Debug|x86.Build.0 = Debug|Any CPU - {456B57D9-E3F7-46DF-AA27-5518C7647FD1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {456B57D9-E3F7-46DF-AA27-5518C7647FD1}.Release|Any CPU.Build.0 = Release|Any CPU - {456B57D9-E3F7-46DF-AA27-5518C7647FD1}.Release|x64.ActiveCfg = Release|Any CPU - {456B57D9-E3F7-46DF-AA27-5518C7647FD1}.Release|x64.Build.0 = Release|Any CPU - {456B57D9-E3F7-46DF-AA27-5518C7647FD1}.Release|x86.ActiveCfg = Release|Any CPU - {456B57D9-E3F7-46DF-AA27-5518C7647FD1}.Release|x86.Build.0 = Release|Any CPU - {B267E37A-96A5-418D-9A86-76C19564D205}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B267E37A-96A5-418D-9A86-76C19564D205}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B267E37A-96A5-418D-9A86-76C19564D205}.Debug|x64.ActiveCfg = Debug|Any CPU - {B267E37A-96A5-418D-9A86-76C19564D205}.Debug|x64.Build.0 = Debug|Any CPU - {B267E37A-96A5-418D-9A86-76C19564D205}.Debug|x86.ActiveCfg = Debug|Any CPU - {B267E37A-96A5-418D-9A86-76C19564D205}.Debug|x86.Build.0 = Debug|Any CPU - {B267E37A-96A5-418D-9A86-76C19564D205}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B267E37A-96A5-418D-9A86-76C19564D205}.Release|Any CPU.Build.0 = Release|Any CPU - {B267E37A-96A5-418D-9A86-76C19564D205}.Release|x64.ActiveCfg = Release|Any CPU - {B267E37A-96A5-418D-9A86-76C19564D205}.Release|x64.Build.0 = Release|Any CPU - {B267E37A-96A5-418D-9A86-76C19564D205}.Release|x86.ActiveCfg = Release|Any CPU - {B267E37A-96A5-418D-9A86-76C19564D205}.Release|x86.Build.0 = Release|Any CPU - {370CBE6A-76A2-4F49-BCD9-68FC79ED4171}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {370CBE6A-76A2-4F49-BCD9-68FC79ED4171}.Debug|Any CPU.Build.0 = Debug|Any CPU - {370CBE6A-76A2-4F49-BCD9-68FC79ED4171}.Debug|x64.ActiveCfg = Debug|Any CPU - {370CBE6A-76A2-4F49-BCD9-68FC79ED4171}.Debug|x64.Build.0 = Debug|Any CPU - {370CBE6A-76A2-4F49-BCD9-68FC79ED4171}.Debug|x86.ActiveCfg = Debug|Any CPU - {370CBE6A-76A2-4F49-BCD9-68FC79ED4171}.Debug|x86.Build.0 = Debug|Any CPU - {370CBE6A-76A2-4F49-BCD9-68FC79ED4171}.Release|Any CPU.ActiveCfg = Release|Any CPU - {370CBE6A-76A2-4F49-BCD9-68FC79ED4171}.Release|Any CPU.Build.0 = Release|Any CPU - {370CBE6A-76A2-4F49-BCD9-68FC79ED4171}.Release|x64.ActiveCfg = Release|Any CPU - {370CBE6A-76A2-4F49-BCD9-68FC79ED4171}.Release|x64.Build.0 = Release|Any CPU - {370CBE6A-76A2-4F49-BCD9-68FC79ED4171}.Release|x86.ActiveCfg = Release|Any CPU - {370CBE6A-76A2-4F49-BCD9-68FC79ED4171}.Release|x86.Build.0 = Release|Any CPU - {6017E174-2FC3-4BE9-9279-855BA7481AF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6017E174-2FC3-4BE9-9279-855BA7481AF3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6017E174-2FC3-4BE9-9279-855BA7481AF3}.Debug|x64.ActiveCfg = Debug|Any CPU - {6017E174-2FC3-4BE9-9279-855BA7481AF3}.Debug|x64.Build.0 = Debug|Any CPU - {6017E174-2FC3-4BE9-9279-855BA7481AF3}.Debug|x86.ActiveCfg = Debug|Any CPU - {6017E174-2FC3-4BE9-9279-855BA7481AF3}.Debug|x86.Build.0 = Debug|Any CPU - {6017E174-2FC3-4BE9-9279-855BA7481AF3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6017E174-2FC3-4BE9-9279-855BA7481AF3}.Release|Any CPU.Build.0 = Release|Any CPU - {6017E174-2FC3-4BE9-9279-855BA7481AF3}.Release|x64.ActiveCfg = Release|Any CPU - {6017E174-2FC3-4BE9-9279-855BA7481AF3}.Release|x64.Build.0 = Release|Any CPU - {6017E174-2FC3-4BE9-9279-855BA7481AF3}.Release|x86.ActiveCfg = Release|Any CPU - {6017E174-2FC3-4BE9-9279-855BA7481AF3}.Release|x86.Build.0 = Release|Any CPU - {E10E3BFC-F5C8-4E70-AC3C-1DC6743BD4D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E10E3BFC-F5C8-4E70-AC3C-1DC6743BD4D8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E10E3BFC-F5C8-4E70-AC3C-1DC6743BD4D8}.Debug|x64.ActiveCfg = Debug|Any CPU - {E10E3BFC-F5C8-4E70-AC3C-1DC6743BD4D8}.Debug|x64.Build.0 = Debug|Any CPU - {E10E3BFC-F5C8-4E70-AC3C-1DC6743BD4D8}.Debug|x86.ActiveCfg = Debug|Any CPU - {E10E3BFC-F5C8-4E70-AC3C-1DC6743BD4D8}.Debug|x86.Build.0 = Debug|Any CPU - {E10E3BFC-F5C8-4E70-AC3C-1DC6743BD4D8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E10E3BFC-F5C8-4E70-AC3C-1DC6743BD4D8}.Release|Any CPU.Build.0 = Release|Any CPU - {E10E3BFC-F5C8-4E70-AC3C-1DC6743BD4D8}.Release|x64.ActiveCfg = Release|Any CPU - {E10E3BFC-F5C8-4E70-AC3C-1DC6743BD4D8}.Release|x64.Build.0 = Release|Any CPU - {E10E3BFC-F5C8-4E70-AC3C-1DC6743BD4D8}.Release|x86.ActiveCfg = Release|Any CPU - {E10E3BFC-F5C8-4E70-AC3C-1DC6743BD4D8}.Release|x86.Build.0 = Release|Any CPU - {D902FBA8-5B07-452E-9A0B-3381D49ABB9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D902FBA8-5B07-452E-9A0B-3381D49ABB9B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D902FBA8-5B07-452E-9A0B-3381D49ABB9B}.Debug|x64.ActiveCfg = Debug|Any CPU - {D902FBA8-5B07-452E-9A0B-3381D49ABB9B}.Debug|x64.Build.0 = Debug|Any CPU - {D902FBA8-5B07-452E-9A0B-3381D49ABB9B}.Debug|x86.ActiveCfg = Debug|Any CPU - {D902FBA8-5B07-452E-9A0B-3381D49ABB9B}.Debug|x86.Build.0 = Debug|Any CPU - {D902FBA8-5B07-452E-9A0B-3381D49ABB9B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D902FBA8-5B07-452E-9A0B-3381D49ABB9B}.Release|Any CPU.Build.0 = Release|Any CPU - {D902FBA8-5B07-452E-9A0B-3381D49ABB9B}.Release|x64.ActiveCfg = Release|Any CPU - {D902FBA8-5B07-452E-9A0B-3381D49ABB9B}.Release|x64.Build.0 = Release|Any CPU - {D902FBA8-5B07-452E-9A0B-3381D49ABB9B}.Release|x86.ActiveCfg = Release|Any CPU - {D902FBA8-5B07-452E-9A0B-3381D49ABB9B}.Release|x86.Build.0 = Release|Any CPU - {7780907C-CABF-4CCD-9039-7C17CC7391F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7780907C-CABF-4CCD-9039-7C17CC7391F9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7780907C-CABF-4CCD-9039-7C17CC7391F9}.Debug|x64.ActiveCfg = Debug|Any CPU - {7780907C-CABF-4CCD-9039-7C17CC7391F9}.Debug|x64.Build.0 = Debug|Any CPU - {7780907C-CABF-4CCD-9039-7C17CC7391F9}.Debug|x86.ActiveCfg = Debug|Any CPU - {7780907C-CABF-4CCD-9039-7C17CC7391F9}.Debug|x86.Build.0 = Debug|Any CPU - {7780907C-CABF-4CCD-9039-7C17CC7391F9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7780907C-CABF-4CCD-9039-7C17CC7391F9}.Release|Any CPU.Build.0 = Release|Any CPU - {7780907C-CABF-4CCD-9039-7C17CC7391F9}.Release|x64.ActiveCfg = Release|Any CPU - {7780907C-CABF-4CCD-9039-7C17CC7391F9}.Release|x64.Build.0 = Release|Any CPU - {7780907C-CABF-4CCD-9039-7C17CC7391F9}.Release|x86.ActiveCfg = Release|Any CPU - {7780907C-CABF-4CCD-9039-7C17CC7391F9}.Release|x86.Build.0 = Release|Any CPU - {555A87B1-5FFE-4F24-B665-160693901D25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {555A87B1-5FFE-4F24-B665-160693901D25}.Debug|Any CPU.Build.0 = Debug|Any CPU - {555A87B1-5FFE-4F24-B665-160693901D25}.Debug|x64.ActiveCfg = Debug|Any CPU - {555A87B1-5FFE-4F24-B665-160693901D25}.Debug|x64.Build.0 = Debug|Any CPU - {555A87B1-5FFE-4F24-B665-160693901D25}.Debug|x86.ActiveCfg = Debug|Any CPU - {555A87B1-5FFE-4F24-B665-160693901D25}.Debug|x86.Build.0 = Debug|Any CPU - {555A87B1-5FFE-4F24-B665-160693901D25}.Release|Any CPU.ActiveCfg = Release|Any CPU - {555A87B1-5FFE-4F24-B665-160693901D25}.Release|Any CPU.Build.0 = Release|Any CPU - {555A87B1-5FFE-4F24-B665-160693901D25}.Release|x64.ActiveCfg = Release|Any CPU - {555A87B1-5FFE-4F24-B665-160693901D25}.Release|x64.Build.0 = Release|Any CPU - {555A87B1-5FFE-4F24-B665-160693901D25}.Release|x86.ActiveCfg = Release|Any CPU - {555A87B1-5FFE-4F24-B665-160693901D25}.Release|x86.Build.0 = Release|Any CPU - {FD4B4018-7283-41DB-AC57-AB62760269FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FD4B4018-7283-41DB-AC57-AB62760269FB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FD4B4018-7283-41DB-AC57-AB62760269FB}.Debug|x64.ActiveCfg = Debug|Any CPU - {FD4B4018-7283-41DB-AC57-AB62760269FB}.Debug|x64.Build.0 = Debug|Any CPU - {FD4B4018-7283-41DB-AC57-AB62760269FB}.Debug|x86.ActiveCfg = Debug|Any CPU - {FD4B4018-7283-41DB-AC57-AB62760269FB}.Debug|x86.Build.0 = Debug|Any CPU - {FD4B4018-7283-41DB-AC57-AB62760269FB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FD4B4018-7283-41DB-AC57-AB62760269FB}.Release|Any CPU.Build.0 = Release|Any CPU - {FD4B4018-7283-41DB-AC57-AB62760269FB}.Release|x64.ActiveCfg = Release|Any CPU - {FD4B4018-7283-41DB-AC57-AB62760269FB}.Release|x64.Build.0 = Release|Any CPU - {FD4B4018-7283-41DB-AC57-AB62760269FB}.Release|x86.ActiveCfg = Release|Any CPU - {FD4B4018-7283-41DB-AC57-AB62760269FB}.Release|x86.Build.0 = Release|Any CPU - {8A98B2B8-92E6-4649-92D7-77FB11E3C9C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8A98B2B8-92E6-4649-92D7-77FB11E3C9C8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8A98B2B8-92E6-4649-92D7-77FB11E3C9C8}.Debug|x64.ActiveCfg = Debug|Any CPU - {8A98B2B8-92E6-4649-92D7-77FB11E3C9C8}.Debug|x64.Build.0 = Debug|Any CPU - {8A98B2B8-92E6-4649-92D7-77FB11E3C9C8}.Debug|x86.ActiveCfg = Debug|Any CPU - {8A98B2B8-92E6-4649-92D7-77FB11E3C9C8}.Debug|x86.Build.0 = Debug|Any CPU - {8A98B2B8-92E6-4649-92D7-77FB11E3C9C8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8A98B2B8-92E6-4649-92D7-77FB11E3C9C8}.Release|Any CPU.Build.0 = Release|Any CPU - {8A98B2B8-92E6-4649-92D7-77FB11E3C9C8}.Release|x64.ActiveCfg = Release|Any CPU - {8A98B2B8-92E6-4649-92D7-77FB11E3C9C8}.Release|x64.Build.0 = Release|Any CPU - {8A98B2B8-92E6-4649-92D7-77FB11E3C9C8}.Release|x86.ActiveCfg = Release|Any CPU - {8A98B2B8-92E6-4649-92D7-77FB11E3C9C8}.Release|x86.Build.0 = Release|Any CPU - {9F027E40-426C-4059-8269-16FDA79B56A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9F027E40-426C-4059-8269-16FDA79B56A8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9F027E40-426C-4059-8269-16FDA79B56A8}.Debug|x64.ActiveCfg = Debug|Any CPU - {9F027E40-426C-4059-8269-16FDA79B56A8}.Debug|x64.Build.0 = Debug|Any CPU - {9F027E40-426C-4059-8269-16FDA79B56A8}.Debug|x86.ActiveCfg = Debug|Any CPU - {9F027E40-426C-4059-8269-16FDA79B56A8}.Debug|x86.Build.0 = Debug|Any CPU - {9F027E40-426C-4059-8269-16FDA79B56A8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9F027E40-426C-4059-8269-16FDA79B56A8}.Release|Any CPU.Build.0 = Release|Any CPU - {9F027E40-426C-4059-8269-16FDA79B56A8}.Release|x64.ActiveCfg = Release|Any CPU - {9F027E40-426C-4059-8269-16FDA79B56A8}.Release|x64.Build.0 = Release|Any CPU - {9F027E40-426C-4059-8269-16FDA79B56A8}.Release|x86.ActiveCfg = Release|Any CPU - {9F027E40-426C-4059-8269-16FDA79B56A8}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {BC1F1EF3-7152-4284-9EDA-AAE8825388A3} = {EBF19CC8-39E4-490E-8BAB-4B0C2FADAC98} - {29BDDFB0-54FA-4057-BEC5-5B3DCD1DE212} = {BC1F1EF3-7152-4284-9EDA-AAE8825388A3} - {09E88199-24C9-45BC-B043-7D636D4BCDF0} = {EBF19CC8-39E4-490E-8BAB-4B0C2FADAC98} - {8FCED8D1-D6CC-44BC-9CDA-9F0C1C786453} = {09E88199-24C9-45BC-B043-7D636D4BCDF0} - {79343A9E-5F1A-490C-AA3F-68B1F03A8CEF} = {EBF19CC8-39E4-490E-8BAB-4B0C2FADAC98} - {DCB6AB5F-4B6F-4B2D-83CB-F539DA614A5E} = {79343A9E-5F1A-490C-AA3F-68B1F03A8CEF} - {945EB98D-95C4-415B-8C00-C7682683FAA3} = {EBF19CC8-39E4-490E-8BAB-4B0C2FADAC98} - {23683C7C-23E6-443C-AB41-3F28EA1B2FC0} = {945EB98D-95C4-415B-8C00-C7682683FAA3} - {17ABC2A8-9E3B-4CE1-AD13-A3780B0B07F0} = {EBF19CC8-39E4-490E-8BAB-4B0C2FADAC98} - {0B1AA7F3-09C4-4D8B-AB54-D500BF0B2537} = {17ABC2A8-9E3B-4CE1-AD13-A3780B0B07F0} - {D9FA7414-F8AB-4195-A483-474BF96467E6} = {EBF19CC8-39E4-490E-8BAB-4B0C2FADAC98} - {2EE9F419-409D-4F43-A541-BBBAD6FEDCA2} = {D9FA7414-F8AB-4195-A483-474BF96467E6} - {520D01A8-B487-4B27-B33A-8ACB97F57BA5} = {EBF19CC8-39E4-490E-8BAB-4B0C2FADAC98} - {B4049A31-CEC8-4310-957D-1FBCBBDEC413} = {520D01A8-B487-4B27-B33A-8ACB97F57BA5} - {79E8F708-7806-4EF5-A8D9-22AE31053124} = {EBF19CC8-39E4-490E-8BAB-4B0C2FADAC98} - {4D8EA982-3285-4637-9010-310FCA5B254A} = {79E8F708-7806-4EF5-A8D9-22AE31053124} - {D065CD06-4296-416A-B47D-274D0B5F82E9} = {BC1F1EF3-7152-4284-9EDA-AAE8825388A3} - {381A72E9-DD7B-45CE-BCEC-D70DC3BEAAEC} = {09E88199-24C9-45BC-B043-7D636D4BCDF0} - {EEDF9F97-98D4-465E-B8FB-0DDAE9219F72} = {945EB98D-95C4-415B-8C00-C7682683FAA3} - {456B57D9-E3F7-46DF-AA27-5518C7647FD1} = {17ABC2A8-9E3B-4CE1-AD13-A3780B0B07F0} - {B267E37A-96A5-418D-9A86-76C19564D205} = {79343A9E-5F1A-490C-AA3F-68B1F03A8CEF} - {370CBE6A-76A2-4F49-BCD9-68FC79ED4171} = {D9FA7414-F8AB-4195-A483-474BF96467E6} - {6017E174-2FC3-4BE9-9279-855BA7481AF3} = {520D01A8-B487-4B27-B33A-8ACB97F57BA5} - {E10E3BFC-F5C8-4E70-AC3C-1DC6743BD4D8} = {79E8F708-7806-4EF5-A8D9-22AE31053124} - {D902FBA8-5B07-452E-9A0B-3381D49ABB9B} = {FD5B4D88-8BDA-4513-BBA1-9F31B9D64BB5} - {7780907C-CABF-4CCD-9039-7C17CC7391F9} = {FD5B4D88-8BDA-4513-BBA1-9F31B9D64BB5} - {EF1CA185-B3C8-4F0A-B134-1114CB51E97D} = {EBF19CC8-39E4-490E-8BAB-4B0C2FADAC98} - {555A87B1-5FFE-4F24-B665-160693901D25} = {EF1CA185-B3C8-4F0A-B134-1114CB51E97D} - {FD4B4018-7283-41DB-AC57-AB62760269FB} = {EF1CA185-B3C8-4F0A-B134-1114CB51E97D} - {8B1B77AA-ED59-4B6F-8926-A65AAF28A713} = {B46172F1-8E97-4934-9969-3957B9129736} - {8A98B2B8-92E6-4649-92D7-77FB11E3C9C8} = {B46172F1-8E97-4934-9969-3957B9129736} - {3E629C69-B021-4899-9A61-C3696310706D} = {B46172F1-8E97-4934-9969-3957B9129736} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {CE7AD0FF-F1D1-4E34-8DE8-FBB2E63AA49F} - EndGlobalSection -EndGlobal diff --git a/common/DatabaseModelGenerator/GenerateDatabaseModelLinux.sh b/common/DatabaseModelGenerator/GenerateDatabaseModelLinux.sh deleted file mode 100644 index e98983480..000000000 --- a/common/DatabaseModelGenerator/GenerateDatabaseModelLinux.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -echo "Creating projects" -dotnet new console -echo "Installing ef core" -dotnet tool install --global dotnet-ef -echo "Adding required packages" -dotnet add package Microsoft.EntityFrameworkCore.Design -dotnet add package Pomelo.EntityFrameworkCore.MySql -echo "Generating database models" -dotnet ef dbcontext scaffold "Server=localhost;Port=3306;database=unispy;User=unispy;Password=;TreatTinyAsBoolean=true;" "Pomelo.EntityFrameworkCore.MySql" -v --output-dir ../../src/Libraries/UniSpyLib/Database/DatabaseModel/MySql \ No newline at end of file diff --git a/common/DatabaseModelGenerator/GenerateDatabaseModelWindows.bat b/common/DatabaseModelGenerator/GenerateDatabaseModelWindows.bat deleted file mode 100644 index a3357a29d..000000000 --- a/common/DatabaseModelGenerator/GenerateDatabaseModelWindows.bat +++ /dev/null @@ -1,5 +0,0 @@ -echo Installing ef core. -dotnet tool install --global dotnet-ef -echo Generating database models. -dotnet ef dbcontext scaffold "Server=localhost;Port=3306;database=unispy;User=unispy;Password=;TreatTinyAsBoolean=true;" "Pomelo.EntityFrameworkCore.MySql" -v --output-dir ../../src/Libraries/UniSpyLib/Database/DatabaseModel/MySql -pause \ No newline at end of file diff --git a/common/Icon/UniSpy_Logo.ico b/common/Icon/UniSpy_Logo.ico deleted file mode 100644 index 0bdce3c8c..000000000 Binary files a/common/Icon/UniSpy_Logo.ico and /dev/null differ diff --git a/common/UniSpy.sql b/common/UniSpy.sql deleted file mode 100644 index 41cb01327..000000000 --- a/common/UniSpy.sql +++ /dev/null @@ -1,4798 +0,0 @@ -# -# SQL Export -# Created by Querious (300063) -# Created: April 10, 2021 at 21:38:07 GMT+8 -# Encoding: Unicode (UTF-8) -# - - -SET @ORIG_FOREIGN_KEY_CHECKS = @@FOREIGN_KEY_CHECKS; -SET FOREIGN_KEY_CHECKS = 0; - -SET @ORIG_UNIQUE_CHECKS = @@UNIQUE_CHECKS; -SET UNIQUE_CHECKS = 0; - -SET @ORIG_TIME_ZONE = @@TIME_ZONE; -SET TIME_ZONE = '+00:00'; - -SET @ORIG_SQL_MODE = @@SQL_MODE; -SET SQL_MODE = 'NO_AUTO_VALUE_ON_ZERO'; - - - -CREATE DATABASE IF NOT EXISTS `unispy` DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci; -USE `unispy`; - - - - -CREATE TABLE `addrequests` ( - `addrequestid` int(11) unsigned NOT NULL AUTO_INCREMENT, - `profileid` int(11) unsigned NOT NULL, - `namespaceid` int(11) unsigned NOT NULL, - `targetid` int(11) unsigned NOT NULL, - `reason` varchar(255) NOT NULL DEFAULT '', - `syncrequested` varchar(255) NOT NULL DEFAULT '', - PRIMARY KEY (`addrequestid`), - UNIQUE KEY `id` (`addrequestid`), - KEY `profileid` (`profileid`), - CONSTRAINT `FK_addrequests_profiles` FOREIGN KEY (`profileid`) REFERENCES `profiles` (`profileid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='Friend request.'; - - -CREATE TABLE `blocked` ( - `blockid` int(11) unsigned NOT NULL AUTO_INCREMENT, - `profileid` int(11) unsigned NOT NULL, - `namespaceid` int(11) unsigned NOT NULL, - `targetid` int(11) unsigned NOT NULL, - PRIMARY KEY (`blockid`), - UNIQUE KEY `id` (`blockid`), - KEY `profileid` (`profileid`), - CONSTRAINT `FK_blocked_profiles` FOREIGN KEY (`profileid`) REFERENCES `profiles` (`profileid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='Block list.'; - - -CREATE TABLE `friends` ( - `friendid` int(11) unsigned NOT NULL AUTO_INCREMENT, - `profileid` int(11) unsigned NOT NULL, - `namespaceid` int(11) unsigned NOT NULL, - `targetid` int(11) unsigned NOT NULL, - PRIMARY KEY (`friendid`) USING BTREE, - UNIQUE KEY `id` (`friendid`), - KEY `profileid` (`profileid`), - CONSTRAINT `FK_friends_profiles` FOREIGN KEY (`profileid`) REFERENCES `profiles` (`profileid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='Friend list.'; - - -CREATE TABLE `games` ( - `gameid` int(11) unsigned NOT NULL, - `gamename` text NOT NULL, - `secretkey` text, - `description` text NOT NULL, - `disabled` tinyint(1) NOT NULL DEFAULT '0', - PRIMARY KEY (`gameid`), - UNIQUE KEY `id` (`gameid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='Game list.'; - - -CREATE TABLE `grouplist` ( - `groupid` int(11) unsigned NOT NULL, - `gameid` int(11) unsigned NOT NULL, - `roomname` text NOT NULL, - PRIMARY KEY (`groupid`), - UNIQUE KEY `id` (`groupid`), - KEY `gameid` (`gameid`), - CONSTRAINT `FK_grouplist_games` FOREIGN KEY (`gameid`) REFERENCES `games` (`gameid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='Old games use grouplist to create their game rooms.'; - - -CREATE TABLE `messages` ( - `messageid` int(11) unsigned NOT NULL AUTO_INCREMENT, - `namespaceid` int(11) unsigned DEFAULT NULL, - `type` int(11) unsigned DEFAULT NULL, - `from` int(11) unsigned NOT NULL, - `to` int(11) unsigned NOT NULL, - `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `message` varchar(200) NOT NULL, - PRIMARY KEY (`messageid`), - UNIQUE KEY `id` (`messageid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='Friend messages.'; - - -CREATE TABLE `partner` ( - `partnerid` int(11) unsigned NOT NULL, - `partnername` varchar(50) NOT NULL, - PRIMARY KEY (`partnerid`), - UNIQUE KEY `id` (`partnerid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='Partner information, these information are used for authentication and login.'; - - -CREATE TABLE `profiles` ( - `profileid` int(11) unsigned NOT NULL AUTO_INCREMENT, - `userid` int(11) unsigned NOT NULL, - `nick` varchar(50) NOT NULL DEFAULT '', - `serverflag` int(1) unsigned NOT NULL DEFAULT '0', - `status` tinyint(3) unsigned DEFAULT '0', - `statstring` varchar(50) NOT NULL DEFAULT 'I love RetroSpy', - `location` varchar(127) DEFAULT '', - `firstname` varchar(50) NOT NULL DEFAULT '', - `lastname` varchar(50) NOT NULL DEFAULT '', - `publicmask` int(11) NOT NULL DEFAULT '0', - `latitude` float(10,0) NOT NULL DEFAULT '0', - `longitude` float(10,0) NOT NULL DEFAULT '0', - `aim` varchar(50) DEFAULT '0', - `picture` int(11) NOT NULL DEFAULT '0', - `occupationid` int(11) DEFAULT '0', - `incomeid` int(11) DEFAULT '0', - `industryid` int(11) DEFAULT '0', - `marriedid` int(11) DEFAULT '0', - `childcount` int(11) DEFAULT '0', - `interests1` int(11) DEFAULT '0', - `ownership1` int(11) DEFAULT '0', - `connectiontype` int(11) DEFAULT '0', - `sex` tinyint(1) unsigned DEFAULT '2', - `zipcode` varchar(10) DEFAULT '00000', - `countrycode` varchar(3) NOT NULL DEFAULT '1', - `homepage` varchar(75) DEFAULT 'rspy.org', - `birthday` int(2) DEFAULT '0', - `birthmonth` int(2) DEFAULT '0', - `birthyear` int(4) DEFAULT '0', - `icquin` int(8) unsigned DEFAULT '0', - `quietflags` tinyint(4) NOT NULL DEFAULT '0', - `streetaddr` text, - `streeaddr` text, - `city` text, - `cpubrandid` int(11) NOT NULL DEFAULT '0', - `cpuspeed` smallint(6) NOT NULL DEFAULT '0', - `memory` tinyint(4) NOT NULL DEFAULT '0', - `videocard1string` text, - `videocard1ram` tinyint(4) NOT NULL DEFAULT '0', - `videocard2string` text, - `videocard2ram` tinyint(4) NOT NULL DEFAULT '0', - `subscription` int(11) NOT NULL DEFAULT '0', - `adminrights` int(11) NOT NULL DEFAULT '0', - PRIMARY KEY (`profileid`), - UNIQUE KEY `id` (`profileid`), - KEY `userid` (`userid`), - CONSTRAINT `FK_profiles_users` FOREIGN KEY (`userid`) REFERENCES `users` (`userid`) -) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='User profiles.'; - - -CREATE TABLE `pstorage` ( - `pstorageid` int(4) unsigned NOT NULL AUTO_INCREMENT, - `profileid` int(11) unsigned NOT NULL, - `ptype` int(4) unsigned NOT NULL, - `dindex` int(4) unsigned NOT NULL, - `data` varchar(200) DEFAULT '', - PRIMARY KEY (`pstorageid`), - UNIQUE KEY `id` (`pstorageid`), - KEY `profileid` (`profileid`), - CONSTRAINT `FK_pstorage_profiles` FOREIGN KEY (`profileid`) REFERENCES `profiles` (`profileid`) -) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='Old games use pstorage to store game data.'; - - -CREATE TABLE `sakestorage` ( - `sakestorageid` int(11) unsigned NOT NULL AUTO_INCREMENT, - `tableid` varchar(50) NOT NULL, - PRIMARY KEY (`sakestorageid`), - UNIQUE KEY `sakestorageid` (`sakestorageid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='Sake storage system.'; - - -CREATE TABLE `subprofiles` ( - `subprofileid` int(11) unsigned NOT NULL AUTO_INCREMENT, - `profileid` int(11) unsigned NOT NULL, - `uniquenick` varchar(50) DEFAULT NULL, - `namespaceid` int(11) unsigned NOT NULL DEFAULT '0', - `partnerid` int(11) unsigned NOT NULL DEFAULT '0', - `productid` int(11) unsigned DEFAULT NULL, - `gamename` text, - `cdkeyenc` varchar(50) DEFAULT NULL, - `firewall` tinyint(1) DEFAULT '0', - `port` int(5) unsigned DEFAULT '0', - `authtoken` varchar(255) DEFAULT NULL, - PRIMARY KEY (`subprofileid`) USING BTREE, - UNIQUE KEY `id` (`subprofileid`), - KEY `profileid` (`profileid`), - CONSTRAINT `FK_subprofiles_profiles` FOREIGN KEY (`profileid`) REFERENCES `profiles` (`profileid`) -) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='User subprofiles.'; - - -CREATE TABLE `users` ( - `userid` int(11) unsigned NOT NULL AUTO_INCREMENT, - `email` varchar(50) NOT NULL, - `password` varchar(32) NOT NULL, - `emailverified` tinyint(1) NOT NULL DEFAULT '1', - `lastip` varchar(16) DEFAULT NULL, - `lastonline` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `createddate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `banned` tinyint(1) NOT NULL DEFAULT '0', - `deleted` tinyint(1) NOT NULL DEFAULT '0', - PRIMARY KEY (`userid`), - UNIQUE KEY `id` (`userid`) -) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='User account information.'; - - - - -LOCK TABLES `addrequests` WRITE; -UNLOCK TABLES; - - -LOCK TABLES `blocked` WRITE; -UNLOCK TABLES; - - -LOCK TABLES `friends` WRITE; -UNLOCK TABLES; - - -LOCK TABLES `games` WRITE; -INSERT INTO `games` (`gameid`, `gamename`, `secretkey`, `description`, `disabled`) VALUES - (1,'gmtest','HA6zkS','Test / demo / temporary',0), - (2,'bgate',NULL,'Baldur\'s Gate',0), - (3,'blood2',NULL,'Blood II',0), - (4,'bz2',NULL,'Battlezone 2',0), - (5,'daikatana',NULL,'Daikatana',0), - (6,'descent3',NULL,'Descent 3',0), - (7,'dh3',NULL,'Deer Hunter 3',0), - (8,'drakan',NULL,'Drakan',0), - (9,'dv',NULL,'Dark Vengeance',0), - (10,'expertpool',NULL,'Expert Pool',0), - (11,'forsaken',NULL,'Forsaken',0), - (12,'gamespy2',NULL,'GameSpy 3D',0), - (13,'gspylite',NULL,'GameSpy Lite',0), - (14,'gspyweb',NULL,'GameSpy Web',0), - (15,'halflife',NULL,'Half Life',0), - (16,'heretic2',NULL,'Heretic II',0), - (17,'hexenworld',NULL,'Hexenworld',0), - (18,'kingpin',NULL,'Kingpin',0), - (19,'mplayer',NULL,'MPlayer',0), - (20,'quake1',NULL,'Quake',0), - (21,'quake2',NULL,'Quake II',0), - (22,'quake3',NULL,'Quake 3: Arena',0), - (23,'quakeworld',NULL,'Quakeworld',0), - (24,'rally',NULL,'Rally Masters',0), - (25,'redline',NULL,'Redline',0), - (26,'shogo',NULL,'Shogo',0), - (27,'sin',NULL,'SiN',0), - (28,'slavezero',NULL,'Slave Zero',0), - (29,'sof',NULL,'Soldier of Fortune',0), - (30,'southpark',NULL,'South Park',0), - (31,'specops',NULL,'Spec Ops',0), - (32,'tribes',NULL,'Starsiege TRIBES',0), - (33,'turok2',NULL,'Turok 2',0), - (34,'unreal',NULL,'Unreal',0), - (35,'ut',NULL,'Unreal Tournament',0), - (36,'viper',NULL,'Viper',0), - (39,'nerfarena',NULL,'Nerf Arena',0), - (40,'wot',NULL,'Wheel of Time',0), - (41,'giants',NULL,'Giants',0), - (42,'dtracing',NULL,'Dirt Track Racing',0), - (43,'terminus',NULL,'Terminus',0), - (44,'darkreign2',NULL,'Dark Reign 2',0), - (45,'ra2',NULL,'Rocket Arena 2',0), - (46,'aoe2',NULL,'Age of Empires 2',0), - (47,'roguespear',NULL,'Rogue Spear',0), - (48,'scompany',NULL,'Shadow Company',0), - (49,'scrabble',NULL,'Scrabble',0), - (50,'boggle',NULL,'Boggle',0), - (51,'werewolf',NULL,'Werewolf: The Apocalypse',0), - (52,'treadmarks',NULL,'Tread Marks',0), - (53,'avp',NULL,'Aliens Vs Predator',0), - (54,'rock',NULL,'Rock',0), - (55,'midmad',NULL,'Midtown Madness',0), - (56,'aoe',NULL,'Age of Empires',0), - (57,'revolt',NULL,'Revolt',0), - (58,'gslive',NULL,'GameSpy Arcade',0), - (60,'paintball',NULL,'Paintball',0), - (61,'wildwings',NULL,'Wild Wings',0), - (62,'rmth3',NULL,'Rocky Mountain Trophy Hunter 3',0), - (64,'metalcrush3',NULL,'Metal Crush 3',0), - (65,'ta',NULL,'Total Annihilation',0), - (67,'mech3',NULL,'Mech Warrior 3',0), - (68,'railty2',NULL,'Railroad Tycoon II',0), - (70,'mcmad',NULL,'Motocross Madness',0), - (71,'heroes3',NULL,'Heroes Of Might And Magic III',0), - (72,'jk',NULL,'Star Wars: Jedi Knight',0), - (73,'links98',NULL,'Links LS 1998',0), - (75,'irl2000',NULL,'Indy Racing League 2000',0), - (84,'xwingtie',NULL,'Star Wars: X-Wing vs. TIE Fighter',0), - (99,'buckmaster',NULL,'Buckmaster Deer Hunting',0), - (100,'cneagle',NULL,'Codename: Eagle',0), - (104,'alphacent',NULL,'Sid Meier\'s Alpha Centauri',0), - (108,'sanity',NULL,'Sanity',0), - (112,'jetfighter4',NULL,'Jet Fighter 4',0), - (113,'starraiders',NULL,'Star Raiders',0), - (114,'kiss',NULL,'KISS: Psycho Circus',0), - (121,'risk',NULL,'Risk C.1997',0), - (122,'cribbage',NULL,'Hasbro\'s Cribbage',0), - (123,'populoustb',NULL,'Populous: The Beginning',0), - (125,'ginrummy',NULL,'Hasbro\'s Gin Rummy',0), - (126,'hearts',NULL,'Hasbro\'s Hearts',0), - (128,'spades',NULL,'Hasbro\'s Spades',0), - (129,'racko',NULL,'Hasbro\'s Racko',0), - (130,'rook',NULL,'Hasbro\'s Rook',0), - (131,'checkers',NULL,'Hasbro\'s Checkers',0), - (133,'chess',NULL,'Hasbro\'s Chess',0), - (134,'dominos',NULL,'Hasbro\'s Dominos',0), - (135,'tzar',NULL,'TZAR',0), - (136,'parcheesi',NULL,'Hasbro\'s Parcheesi',0), - (137,'pente',NULL,'Hasbro\'s Pente',0), - (138,'backgammon',NULL,'Hasbro\'s Backgammon',0), - (139,'freepark',NULL,'Hasbro\'s Free Parking',0), - (140,'connect4',NULL,'Hasbro\'s Connect 4',0), - (141,'millebourn',NULL,'Hasbro\'s Mille Bournes',0), - (142,'msgolf99',NULL,'Microsoft Golf 99',0), - (143,'civ2tot',NULL,'Civilization II: Test of Time',0), - (144,'close4bb',NULL,'CloseCombat4BB',0), - (145,'aliencross',NULL,'Alien Crossfire',0), - (146,'outlaws',NULL,'Outlaws',0), - (147,'civ2gold',NULL,'Civilization 2: Gold',0), - (148,'getmede',NULL,'Get Medieval',0), - (149,'gruntz',NULL,'Gruntz',0), - (150,'monopoly',NULL,'Monopoly',0), - (151,'rb6',NULL,'Rainbow Six',0), - (152,'wz2100',NULL,'Warzone 2100',0), - (153,'rebellion',NULL,'Star Wars: Rebellion',0), - (154,'ccombat3',NULL,'Close Combat 3',0), - (155,'baldursg',NULL,'Baludurs Gate',0), - (156,'jkmosith1',NULL,'Star Wars Jedi Knight: Mysteries of the Sith1',0), - (157,'smgettysbu',NULL,'Sid Meier\'s Gettysburg',0), - (158,'srally2dmo',NULL,'Sega Rally 2 PC Demo',0), - (159,'fltsim2k',NULL,'Flight Simulator 2000',0), - (160,'aowdemo',NULL,'Age Of Wonders Demo',0), - (161,'duke4',NULL,'Duke Nukem Forever',0), - (162,'aowfull',NULL,'Age Of Wonders',0), - (163,'darkstone',NULL,'Darkstone',0), - (164,'abominatio',NULL,'Abomination',0), - (165,'bc3k',NULL,'Battle Cruiser 3000 AD',0), - (166,'outlawsdem',NULL,'Outlaw Multiplay Demo',0), - (167,'allegiance',NULL,'MS Allegiance',0), - (168,'rsurbanops',NULL,'Rogue Spear: Urban Ops',0), - (169,'aoe2demo',NULL,'Age of Empires II Demo',0), - (170,'mcmaddemo',NULL,'Motocross Madness Demo',0), - (171,'midmaddemo',NULL,'Midtown Madness Demo',0), - (172,'mtmdemo',NULL,'Monster Truck Madness Demo',0), - (173,'axisallies',NULL,'Axis & Allies',0), - (174,'rallychamp',NULL,'Mobil1 Rally Championship',0), - (175,'worms2',NULL,'Worms 2',0), - (176,'mtruckm2',NULL,'Monster Truck Madness 2',0), - (177,'powerslide',NULL,'Powerslide',0), - (178,'kissdc',NULL,'Kiss (Dreamcast)',0), - (179,'legendsmm',NULL,'Legends of Might and Magic',0), - (180,'mech4',NULL,'Mechwarrior 4',0), - (181,'sofretail',NULL,'Soldier of Fortune: Retail',0), - (182,'majesty',NULL,'Majesty',0), - (183,'fblackjack',NULL,'Fiendish Blackjack',0), - (184,'slancerdc',NULL,'Starlancer (Dreamcast)',0), - (185,'fbackgammon',NULL,'Fiendish Backgammon',0), - (186,'dogsofwar',NULL,'Dogs of War',0), - (187,'starlancer',NULL,'Starlancer',0), - (188,'laserarena',NULL,'Laser Arena (2015)',0), - (189,'mmadness2',NULL,'Motocross Madness 2',0), - (190,'obiwon',NULL,'Obi-Wan',0), - (191,'ra3',NULL,'Rocket Arena 3',0), - (192,'virtualpool3',NULL,'Virtual Pool 3',0), - (195,'sanitydemo',NULL,'Sanity Demo',0), - (196,'sanitybeta',NULL,'Sanity Beta',0), - (197,'Frogger',NULL,'Frogger',0), - (198,'stitandemo',NULL,'Submarine Titans Demo',0), - (199,'stbotf',NULL,'Birth of the Federation',0), - (200,'machines',NULL,'Machines',0), - (201,'amairtac',NULL,'Army Men - Air Tactics',0), - (202,'amworldwar',NULL,'Army Men World War',0), - (203,'gettysburg',NULL,'Gettysburg',0), - (204,'hhbball2000',NULL,'High Heat Baseball 2000',0), - (205,'dogalo',NULL,'MechWarrior 3',0), - (206,'armymen2',NULL,'Army Men II',0), - (207,'armymenspc',NULL,'Army Men Toys in Space',0), - (208,'hhbball2001',NULL,'High Heat Baseball 2001',0), - (209,'risk2',NULL,'Risk II',0), - (210,'starwrsfrc',NULL,'Star Wars: Force Commander',0), - (211,'peoplesgen',NULL,'Peoples General',0), - (212,'planecrazy',NULL,'Plane Crazy',0), - (213,'linksext',NULL,'Links Extreme',0), - (214,'flyinghero',NULL,'Flying Heroes',0), - (215,'fltsim98',NULL,'Microsoft Flight Simulator 98',0), - (216,'links2000',NULL,'Links LS 2000',0), - (217,'ritesofwar',NULL,'Warhammer: Rites of War',0), - (218,'gulfwarham',NULL,'Gulf War: Operatin Desert',0), - (219,'uprising2',NULL,'Uprising 2',0), - (220,'earth2150',NULL,'Earth 2150',0), - (221,'evolva',NULL,'Evolva',0), - (222,'eawar',NULL,'European Air War',0), - (223,'7kingdoms',NULL,'Seven Kingdoms 2',0), - (224,'migalley',NULL,'Mig Alley',0), - (225,'axallirnb',NULL,'Axis & Allies: Iron Blitz',0), - (226,'rrt2scnd',NULL,'Railroad Tycoon 2: The Second Century',0), - (227,'mcommgold',NULL,'MechCommander Gold',0), - (228,'santietam',NULL,'Sid Meier\'s Antietam!',0), - (229,'heroes3arm',NULL,'Heroes of Might and Magic',0), - (230,'panzergen2',NULL,'Panzer General',0), - (231,'lazgo2demo',NULL,'Lazgo 2 Demo',0), - (232,'taking',NULL,'Total Annihilation: Kingdoms',0), - (233,'mfatigue',NULL,'Metal Fatigue',0), - (234,'cfs',NULL,'Microsoft Combat Flight Simulator',0), - (235,'starsiege',NULL,'Starsiege',0), - (236,'jkmots',NULL,'Star Wars Jedi Knight: Mysteries of the Sith',0), - (237,'zdoom',NULL,'ZDoom',0), - (238,'warlordsb',NULL,'Warlords Battlecry',0), - (239,'bangdemo',NULL,'Bang! Gunship Elite Demo',0), - (240,'anno1602ad',NULL,'Anno 1602 A.D.',0), - (241,'dh4',NULL,'Deer Hunter 4',0), - (242,'group',NULL,'Group Room',0), - (243,'blademasters',NULL,'Legend of the Blademasters',0), - (244,'iwdale',NULL,'Icewind Dale',0), - (245,'dogsrunamock',NULL,'dogsrunamock (?)',0), - (246,'excessive',NULL,'Excessive Q3',0), - (247,'bgate2',NULL,'Baldur\'s Gate II: Shadows of Amn',0), - (248,'mcm2demo',NULL,'Motocross Madness 2 Demo',0), - (249,'dtrsc',NULL,'Dirt Track Racing: Sprint Cars',0), - (250,'chspades',NULL,'Championship Spades',0), - (251,'chhearts',NULL,'Championship Hearts',0), - (252,'stef1',NULL,'Star Trek: Voyager – Elite Force',0), - (253,'orb',NULL,'O.R.B: Off-World Resource Base',0), - (254,'nolf',NULL,'No One Lives Forever',0), - (255,'dtr',NULL,'Dirt Track Racing',0), - (256,'sacrifice',NULL,'Sacrifice',0), - (257,'rune',NULL,'Rune',0), - (258,'aoe2tc',NULL,'Age of Empires II: The Conquerors',0), - (259,'stitans',NULL,'Submarine Titans',0), - (260,'bang',NULL,'Bang! Gunship Elite',0), - (261,'aoe2tcdemo',NULL,'Age of Empires II: The Conquerors Demo',0), - (262,'fakk2',NULL,'F.A.K.K. 2',0), - (263,'bcm',NULL,'Battlecruiser: Millenium',0), - (264,'ds9dominion',NULL,'DS9: Dominion Wars',0), - (265,'bots',NULL,'Bots (Lith)',0), - (266,'tacore',NULL,'Core Contingency',0), - (267,'mech3pm',NULL,'Pirates Moon',0), - (268,'diplomacy',NULL,'Diplomacy',0), - (269,'bandw',NULL,'Black and White',0), - (270,'fargate',NULL,'Far Gate',0), - (271,'nexttetris',NULL,'The Next Tetris',0), - (272,'fforce',NULL,'Freedom Force',0), - (273,'iwar2',NULL,'Independance War 2',0), - (274,'gp500',NULL,'GP500',0), - (275,'midmad2',NULL,'Midtown Madness 2',0), - (276,'insane',NULL,'Insane',0), - (277,'unreal2',NULL,'Unreal 2',0), - (278,'4x4evo',NULL,'4x4 Evolution',0), - (279,'crimson',NULL,'Crimson Skies',0), - (280,'harleywof',NULL,'Wheels of Freedom',0), - (281,'dtrscdmo',NULL,'Dirt Track Racing: Sprint',0), - (282,'ageofsail2',NULL,'Age of Sail 2',0), - (283,'cskies',NULL,'Crimson Skies',0), - (284,'rscovertops',NULL,'Rainbow Six: Covert Ops',0), - (285,'pba2001',NULL,'PBA Bowling 2001',0), - (286,'cskiesdemo',NULL,'Crimson Skies Demo',0), - (287,'mech4st',NULL,'MechWarrior 4: Vengeance',0), - (288,'wosin',NULL,'SiN: Wages of Sin',0), - (289,'sinmac',NULL,'SiN (Mac)',0), - (290,'wosinmac',NULL,'SiN: Wages of Sin (Mac)',0), - (291,'utdc',NULL,'Unreal Tournament (Dreamcast)',0), - (292,'kohan',NULL,'Kohan: Immortal Sovereigns',0), - (293,'mcmania',NULL,'Motocross Mania',0), - (294,'close5',NULL,'Close Combat 5',0), - (295,'furfiighters',NULL,'Fur Fighters (?)',0), - (296,'furfighters',NULL,'Fur Fighters',0), - (297,'owar',NULL,'Original War',0), - (298,'cfs2',NULL,'Combat Flight Simulator 2',0), - (299,'uno',NULL,'UNO',0), - (301,'deusex',NULL,'Deus Ex',0), - (302,'gore',NULL,'Gore',0), - (303,'gangsters2',NULL,'Gansters II: Vendetta',0), - (304,'insanedmo',NULL,'Insane Demo',0), - (305,'close5dmo',NULL,'Close Combat 5 Demo',0), - (306,'atlantis',NULL,'Atlantis',0), - (307,'cossacks','p2vPkJ','Cossacks Anthology',0), - (308,'ihraracing',NULL,'IHRA Drag Racing',0), - (309,'atlantispre',NULL,'Atlantis Prequel',0), - (310,'4x4retail',NULL,'4x4 Evolution',0), - (311,'rnconsole',NULL,'Real Networks Console',0), - (312,'dukes',NULL,'Dukes Of Hazzard: Racing',0), - (313,'serioussam',NULL,'Serious Sam',0), - (314,'runedemo',NULL,'Rune Demo',0), - (315,'suddenstrike',NULL,'Sudden Strike',0), - (316,'rfts',NULL,'Reach For The Stars',0), - (317,'cheuchre',NULL,'Championship Euchre',0), - (318,'links2001',NULL,'Links 2001',0), - (319,'stefdemo',NULL,'Star Trek: Voyager – Elite Force Demo',0), - (320,'4x4evodemo',NULL,'4x4 Evolution Demo',0), - (321,'mcmaniadmo',NULL,'Motocross Mania Demo',0), - (322,'gamevoice',NULL,'MS Game Voice',0), - (323,'cstrike',NULL,'Counter-Strike',0), - (324,'venomworld',NULL,'Venom World',0), - (325,'omfbattle',NULL,'One Must Fall Battlegrounds',0), - (326,'furdemo',NULL,'Fur Fighters Demo',0), - (327,'q3tademo',NULL,'Team Arena Demo',0), - (328,'nwn',NULL,'Neverwinter Nights',0), - (329,'strifeshadow',NULL,'Strifeshadow',0), - (330,'ssamdemo',NULL,'Serious Sam Demo',0), - (331,'kacademy',NULL,'Klingon Academy',0), - (332,'goredemo',NULL,'Gore Demo',0), - (333,'majestyx',NULL,'Majesty Expansion',0), - (334,'midmad2dmo',NULL,'Midtown Madness 2 Demo',0), - (335,'gunman',NULL,'Gunman Chronicles',0), - (336,'stronghold',NULL,'Stronghold',0), - (337,'armada2','N3a2mZ','Star Trek Armada 2',0), - (338,'links2001dmo',NULL,'Links 2001 Demo',0), - (339,'q3tafull',NULL,'Team Arena Retail',0), - (340,'botbattles',NULL,'Tex Atomics Big Bot Battles',0), - (341,'battlerealms',NULL,'Battle Realms',0), - (342,'sfc',NULL,'Starfleet Command',0), - (343,'strfltcmd2',NULL,'Starfleet Command Volume',0), - (344,'stnw',NULL,'Star Trek: New Worlds',0), - (345,'strfltcmd2d',NULL,'Empires at War Demo',0), - (346,'sfcdemo',NULL,'Starfleet Command Demo',0), - (347,'crmgdntdr2k',NULL,'Carmageddon TDR 2000',0), - (348,'waterloo',NULL,'Waterloo',0), - (349,'falloutbosd',NULL,'Fallout Tactics',0), - (350,'kohandemo',NULL,'Kohan Demo',0), - (351,'exploeman',NULL,'Explöman',0), - (352,'segarally2',NULL,'Sega Rally 2',0), - (353,'explomän',NULL,'Explomän',0), - (354,'streetjam',NULL,'Ultra Wheels Street Jam',0), - (355,'explomaen',NULL,'Explomän',0), - (356,'bcommander',NULL,'Star Trek: Bridge Commander',0), - (357,'mrwtour',NULL,'Motoracer World Tour',0), - (358,'wordzap',NULL,'WordZap',0), - (359,'iwdalehow',NULL,'Icewind Dale: Heart of Winter',0), - (360,'magmay2',NULL,'Magic & Mayhem 2',0), - (361,'chat01',NULL,'Chat Group 1',0), - (362,'chat02',NULL,'Chat Group 2',0), - (363,'chat03',NULL,'Chat Group 3',0), - (364,'Chat04',NULL,'Chat Group 4',0), - (365,'Chat05',NULL,'Chat Group 5',0), - (366,'Chat06',NULL,'Chat Group 6',0), - (367,'Chat07',NULL,'Chat Group 7',0), - (368,'Chat08',NULL,'Chat Group 8',0), - (369,'Chat09',NULL,'Chat Group 9',0), - (370,'Chat10',NULL,'Chat Group 10',0), - (371,'Chat11',NULL,'Chat Group 11',0), - (372,'Chat12',NULL,'Chat Group 12',0), - (373,'Chat13',NULL,'Chat Group 13',0), - (374,'Chat14',NULL,'Chat Group 14',0), - (375,'Chat15',NULL,'Chat Group 15',0), - (376,'Chat16',NULL,'Chat Group 16',0), - (377,'Chat17',NULL,'Chat Group 17',0), - (378,'Chat18',NULL,'Chat Group 18',0), - (379,'Chat19',NULL,'Chat Group 19',0), - (380,'Chat20',NULL,'Chat Group 20',0), - (381,'empireearth',NULL,'Empire Earth',0), - (382,'chasspart5',NULL,'ChessPartner 5',0), - (383,'bg2bhaal',NULL,'Baldur\'s Gate II: Throne of Bhaal',0), - (384,'legendsmmbeta',NULL,'Legends of Might and Magic Beta',0), - (385,'cultures',NULL,'Cultures',0), - (386,'fatedragon',NULL,'Fate of the Dragon',0), - (387,'sbubpop',NULL,'Super Bubble Pop',0), - (388,'xcomenforcer',NULL,'X-Com: Enforcer',0), - (389,'aow2',NULL,'Age of Wonders 2',0), - (390,'startopia',NULL,'Startopia',0), - (391,'jefftest',NULL,'Test for Jeffs Games',0), - (392,'hhbball2002',NULL,'High Heat Baseball 2002',0), - (394,'por2',NULL,'Pool of Radiance 2',0), - (395,'falloutbos',NULL,'Fallout Tactics',0), - (396,'moonproject',NULL,'Moon Project',0), - (397,'fatedragond',NULL,'Fate of the Dragon Demo',0), - (398,'demonstar',NULL,'Demonstar',0), - (399,'tf15',NULL,'Half-Life 1.5',0), - (400,'gspoker',NULL,'GameSpy Poker',0), - (401,'gsspades',NULL,'GameSpy Spades',0), - (402,'gshearts',NULL,'GameSpy Hearts',0), - (403,'gsbgammon',NULL,'GameSpy Backgammon',0), - (404,'gscheckers',NULL,'GameSpy Checkers',0), - (405,'atlantica',NULL,'Atlantica',0), - (406,'merchant2',NULL,'Merchant Prince II',0), - (407,'magmay2d',NULL,'The Art of War',0), - (408,'assimilation',NULL,'Assimilation',0), - (409,'zax',NULL,'Zax',0), - (410,'leadfoot',NULL,'Leadfoot',0), - (411,'leadfootd',NULL,'Leadfoot Demo',0), - (412,'chat',NULL,'Chat Service',0), - (413,'disciples',NULL,'Disciples',0), - (414,'opflash',NULL,'Operation Flashpoint',0), - (415,'zsteel',NULL,'Z: Steel Soldiers',0), - (416,'redlinenet',NULL,'Redline Multi-Player Inst',0), - (417,'gschess',NULL,'GameSpy Chess',0), - (418,'gsreversi',NULL,'GameSpy Reversi',0), - (419,'gsyarn',NULL,'GameSpy Y.A.R.N.',0), - (420,'tribes2',NULL,'Tribes 2',0), - (421,'avp2',NULL,'Aliens vs Predator 2',0), - (422,'bodarkness',NULL,'Blade of Darkness',0), - (423,'dominion',NULL,'Dominion',0), - (424,'disciples2',NULL,'Disciples 2',0), - (425,'opflashd',NULL,'Operation Flashpoint Demo',0), - (426,'blade',NULL,'Blade',0), - (427,'mechcomm',NULL,'MechCommander',0), - (428,'globalops',NULL,'Global Operations',0), - (429,'links99',NULL,'Links LS 1999',0), - (430,'rulesotg',NULL,'Rules of the Game',0), - (431,'avpnotgold',NULL,'Aliens vs. Predator',0), - (432,'armymen',NULL,'Army Men',0), - (433,'_news',NULL,'News',0), - (434,'railsamd',NULL,'Rails Across America Demo',0), - (435,'railsam',NULL,'Rails Across America',0), - (436,'kohanexp',NULL,'Kohan Expansion',0), - (437,'cueballworld',NULL,'Jimmy White Cueball World',0), - (438,'wz2100demo',NULL,'Warzone 2100 (Demo)',0), - (439,'sfc2opdv',NULL,'Starfleet Command II: Orion Pirates (Dynaverse II)',0), - (440,'roguespeard',NULL,'Rogue Spear Demo',0), - (441,'redalert',NULL,'Red Alert',0), - (442,'wormsarm',NULL,'Worms Armageddon',0), - (443,'takingdoms',NULL,'TA: Kingdoms',0), - (444,'arc',NULL,'Arc: Sierra',0), - (445,'diablo',NULL,'Diablo',0), - (446,'tetrisworlds',NULL,'Tetris Worlds',0), - (447,'dh5',NULL,'Deer Hunter 5',0), - (448,'diablo2',NULL,'Diablo 2',0), - (449,'starcraft',NULL,'Starcraft',0), - (450,'starcraftdmo',NULL,'Starcraft Demo',0), - (451,'rsblackthorn',NULL,'Rogue Spear: Black Thorn',0), - (452,'warcraft2bne',NULL,'Warcraft 2',0), - (453,'redalert2',NULL,'Red Alert 2',0), - (454,'projecteden',NULL,'Project Eden',0), - (455,'roadwars',NULL,'Road Wars',0), - (456,'tiberiansun',NULL,'Tiberian Sun',0), - (457,'chessworlds',NULL,'Chess Worlds',0), - (458,'americax',NULL,'America Addon',0), - (459,'sfc2op',NULL,'Starfleet Command: Orion',0), - (460,'warlordsdr',NULL,'Warlords III: Dark Rising',0), - (461,'stef1exp',NULL,'Star Trek: Voyager - Elite Force expansion pack',0), - (462,'cmanager',NULL,'Cycling Manager',0), - (463,'laserarenad',NULL,'Laser Arena Demo',0), - (464,'starcraftexp',NULL,'Starcraft: Brood Wars',0), - (465,'tsfirestorm',NULL,'Tiberian Sun - Firestorm',0), - (466,'monopolyty',NULL,'Monopoly Tycoon',0), - (467,'thps3ps2',NULL,'Tony Hawk Pro Skater 3 (PS2)',0), - (468,'emperorbfd',NULL,'Emperor: Battle For Dune',0), - (469,'claw',NULL,'Claw',0), - (470,'armymenrts',NULL,'Army Men RTS',0), - (471,'legendsmmbeta2',NULL,'Legends of Might and Magic First Look 2',0), - (472,'conquestfw',NULL,'Conquest: Frontier Wars',0), - (473,'realwar',NULL,'Real War',0), - (474,'axis',NULL,'Axis',0), - (475,'anno1503',NULL,'Anno 1503',0), - (476,'incomingforces',NULL,'Incoming Forces',0), - (477,'ironstrategy',NULL,'Iron Strategy',0), - (478,'heavygear2',NULL,'Heavy Gear 2',0), - (479,'sfc2dv',NULL,'Starfleet Command 2: Empires At War Dynaverse',0), - (480,'motoracer3',NULL,'Motoracer 3',0), - (481,'rogerwilco',NULL,'Roger Wilco',0), - (482,'conquestfwd',NULL,'Conquest: Frontier Wars D',0), - (483,'thps3media',NULL,'Tony Hawk Pro Skater 3 Media',0), - (484,'echelon',NULL,'Echelon',0), - (485,'takeda',NULL,'Takeda',0), - (486,'cnoutbreak',NULL,'Codename: Outbreak',0), - (487,'oldscrabble',NULL,'Scrabble 1.0',0), - (488,'st_highscore',NULL,'Stats and Tracking Sample',0), - (489,'rdpoker',NULL,'Reel Deal Poker',0), - (490,'f1teamdriver',NULL,'Williams F1 Team: Team Dr',0), - (491,'aquanox',NULL,'Aquanox',0), - (492,'mohaa',NULL,'Medal of Honor Allied Assault',0), - (493,'harley3',NULL,'Harel 3',0), - (494,'cnoutbreakd',NULL,'Codename: Outbreak Demo',0), - (495,'ras',NULL,'Red Ace Squadron',0), - (496,'opfor',NULL,'Opposing Force',0), - (497,'rallychampx',NULL,'Rally Championship Extrem',0), - (498,'austerlitz',NULL,'Austerlitz: Napoleons Gre',0), - (499,'dmania',NULL,'DMania',0), - (500,'bgatetales',NULL,'Baldur\'s Gate: Tales of the Sword Coast',0), - (501,'cueballworldd',NULL,'Cueball World Demo',0), - (502,'st_rank',NULL,'Global Rankings Sample',0), - (503,'rallytrophy',NULL,'Rally Trophy',0), - (504,'kohanagdemo',NULL,'Kohan: Ahrimans Gift Demo',0), - (505,'actval1',NULL,'Activision Value Title 1',0), - (506,'etherlords',NULL,'Etherlords',0), - (507,'swine',NULL,'S.W.I.N.E.',0), - (508,'warriorkings',NULL,'Warrior Kings',0), - (509,'myth3',NULL,'Myth 3',0), - (517,'commandos2',NULL,'Commandos 2',0), - (518,'mcomm2',NULL,'MechCommander 2',0), - (519,'masterrally',NULL,'Master Rally',0), - (520,'praetorians',NULL,'Praetorians',0), - (521,'iwd2',NULL,'Icewind Dale 2',0), - (522,'gamebot',NULL,'GameBot Test',0), - (523,'armada2beta',NULL,'Star Trek: Armada 2 Beta',0), - (524,'rtcwtest',NULL,'Wolfenstein MP Test',0), - (525,'mechcomm2',NULL,'MechCommander 2',0), - (526,'nvchess',NULL,'nvChess',0), - (527,'msecurity',NULL,'Alcatraz: Prison Escape',0), - (528,'avp2demo',NULL,'Aliens vs Predator 2 Demo',0), - (529,'swgbd',NULL,'Star Wars: Galactic Battlegrounds Demo',0), - (530,'chaser',NULL,'Chaser',0), - (531,'nascar5',NULL,'NASCAR 5',0), - (532,'kohanag',NULL,'Kohan: Ahrimans Gift',0), - (533,'tribes2demo',NULL,'Tribes 2 Demo',0), - (534,'serioussamse',NULL,'Serious Sam: Second Encounter',0), - (535,'st_ladder',NULL,'Global Rankings Sample - Ladder',0), - (536,'swgb',NULL,'Star Wars: Galactic Battlegrounds',0), - (537,'bumperwars',NULL,'Bumper Wars!',0), - (538,'combat',NULL,'Combat',0), - (539,'etherlordsd',NULL,'Etherlords Demo',0), - (540,'rsblackthornd',NULL,'Black Thorn Demo',0), - (541,'bfield1942',NULL,'Battlefield 1942',0), - (542,'battlerealmsbBAD',NULL,'Battle Realms Beta',0), - (543,'swinedemo',NULL,'Swine Demo',0), - (544,'freedomforce',NULL,'Freedom Force',0), - (545,'il2sturmovik',NULL,'IL-2 Sturmovik',0), - (548,'myth3demo',NULL,'Myth 3 Demo',0), - (549,'strongholdd',NULL,'Stronghold Demo',0), - (550,'ghostrecon',NULL,'Tom Clancy\'s Ghost Recon',0), - (551,'ghostrecond',NULL,'Tom Clancy\'s Ghost Recon Demo',0), - (552,'fltsim2002',NULL,'Microsoft Flight Simulator 2002',0), - (553,'mech4bkexp',NULL,'MechWarrior Black Knight',0), - (554,'hd',NULL,'Hidden & Dangerous Enhanc',0), - (555,'strifeshadowd',NULL,'Strifeshadow Demo',0), - (556,'conflictzone',NULL,'Conflict Zone',0), - (557,'racedriver',NULL,'TOCA Race Driver',0), - (558,'druidking',NULL,'Druid King',0), - (559,'itycoon2',NULL,'Industry Tycoon 2',0), - (560,'sof2',NULL,'Soldier of Fortune 2',0), - (561,'armada2d',NULL,'Star Trek: Armada II Demo',0), - (562,'avp2lv',NULL,'Aliens vs. Predator 2 (Low violence)',0), - (563,'rtcw',NULL,'Return to Castle Wolfenstein',0), - (564,'xboxtunnel',NULL,'Xbox Tunnel Service',0), - (565,'survivor',NULL,'Survivor Ultimate',0), - (566,'il2sturmovikd',NULL,'IL-2 Sturmovik Demo',0), - (567,'haegemonia',NULL,'Haegemonia',0), - (568,'mohaad',NULL,'Medal of Honor: Allied Assault Demo',0), - (569,'serioussamsed',NULL,'Serious Sam: Second Encounter Demo',0), - (570,'janesf18',NULL,'Janes F/A-18',0), - (571,'janesusaf',NULL,'Janes USAF',0), - (572,'janesfa',NULL,'Janes Fighters Anthology',0), - (573,'janesf15',NULL,'Janes F-15',0), - (574,'janesww2',NULL,'Janes WWII Fighters',0), - (575,'mech4bwexpd',NULL,'MechWarrior Black Knight',0), - (576,'f12002',NULL,'F1 2002',0), - (577,'ccrenegade',NULL,'Command & Conquer: Renegade',0), - (578,'redalert2exp',NULL,'Command & Conquer: Yuri\'s Revenge',0), - (579,'capitalism2',NULL,'Capitalism 2',0), - (580,'demoderby',NULL,'Demolition Derby & Figure',0), - (581,'janesattack',NULL,'Janes Attack Squadron',0), - (582,'chesk',NULL,'Chesk',0), - (583,'hhball2003',NULL,'High Heat Baseball 2003',0), - (584,'duelfield',NULL,'Duelfield',0), - (585,'carnivores3',NULL,'Carnivores 3',0), - (586,'jk2',NULL,'Star Wars Jedi Knight II: Jedi Outcast',0), - (587,'thps3pc',NULL,'Tony Hawk 3 (PC)',0), - (588,'blockade',NULL,'Operation Blockade',0), - (589,'mafia',NULL,'Mafia',0), - (590,'ccrenegadedemo',NULL,'Command & Conquer: Renegade Demo',0), - (591,'shadowforce',NULL,'Shadow Force: Razor Unit',0), - (595,'gta3pc',NULL,'Grand Theft Auto 3 (PC)',0), - (596,'vietkong',NULL,'Vietkong',0), - (597,'mooncommander',NULL,'Moon Commander',0), - (598,'subcommand',NULL,'Sub Command',0), - (599,'originalwar',NULL,'Original War',0), - (600,'thps4ps2',NULL,'Tony Hawk: Pro Skater 4 (PS2)',0), - (601,'warlordsb2d',NULL,'Warlords Battlecry II Demo',0), - (602,'ioftheenemy',NULL,'I of the Enemy',0), - (603,'sharpshooter',NULL,'Sharp Shooter',0), - (604,'medieval',NULL,'Medieval: Total War',0), - (605,'globalopspb',NULL,'Global Operations Public Beta',0), - (606,'pb4',NULL,'Extreme Paintbrawl 4',0), - (610,'armygame',NULL,'Americas Army: Special Forces',0), - (611,'homm4',NULL,'Heroes of Might and Magic',0), - (612,'darkplanet',NULL,'Dark Planet',0), - (613,'mobileforces',NULL,'Mobile Forces',0), - (614,'teamfactor',NULL,'Team Factor',0), - (615,'dragonthrone',NULL,'Dragon Throne',0), - (616,'celebdm',NULL,'Celebrity Deathmatch',0), - (617,'phoenix',NULL,'Phoenix (Stainless Steel)',0), - (618,'matrixproxy',NULL,'Matrix Proxy',0), - (619,'mobileforcesd',NULL,'Mobile Forces Demo',0), - (620,'ghostreconds',NULL,'Ghost Recon: Desert Siege',0), - (621,'sof2demo',NULL,'Soldier of Fortune 2 Demo',0), - (622,'etherlordsbeta',NULL,'Etherlords Patch Beta',0), - (623,'aow2d',NULL,'Age of Wonders 2 Demo',0), - (624,'privateer',NULL,'Privateers Bounty: Age of Sail 2',0), - (625,'gcracing',NULL,'Great Clips Racing',0), - (626,'survivorm',NULL,'Survivor: Marquesas',0), - (627,'dungeonsiege',NULL,'Dungeon Siege',0), - (628,'silenthunter2',NULL,'Silent Hunter 2',0), - (629,'celtickings',NULL,'Druid King',0), - (630,'globalopsd',NULL,'Global Ops Demo',0), - (631,'renegadebf',NULL,'Renegade Battlefield',0), - (632,'warlordsb2',NULL,'Warlords Battlecry II',0), - (633,'tacticalops',NULL,'Tactical Ops',0), - (634,'ut2',NULL,'Unreal Tournament 2003',0), - (635,'swgbcc',NULL,'Star Wars Galactic Battle',0), - (636,'ut2d',NULL,'Unreal Tournament 2003 Demo',0), - (637,'voiceapp',NULL,'VoiceApp Voice SDK Test',0), - (638,'sumofallfearsd',NULL,'The Sum of All Fears Demo',0), - (639,'streetracer',NULL,'Streetracer',0), - (640,'opflashr',NULL,'Operation Flashpoint: Resistance',0), - (641,'mohaas',NULL,'Medal of Honor: Allied Assault Spearhead',0), - (642,'avp2ph',NULL,'Aliens vs. Predator 2: Primal Hunt',0), - (643,'nthunder2003',NULL,'NASCAR Thunder 2003',0), - (645,'dtr2',NULL,'Dirt Track Racing II',0), - (646,'GameSpy.com',NULL,'GameSpy.com',0), - (647,'fileplanet',NULL,'FilePlanet.com',0), - (648,'gored',NULL,'Gore Retail Demo',0), - (649,'darkheaven',NULL,'Dark Heaven',0), - (650,'twc',NULL,'Takeout Weight Curling',0), - (651,'steeltide',NULL,'Operation Steel Tide',0), - (652,'realwarrs',NULL,'Real War: Rogue States',0), - (653,'ww2frontline',NULL,'World War II: Frontline Command',0), - (654,'rmth2003',NULL,'Trophy Hunter 2003',0), - (655,'strongholdc',NULL,'Stronghold: Crusader',0), - (656,'soa',NULL,'Soldiers of Anarchy',0), - (657,'jbnightfire',NULL,'James Bond: Nightfire',0), - (658,'sumofallfears',NULL,'The Sum of All Fears',0), - (659,'nfs6',NULL,'Need For Speed: Hot Pursuit 2',0), - (660,'bangler2003',NULL,'Bass Angler 2003',0), - (661,'netathlon2',NULL,'NetAthlon',0), - (662,'sfc3',NULL,'Starfleet Command III',0), - (663,'ddozenpt',NULL,'Deadly Dozen: Pacific Theater',0), - (664,'vietnamso',NULL,'Line of Sight: Vietnam',0), - (665,'mt2003',NULL,'Monopoly 2003',0), - (666,'soad',NULL,'Soldiers of Anarchy Demo',0), - (667,'celtickingsdemo',NULL,'Celtic Kings Demo',0), - (668,'ironstorm',NULL,'Iron Storm',0), - (669,'civ3ptw',NULL,'Civilization III: Play the World',0), - (670,'tron20',NULL,'TRON 2.0',0), - (671,'bfield1942d',NULL,'Battlefield 1942 Demo',0), - (672,'scrabble3',NULL,'Scrabble 3',0), - (673,'vietcong',NULL,'Vietcong',0), - (674,'th2003d',NULL,'Trophy Hunter 2003 Demo',0), - (675,'ccgenerals',NULL,'Command & Conquer: Generals',0), - (676,'sfc3dv',NULL,'Starfleet Command III (Dynaverse)',0), - (677,'bandits',NULL,'Bandits: Phoenix Rising',0), - (678,'xar',NULL,'Xtreme Air Racing',0), - (679,'echelonww',NULL,'Echelon Wind Warriors',0), - (683,'dtr2d',NULL,'Dirt Track Racing 2 Demo',0), - (684,'mclub2ps2',NULL,'Midnight Club 2 (PS2)',0), - (689,'dh2003',NULL,'Deerhunter 2003',0), - (690,'hwbasharena',NULL,'Hot Wheels Bash Arena',0), - (691,'robotarena2',NULL,'Robot Arena 2',0), - (692,'monopoly3',NULL,'Monopoly 3',0), - (693,'banditsd',NULL,'Bandits: Phoenix Rising Demo',0), - (694,'painkiller',NULL,'Painkiller',0), - (695,'revolution',NULL,'Revolution',0), - (696,'ddozenptd',NULL,'Deadly Dozen Pacific Theater Demo',0), - (697,'ironstormd',NULL,'Iron Storm Demo',0), - (698,'strikefighters1',NULL,'Strike Fighters: Project',0), - (699,'moo3',NULL,'Master of Orion III',0), - (700,'suddenstrike2',NULL,'Sudden Strike II',0), - (701,'mostwanted',NULL,'Most Wanted',0), - (702,'gicombat1',NULL,'G.I. Combat',0), - (703,'projectigi2',NULL,'IGI 2: Covert Strike Demo',0), - (704,'realwarrsd',NULL,'Real War: Rogue States Demo',0), - (705,'pnomads',NULL,'Project Nomads',0), - (706,'thps5ps2',NULL,'Tony Hawk\'s Underground (PS2)',0), - (707,'strongholdcd',NULL,'Stronghold: Crusader Demo',0), - (708,'blitzkrieg',NULL,'Blitzkrieg',0), - (709,'woosc',NULL,'World of Outlaws Sprint Cars',0), - (710,'vietcongd',NULL,'Vietcong Demo',0), - (711,'hlwarriors',NULL,'Highland Warriors',0), - (712,'mohaasd',NULL,'Medal of Honor: Allied As',0), - (713,'bfield1942rtr',NULL,'Battlefield 1942: Road to Rome',0), - (714,'horserace',NULL,'HorseRace',0), - (715,'netathlon',NULL,'NetAthlon',0), - (716,'ccgeneralsb',NULL,'Command & Conquer: Generals Beta',0), - (717,'sandbags',NULL,'Sandbags and Bunkers',0), - (718,'crttestdead',NULL,'CRT - TEST',0), - (719,'nolf2',NULL,'No One Lives Forever 2',0), - (720,'wkingsb',NULL,'Warrior Kings Battles',0), - (721,'riseofnations',NULL,'Rise of Nations',0), - (722,'worms3','fZDYBO','Worms 3D',0), - (723,'castles',NULL,'Castles and Catapluts',0), - (724,'mech4merc',NULL,'MechWarrior 4: Mercenarie',0), - (725,'orbb',NULL,'O.R.B: Off-World Resource Base Beta',0), - (726,'echelonwwd',NULL,'Echelon Wind Warriors Demo',0), - (728,'snooker2003',NULL,'Snooker 2003',0), - (729,'jeopardyps2',NULL,'Jeopardy (PS2)',0), - (730,'riskps2',NULL,'Risk (PS2)',0), - (731,'wofps2',NULL,'Wheel of Fortune (PS2)',0), - (732,'dhunterps2',NULL,'Deer Hunter (PS2)',0), - (733,'trivialppc',NULL,'Trivial Pursuit (PC) US',0), - (734,'trivialpps2',NULL,'Trivial Pursuit (PS2)',0), - (735,'projectigi2d',NULL,'IGI 2: Covert Strike Demo',0), - (736,'projectigi2r',NULL,'IGI 2 Covert Strike',0), - (738,'il2sturmovikfb',NULL,'IL-2 Sturmovik Forgotten Battles',0), - (739,'wooscd',NULL,'World of Outlaws Sprint Cars Demo',0), - (740,'nthunder2004',NULL,'NASCAR Thunder 2004',0), - (741,'f1comp',NULL,'F1 1999-2000 Compilation',0), - (742,'nomansland',NULL,'No Mans Land',0), - (743,'nwnxp1',NULL,'Neverwinter Nights: Shado',0), - (744,'praetoriansd',NULL,'Praetorians Demo',0), - (745,'nrs2003',NULL,'NASCAR Racing Season 2003',0), - (746,'gmtestam',NULL,'test (Auto-Matchmaking)',0), - (747,'nolf2d',NULL,'No One Lives Forever: The Operative 2 Demo',0), - (748,'devastation',NULL,'Devastation',0), - (749,'blitz2004ps2',NULL,'NFL Blitz 2004 (PS2)',0), - (750,'hd2',NULL,'Hidden and Dangerous 2',0), - (751,'hd2b',NULL,'Hidden and Dangerous 2 Beta',0), - (754,'hd2d',NULL,'Hidden and Dangerous 2 Demo',0), - (755,'mrpantsqm',NULL,'Mr. Pants QuickMatch',0), - (756,'moutlawne',NULL,'Midnight Outlaw Nitro',0), - (757,'vietnamsod',NULL,'Line of Sight: Vietnam Demo',0), - (758,'lionheart',NULL,'Lionheart',0), - (759,'medievalvi',NULL,'Medieval Total War Viking Invasion',0), - (760,'black9pc',NULL,'Black9 (PC)',0), - (761,'black9ps2',NULL,'Black9 (PS2)',0), - (762,'cmanager3',NULL,'Cycling Manager 3',0), - (764,'devastationd',NULL,'Devastation Demo',0), - (765,'hitz2004ps2',NULL,'NHL Hitz 2004 PS2',0), - (766,'wkingsbd',NULL,'Warrior Kings Battles Demo',0), - (767,'chaserd',NULL,'Chaser Demo',0), - (768,'motogp2',NULL,'MotoGP 2',0), - (769,'motogp2d',NULL,'MotoGP 2 Demo',0), - (770,'racedriverd',NULL,'Race Driver Demo',0), - (771,'empiresam',NULL,'Empires Dawn of the Modern World (AM)',0), - (772,'empires',NULL,'Empires: Dawn of the Modern World',0), - (773,'crashnitro',NULL,'Crash Nitro Carts',0), - (774,'breed',NULL,'Breed',0), - (775,'breedd',NULL,'Breed Demo',0), - (776,'homeworld2',NULL,'Homeworld 2',0), - (777,'moo3a',NULL,'Master of Orion III',0), - (778,'nwnmac',NULL,'Neverwinter Nights (Mac)',0), - (779,'ravenshield',NULL,'Raven Shield',0), - (780,'stef2',NULL,'Star Trek: Elite Force II',0), - (781,'spacepod',NULL,'SpacePod',0), - (782,'agrome',NULL,'Against Rome',0), - (783,'bfield1942sw',NULL,'Battlefield 1942: Secret Weapons of WW2',0), - (784,'thps4pc',NULL,'Tony Hawk: Pro Skater 4 (PC)',0), - (785,'omfbattled',NULL,'One Must Fall Battlergounds Demo',0), - (786,'nwnlinux',NULL,'Neverwinter Nights (Linux)',0), - (787,'blitz2004ps2e',NULL,'NFL Blitz Pro 2004 E3 (PS2)',0), - (788,'blitz2004ps2b',NULL,'NFL Blitz Pro 2004 Beta (PS2)',0), - (789,'homeworld2b',NULL,'Homeworld 2 Beta',0), - (790,'halo',NULL,'Halo Beta',0), - (791,'lotr3',NULL,'Lords of the Realm III',0), - (792,'lotr3b',NULL,'Lords of the Realm III Beta',0), - (793,'halor',NULL,'Halo: Combat Evolved',0), - (794,'bllrs2004ps2',NULL,'NBA Ballers (PS2)',0), - (795,'rtcwett',NULL,'Wolfenstein: Enemy Territory Test',0), - (796,'mclub2pc',NULL,'Midnight Club 2 (PC)',0), - (797,'jacknick6',NULL,'Jack Nicklaus Golden Bear',0), - (798,'wotr',NULL,'War of the Ring',0), - (799,'terminator3',NULL,'Terminator 3',0), - (800,'fwarriorpc',NULL,'Fire Warrior',0), - (801,'fwarriorps2',NULL,'Fire Warrior (PS2)',0), - (802,'mohaab',NULL,'Medal of Honor: Allied Assault Breakthrough',0), - (803,'aow3',NULL,'Age of Wonders: Shadow Magic (aow3)',0), - (804,'E3_2003',NULL,'E3_2003',0), - (805,'aowsm',NULL,'Age of Wonders: Shadow Magic (aowsm)',0), - (806,'specialforces',NULL,'Special Forces',0), - (807,'spartan',NULL,'Spartan & Spartan',0), - (808,'dod',NULL,'Day of Defeat',0), - (809,'tron20d',NULL,'TRON 2.0 Demo',0), - (810,'omfbattleb',NULL,'One Must Fall Battlegrounds',0), - (811,'bfield1942swd',NULL,'Battlefield 1942: Secret Weapons of WW2 Demo',0), - (813,'rtcwet',NULL,'Wolfenstein: Enemy Territory',0), - (814,'mphearts',NULL,'mphearts',0), - (815,'hotrod',NULL,'Hot Rod, American Street Drag',0), - (816,'civ3con',NULL,'Civilization III: Conquests',0), - (817,'civ3conb',NULL,'Civilization III: Conquests Beta',0), - (818,'riseofnationsam',NULL,'Rise of Nations Auto-Matching',0), - (819,'afrikakorps',NULL,'Afrika Korps',0), - (820,'apocalypticadi',NULL,'Apocalyptica',0), - (821,'robotech2',NULL,'Robotech 2 (PS2)',0), - (822,'spacepodd',NULL,'Space Pod Demo',0), - (823,'ccgenzh',NULL,'Command & Conquer: Generals – Zero Hour',0), - (824,'ronb',NULL,'Rise of Nations Beta',0), - (825,'ronbam',NULL,'Rise of Nations Beta (Automatch)',0), - (826,'commandos3',NULL,'Commandos 3',0), - (827,'exigo',NULL,'Armies of Exigo',0), - (828,'dh2004',NULL,'Deer Hunter 2004',0), - (830,'dh2004d',NULL,'Deer Hunter 2004 Demo',0), - (831,'armygamemac',NULL,'Americas Army: Special Forces (Mac)',0), - (832,'bridgebaron14',NULL,'Bridge Baron',0), - (833,'jk3',NULL,'Star Wars Jedi Knight: Jedi Academy',0), - (834,'anno1503b',NULL,'Anno 1503 Beta',0), - (835,'contractjack',NULL,'Contract Jack',0), - (836,'postal2',NULL,'Postal 2',0), - (837,'ut2004',NULL,'Unreal Tournament 2004',0), - (838,'ut2004d',NULL,'Unreal Tournament 2004 Demo',0), - (839,'contractjackd',NULL,'Contract Jack Demo',0), - (840,'empiresd',NULL,'Empires: Dawn of the Modern World Demo',0), - (841,'empiresdam',NULL,'Empires: Dawn of the Modern World',0), - (842,'mtgbgrounds',NULL,'Magic The Gathering: Battlegrounds',0), - (843,'groundcontrol2',NULL,'Ground Control 2',0), - (844,'bfield1942ps2',NULL,'Battlefield Modern Combat (PS2)',0), - (845,'dsiege2',NULL,'Dungeon Siege 2 The Azunite Prophecies',0), - (846,'judgedredddi',NULL,'Judge Dredd',0), - (847,'coldwinter',NULL,'Cold Winter',0), - (848,'haegemoniaxp',NULL,'Hegemonia Expansion',0), - (849,'asbball2005ps2',NULL,'All-star Baseball 2005',0), - (850,'castlestrike',NULL,'Castle Strike',0), - (851,'homeworld2d',NULL,'Homeworld 2 Demo',0), - (852,'callofduty',NULL,'Call of Duty',0), - (853,'mohaabd',NULL,'Medal of Honor: Allied Assault Breakthrough Demo',0), - (854,'twc2',NULL,'Takeout Weight Curling 2',0), - (855,'nthunder2004d',NULL,'NASCAR Thunder 2004 Demo',0), - (856,'moutlawned',NULL,'Midnight Outlaw Illegal Street Drag Nitro Edition Demo',0), - (857,'mta',NULL,'Multi Theft Auto',0), - (859,'railty3',NULL,'Railroad Tycoon 3',0), - (860,'spellforce',NULL,'Spellforce',0), - (861,'halomac',NULL,'Halo (Mac)',0), - (862,'contractjackpr',NULL,'Contract Jack PR',0), - (864,'wotrb',NULL,'War of the Ring Beta',0), - (865,'halod',NULL,'Halo Demo',0), - (866,'wcpool2004ps2',NULL,'World Championship Pool 2004 (PS2)',0), - (867,'fairstrike',NULL,'Fair Strike',0), - (868,'aarts',NULL,'Axis and Allies RTS',0), - (869,'nwnxp2',NULL,'Neverwinter Nights: Hordes of Underdark',0), - (870,'lotrbme',NULL,'Lord of the Rings: The Battle For Middle-Earth',0), - (871,'mototrax',NULL,'Moto Trax',0), - (872,'painkillerd',NULL,'Painkiller Demo',0), - (873,'painkillert',NULL,'Painkiller Multiplayer Test',0), - (874,'entente',NULL,'The Entente',0), - (876,'sforces',NULL,'Special Forces',0), - (877,'slugfestps2',NULL,'Slugfest Pro (PS2)',0), - (878,'mohpa',NULL,'Medal of Honor: Pacific Assault',0), - (879,'battlemages',NULL,'Battle Mages',0), - (880,'bfvietnam',NULL,'Battlefield: Vietnam',0), - (881,'planetside',NULL,'PlanetSide',0), - (882,'daoc',NULL,'Dark Age of Camelot',0), - (883,'uotd',NULL,'Ultima Online Third Dawn',0), - (884,'swg',NULL,'Star Wars Galaxies',0), - (885,'eq',NULL,'Everquest',0), - (886,'kohankow',NULL,'Kohan: Kings of War',0), - (887,'serioussamps2',NULL,'Serious Sam (PS2)',0), - (888,'omfbattlecp',NULL,'One Must Fall Battlegrounds (GMX)',0), - (889,'fairstriked',NULL,'Fair Strike Demo',0), - (890,'celtickingspu',NULL,'Nemesis of the Roman Empire',0), - (891,'test',NULL,'Test',0), - (892,'truecrime',NULL,'True Crime',0), - (895,'unreal2d',NULL,'Unreal 2 Demo',0), - (896,'links2004',NULL,'Links 2004',0), - (897,'terminator3d',NULL,'Terminator 3 Demo',0), - (900,'wcpool2004pc',NULL,'World Championship Pool 2004',0), - (901,'postal2d',NULL,'Postal 2 Demo',0), - (902,'unreal2demo',NULL,'Unreal 2 Demo',0), - (903,'spellforced',NULL,'Spellforce Demo',0), - (904,'le_projectx',NULL,'Legend Entertainment Project X',0), - (905,'racedriver2',NULL,'Race Driver 2',0), - (906,'bomberfunt',NULL,'BomberFUN Tournament',0), - (907,'pbfqm',NULL,'PlanetBattlefield QuickMatch',0), - (908,'gangland',NULL,'Gangland',0), - (909,'halomacd',NULL,'Halo Demo (Mac)',0), - (910,'juicedpc',NULL,'Juiced (PC)',0), - (911,'juicedps2',NULL,'Juiced (PS2)',0), - (913,'tribesv',NULL,'Tribes Vengeance',0), - (914,'racedriver2ps2',NULL,'Race Driver 2 (PS2)',0), - (915,'racedriver2d',NULL,'Race Driver 2 Demo',0), - (916,'indycarps2',NULL,'Indycar Series (PS2)',0), - (917,'thps6ps2',NULL,'Tony Hawks Underground 2 (PS2)',0), - (918,'sniperelps2',NULL,'Sniper Elite (PS2)',0), - (920,'bllrs2004ps2d',NULL,'NBA Ballers Demo (PS2)',0), - (921,'saturdayns',NULL,'Saturday Night Speedway',0), - (922,'rometw',NULL,'Rome: Total War',0), - (923,'conan',NULL,'Conan: The Dark Axe',0), - (924,'rontp',NULL,'Rise of Nations: Throne and Patriots',0), - (925,'rontpam',NULL,'Rise of Nations: Throne and Patriots (Automatch)',0), - (926,'dmhand',NULL,'Dead Man Hand',0), - (927,'upwords',NULL,'upwords',0), - (928,'saturdaynsd',NULL,'Saturday Night Speedway Demo',0), - (929,'scrabbledel',NULL,'Scrabble Deluxe',0), - (930,'dsiege2am',NULL,'Dungeon Siege 2 The Azunite Prophecies (Automatch)',0), - (931,'cmr4pc',NULL,'Colin McRae Rally 4 (PC)',0), - (932,'kumawar',NULL,'Kuma War',0), - (933,'cmr4pcd',NULL,'Colin McRae Rally 4 Demo (PC)',0), - (939,'afrikakorpsd',NULL,'Desert Rats vs. Afrika Korps Demo',0), - (940,'crashnburnps2',NULL,'Crash N Burn (PS2)',0), - (941,'spartand',NULL,'Spartan Demo',0), - (942,'ace',NULL,'A.C.E.',0), - (944,'perimeter',NULL,'Perimeter',0), - (945,'ilrosso',NULL,'Il Rosso e Il Nero - The Italian Civil War',0), - (946,'whammer40000',NULL,'Warhammer 40,000: Dawn of War',0), - (947,'swat4',NULL,'SWAT 4',0), - (948,'eearth2','h3C2jU','Empire Earth 2',0), - (949,'tribesvd',NULL,'Tribes Vengeance Demo',0), - (950,'tribesvb',NULL,'Tribes Vengeance Beta',0), - (951,'ganglandd',NULL,'Gangland Demo',0), - (952,'sniperelpc',NULL,'Sniper Elite (PC)',0), - (954,'altitude',NULL,'Altitude',0), - (955,'fsx',NULL,'Flight Simulator 2006',0), - (956,'hotwheels2pc',NULL,'Hot Wheels 2 (PC)',0), - (957,'hotwheels2ps2',NULL,'Hot Wheels 2 (PS2)',0), - (958,'hotwheels2pcd',NULL,'Hot Wheels 2 Demo (PC)',0), - (959,'cnpanzers',NULL,'Codename Panzers',0), - (960,'gamepopulator',NULL,'Game Populator',0), - (961,'gamepopulatoram',NULL,'Game Populator (Automatch)',0), - (963,'livewire',NULL,'GameSpy Livewire',0), - (964,'ravenshieldas',NULL,'Raven Shield: Athena\'s Sword',0), - (965,'fear',NULL,'FEAR: First Encounter Assault Recon',0), - (966,'tron20mac',NULL,'TRON 2.0 (Mac)',0), - (967,'s_cstrikecz',NULL,'Steam Counter-Strike: Condition Zero',0), - (968,'wingsofwar',NULL,'Wings of War',0), - (969,'mxun05ps2',NULL,'MX Unleashed 05 (PS2)',0), - (970,'mxun05ps2am',NULL,'MX Unleashed 05 (PS2) (Automatch)',0), - (971,'swbfrontps2',NULL,'Star Wars: Battlefront (PS2, Japan)',0), - (973,'swbfrontpc',NULL,'Star Wars: Battlefront (PC)',0), - (974,'perimeterd',NULL,'Perimeter Demo',0), - (975,'wracing1',NULL,'World Racing 1',0), - (976,'wormsforts','y3Gc8n','Worms Forts: Under Siege',0), - (977,'mohaamac',NULL,'Medal of Honor: Allied Assault (Mac)',0), - (978,'mohaasmac',NULL,'Medal of Honor: Allied Assault Spearhead (Mac)',0), - (979,'mohaabmac',NULL,'Medal of Honor: Breakthrough (Mac)',0), - (980,'bfield1942mac',NULL,'Battlefield 1942 (Mac)',0), - (981,'bfield1942rtrm',NULL,'Battlefield 1942 Road to Rome (Mac)',0), - (982,'halom',NULL,'Halo Multiplayer Expansion',0), - (983,'nitrofamily',NULL,'Nitro Family',0), - (984,'besieger',NULL,'Besieger',0), - (986,'mkdeceptionps2',NULL,'Mortal Kombat Deceptions (PS2)',0), - (987,'swrcommando',NULL,'Star Wars: Republic Commando',0), - (988,'fightclubps2',NULL,'Fight Club (PS2)',0), - (989,'area51ps2',NULL,'Area 51 (PS2)',0), - (990,'dday',NULL,'D-Day',0), - (991,'exigoam',NULL,'Armies of Exigo (Automatch)',0), - (992,'mohaabdm',NULL,'Medal of Honor: Allied Assault Breakthrough Demo (Mac)',0), - (993,'mkdeceppalps2',NULL,'Mortal Kombat Deception PAL (PS2)',0), - (994,'civ4b',NULL,'Civilization 4 Beta',0), - (995,'topspin',NULL,'Top Spin',0), - (996,'bllrs2004pal',NULL,'NBA Ballers PAL (PS2)',0), - (997,'whammer40000am',NULL,'Warhammer 40,000: Dawn of War',0), - (999,'scrabbleo',NULL,'Scrabble Online',0), - (1000,'wcsnkr2004ps2',NULL,'World Championship Snooker 2004 (PS2)',0), - (1001,'olg2PS2',NULL,'Outlaw Golf 2 PS2',0), - (1002,'gtasaps2',NULL,'Grand Theft Auto San Andreas (PS2)',0), - (1003,'thps6pc',NULL,'T.H.U.G. 2',0), - (1004,'smackdnps2',NULL,'WWE Smackdown vs RAW Sony Beta (PS2)',0), - (1005,'thps5pc',NULL,'Tony Hawks Underground (PC)',0), - (1006,'menofvalor',NULL,'Men of Valor',0), - (1007,'srsyndps2',NULL,'Street Racing Syndicate (PS2)',0), - (1008,'gc2demo',NULL,'Ground Control 2 Demo',0), - (1009,'fswpc','R5pZ29','Full Spectrum Warrior',0), - (1010,'soldiersww2',NULL,'Soldiers: Heroes of World War II',0), - (1011,'mtxmototrax',NULL,'MTX MotoTrax',0), - (1012,'pbfqmv',NULL,'PlanetBattlefield QuickMatch Vietnam',0), - (1013,'wcsnkr2004pc',NULL,'World Championship Snooker 2004 (PC)',0), - (1014,'locomotion',NULL,'Chris Sawyer\'s Locomotion',0), - (1015,'gauntletps2',NULL,'Gauntlet (PS2)',0), - (1016,'gotcha',NULL,'Gotcha!',0), - (1017,'menofvalord',NULL,'Men of Valor Demo',0), - (1019,'knightsoh',NULL,'Knights of Honor',0), - (1020,'wingsofward',NULL,'Wings of War Demo',0), - (1021,'cmr5ps2',NULL,'Colin McRae Rally 5 (PS2)',0), - (1022,'callofdutyps2',NULL,'Call of Duty (PS2)',0), - (1023,'crashnburnps2b',NULL,'Crash N Burn Sony Beta (PS2)',0), - (1024,'hotrod2',NULL,'Hot Rod 2: Garage to Glory',0), - (1025,'mclub3ps2',NULL,'Midnight Club 3 DUB Edition (PS2)',0), - (1027,'trivialppalps2',NULL,'Trivial Pursuit PAL (PS2)',0), - (1028,'trivialppalpc',NULL,'Trivial Pursuit PAL (PC)',0), - (1029,'hd2ss',NULL,'Hidden & Dangerous 2 - Sabre Squadron',0), - (1030,'whammer40kb',NULL,'Warhammer 40,000: Dawn of War Beta',0), - (1031,'whammer40kbam',NULL,'Warhammer 40,000: Dawn of War Beta (Automatch)',0), - (1032,'srsyndpc',NULL,'Street Racing Syndicate (PC)',0), - (1033,'ddayd',NULL,'D-Day Demo',0), - (1034,'godzilla2ps2',NULL,'Godzilla: Save the Earth (PS2)',0), - (1035,'actofwar',NULL,'Act of War: Direct Action',0), - (1036,'juicedpalps2',NULL,'Juiced PAL (PS2)',0), - (1037,'statesmen',NULL,'Statesmen',0), - (1038,'conflictsopc','vh398A','Conflict: Special Ops (PC)',0), - (1039,'conflictsops2',NULL,'Conflict: Special Ops (PS2)',0), - (1040,'dh2005',NULL,'Deer Hunter 2005',0), - (1041,'gotchad',NULL,'Gotcha! Demo',0), - (1042,'eearth2d','h3C2jU','Empire Earth 2 Demo',0), - (1043,'smackdnps2pal',NULL,'WWE Smackdown vs RAW PAL (PS2)',0), - (1044,'wcpokerps2',NULL,'World Championship Poker (PS2)',0), - (1045,'cmr5pc',NULL,'Colin McRae Rally 5 (PC)',0), - (1046,'dh2005d',NULL,'Deer Hunter 2005 Demo',0), - (1048,'callofdutyps2d',NULL,'Call of Duty Sony Beta (PS2)',0), - (1049,'doom3',NULL,'Doom 3',0), - (1050,'cmr5pcd',NULL,'Colin McRae Rally 5 Demo (PC)',0), - (1051,'spoilsofwar',NULL,'Spoils of War',0), - (1052,'saadtest',NULL,'SaadsTest',0), - (1054,'superpower2',NULL,'Super Power 2',0), - (1055,'swat4d',NULL,'SWAT 4 Demo',0), - (1056,'exigob',NULL,'Armies of Exigo Beta',0), - (1057,'exigobam',NULL,'Armies of Exigo Beta (Automatch)',0), - (1058,'knightsohd',NULL,'Knights of Honor Demo',0), - (1059,'battlefield2',NULL,'Battlefield 2',0), - (1060,'actofwaram',NULL,'Act of War: Direct Action (Automatch)',0), - (1061,'bf1942swmac',NULL,'Battlefield 1942: Secret Weapons of WW2 Mac',0), - (1062,'closecomftf',NULL,'Close Combat: First to Fight',0), - (1063,'closecomftfmac',NULL,'Close Combat: First to Fight Mac',0), - (1064,'kohankowd',NULL,'Kohan: Kings of War Demo',0), - (1066,'swempire',NULL,'Star Wars: Empire at War',0), - (1067,'stalkersc',NULL,'STALKER: Shadows of Chernobyl',0), - (1068,'poolshark2ps2',NULL,'Pool Shark 2 (PS2)',0), - (1069,'poolshark2pc',NULL,'Pool Shark 2 (PC)',0), - (1070,'smackdnps2kor',NULL,'WWE Smackdown vs RAW (PS2) Korean',0), - (1071,'smackdnps2r',NULL,'WWE Smackdown vs RAW (PS2) Retail',0), - (1072,'callofdutyuo',NULL,'Call of Duty: United Offensive',0), - (1073,'swbfrontps2p',NULL,'Star Wars: Battlefront (PS2)',0), - (1074,'trivialppcuk',NULL,'Trivial Pursuit (PC) UK',0), - (1075,'trivialppcfr',NULL,'Trivial Pursuit (PC) French',0), - (1076,'trivialppcgr',NULL,'Trivial Pursuit (PC) German',0), - (1077,'trivialppcit',NULL,'Trivial Pursuit (PC) Italian',0), - (1078,'trivialppcsp',NULL,'Trivial Pursuit (PC) Spanish',0), - (1079,'smackdnps2palr',NULL,'WWE Smackdown vs RAW (PS2) PAL Retail',0), - (1080,'aartsd',NULL,'Axis and Allies RTS demo',0), - (1081,'blitzkriegrt',NULL,'Blitzkrieg: Rolling Thunder',0), - (1082,'dungeonlords',NULL,'Dungeon Lords',0), - (1083,'SpyNote',NULL,'Server Monitor',0), - (1085,'blitz2005ps2',NULL,'Blitz: The League 2005',0), - (1086,'rof',NULL,'Rise of Legends',0), - (1087,'rofam',NULL,'Rise of Legends (Automatch)',0), - (1088,'nsr0405',NULL,'NASCAR Sim Racing (2005)',0), - (1089,'ffvsttr',NULL,'Freedom Force vs. The Third Reich',0), - (1092,'dshard',NULL,'The Dragonshard Wars',0), - (1093,'mohpad',NULL,'Medal of Honor: Pacific Assault Demo',0), - (1094,'exigor',NULL,'Armies of Exigo Retail',0), - (1095,'exigoram',NULL,'Armies of Exigo (Automatch)',0), - (1096,'bfield1942t',NULL,'Battlefield 1942 Testing',0), - (1099,'bfvietnamt',NULL,'Battlefield: Vietnam Testing',0), - (1101,'civ4','y3D9Hw','Civilization IV',0), - (1102,'civ4am','y3D9Hw','Civilization IV (Automatch)',0), - (1103,'regimentpc',NULL,'The Regiment PC',0), - (1104,'regimentps2',NULL,'The Regiment PS2',0), - (1105,'olvps2',NULL,'Outlaw Volleyball PS2',0), - (1106,'battlefield2d',NULL,'Battlefield 2 Demo',0), - (1108,'fswps2',NULL,'Full Spectrum Warrior PS2',0), - (1109,'dshardam',NULL,'The Dragonshard Wars (Automatch)',0), - (1110,'spoilsofwaram',NULL,'Spoils of War (Automatch)',0), - (1111,'source',NULL,'Half Life 2',0), - (1112,'s_cssource',NULL,'Counter-Strike Source',0), - (1113,'feard',NULL,'FEAR: First Encounter Assault Recon Demo',0), - (1114,'s_hl2dm',NULL,'s_hl2dm',0), - (1115,'bfield1942ps2b',NULL,'Battlefield Modern Combat (PS2) Beta',0), - (1116,'whammer40kt',NULL,'Warhammer 40000: Dawn of War test',0), - (1117,'firecapbay',NULL,'Fire Captain: Bay Area Inferno',0), - (1118,'splintcellchaos',NULL,'splintcellchaos',0), - (1119,'fswps2pal',NULL,'Full Spectrum Warrior PAL PS2',0), - (1120,'fearcb',NULL,'FEAR: First Encounter Assault Recon (Closed Beta)',0), - (1121,'fearob',NULL,'FEAR: First Encounter Assault Recon (Open Beta)',0), - (1122,'ejammingpc',NULL,'eJamming Jamming Station PC',0), - (1123,'ejammingmac',NULL,'eJamming Jamming Station MAC (engine)',0), - (1124,'wcpokerpalps2',NULL,'World Championship Poker PAL (PS2)',0), - (1125,'titanquest',NULL,'Titan Quest',0), - (1126,'wcsnkr2005ps2',NULL,'World Championship Snooker 2005 PS2',0), - (1127,'wcsnkr2005',NULL,'World Championship Snooker 2005 (PC)',0), - (1128,'thps7ps2',NULL,'Tony Hawks American Wasteland (PS2)',0), - (1129,'pariahpc',NULL,'Pariah (PC)',0), - (1130,'impglory',NULL,'Imperial Glory',0), - (1132,'swrcommandoj',NULL,'Star Wars Republic Commando Japanese Dist',0), - (1133,'oltps2',NULL,'Outlaw Tennis PS2',0), - (1134,'wptps2',NULL,'World Poker Tour PS2',0), - (1135,'blkhwkdnps2',NULL,'Delta Force: Black Hawk Down (PS2)',0), - (1137,'motogp3',NULL,'MotoGP 3',0), - (1138,'cmmwcpoker',NULL,'Chris Moneymakers World Championship Poker',0), - (1139,'ddayxp1',NULL,'D-Day: 1944 Battle of the Bulge',0), - (1140,'spcell3coop',NULL,'Splinter Cell 3 CoOp',0), - (1142,'ffvsttrd',NULL,'Freedom Force vs. The Third Reich MP Demo',0), - (1143,'topspinps2',NULL,'Top Spin (PS2)',0), - (1144,'betonsoldier',NULL,'Bet on Soldier',0), - (1145,'swrcommandot',NULL,'Star Wars Republic Commando Thai Dist',0), - (1146,'topspinps2am',NULL,'Top Spin (PS2) (Automatch)',0), - (1147,'vietcong2',NULL,'Vietcong 2',0), - (1148,'spyvsspyps2',NULL,'Spy vs Spy (PS2)',0), - (1149,'nitrosample',NULL,'Nitro Sample',0), - (1150,'flatoutps2',NULL,'Flat Out (PS2)',0), - (1151,'hotpacificps2',NULL,'Heroes of the Pacific (PS2)',0), - (1152,'hotpacificpc',NULL,'Heroes of the Pacific (PC)',0), - (1154,'cnpanzers2',NULL,'Codename Panzers Phase 2',0), - (1155,'stronghold2',NULL,'Stronghold 2',0), - (1156,'actofward',NULL,'Act of War: Direct Action Demo',0), - (1157,'actofwardam',NULL,'Act of War: Direct Action Demo (Automatch)',0), - (1158,'xmenlegpc',NULL,'X-Men Legends (PC)',0), - (1159,'xmenlegps2',NULL,'X-Men Legends (PS2)',0), - (1160,'coteagles',NULL,'War Front: Turning Point',0), - (1161,'area51pc',NULL,'Area 51 (PC)',0), - (1164,'area51pcb',NULL,'Area 51 (PC) Beta',0), - (1165,'fswps2kor',NULL,'Full Spectrum Warrior Korean (PS2)',0), - (1169,'stalinsubd',NULL,'The Stalin Subway Demo',0), - (1170,'supruler2010',NULL,'Supreme Ruler 2010',0), - (1171,'pariahpcd',NULL,'Pariah Demo (PC)',0), - (1172,'serioussam2',NULL,'Serious Sam 2 (PC)',0), - (1173,'riskingdoms',NULL,'Rising Kingdoms',0), - (1176,'stalinsub',NULL,'The Stalin Subway',0), - (1177,'bsmidwaypc',NULL,'Battlestations Midway (PC)',0), - (1178,'bsmidwayps2',NULL,'Battlestations Midway (PS2)',0), - (1179,'bsmidwaypcam',NULL,'Battlestations Midway (PC) (Automatch)',0), - (1180,'bsmidwayps2am',NULL,'Battlestations Midway PS2 (Automatch)',0), - (1181,'riskingdomsd',NULL,'Rising KIngdoms Demo',0), - (1182,'riskingdomsam',NULL,'Rising Kingdoms (Automatch)',0), - (1183,'wsoppc',NULL,'World Series of Poker (PC)',0), - (1184,'wsopps2',NULL,'World Series of Poker (PS2)',0), - (1185,'velocityps2',NULL,'Velocity PS2',0), - (1186,'velocitypc',NULL,'Velocity PC',0), - (1187,'swat4xp1',NULL,'SWAT 4: The Stetchkov Syndicate',0), - (1188,'hotpaceudps2',NULL,'Heroes of the Pacific EU Demo (PS2)',0), - (1189,'hotpacnadps2',NULL,'Heroes of the Pacific NA Demo (PS2)',0), - (1190,'gbrome','hEf6s9j','Great Battles of Rome',0), - (1191,'rafcivatwar',NULL,'Rise And Fall: Civilizations at War',0), - (1193,'rafcivatwaram',NULL,'Rise And Fall: Civilizations at War (Automatch)',0), - (1194,'fearobsc',NULL,'FEAR: First Encounter Assault Recon (Open Beta Special Content)',0), - (1195,'worms4','Bs28Kl','Worms 4 Mayhem',0), - (1196,'smackdn2ps2',NULL,'WWE Smackdown vs RAW 2 (PS2)',0), - (1197,'smackdn2ps2pal',NULL,'WWE Smackdown vs RAW 2 PAL (PS2)',0), - (1198,'smackdn2ps2kor',NULL,'WWE Smackdown vs RAW 2 Korea (PS2)',0), - (1199,'fsw10hps2',NULL,'Full Spectrum Warrior: Ten Hammers (PS2)',0), - (1200,'fsw10hpc','6w2X9m','Full Spectrum Warrior: Ten Hammers (PC)',0), - (1201,'fsw10hps2kor',NULL,'Full Spectrum Warrior: Ten Hammers (Korea, PS2)',0), - (1202,'fsw10hps2pal',NULL,'Full Spectrum Warrior: Ten Hammers (PAL, PS2)',0), - (1203,'swbfront2pc',NULL,'Star Wars Battlefront 2 PC',0), - (1204,'swbfront2ps2',NULL,'Star Wars Battlefront 2 (PS2)',0), - (1205,'swbfront2ps2j',NULL,'Star Wars Battlefront 2 (PS2) Japanese',0), - (1206,'worms4d','Bs28Kl','Worms 4 Mayhem Demo',0), - (1207,'whammer40kwa',NULL,'Warhammer 40,000: Winter Assault',0), - (1208,'whammer40kwaam',NULL,'Warhammer 40,000: Winter Assault (Automatch)',0), - (1209,'codbigredps2',NULL,'Call of Duty 2: Big Red One (PS2)',0), - (1210,'dsnattest',NULL,'ds nat test',0), - (1212,'xmenlegps2pal',NULL,'X-Men Legends PAL (PS2)',0), - (1213,'xmenlegps2pals',NULL,'X-Men Legends PAL Spanish (PS2)',0), - (1215,'gbromeam',NULL,'Great Battles of Rome (Automatch)',0), - (1216,'pbfqm2',NULL,'PlanetBattlefield QuickMatch 2',0), - (1217,'wsopps2am',NULL,'World Series of Poker (PS2) (Automatch)',0), - (1218,'wsoppcam',NULL,'World Series of Poker (PC) (Automatch)',0), - (1222,'motogp3d',NULL,'MotoGP 3 Demo',0), - (1223,'vietcong2d',NULL,'Vietcong 2 Demo',0), - (1224,'eearth2xp1','h3C2jU','Empire Earth II: The Art of Supremacy',0), - (1225,'afllive05ps2',NULL,'AFL Live 2005 (ps2)',0), - (1226,'fordvchevyps2',NULL,'Ford Versus Chevy (PS2)',0), - (1227,'hotpacificpcd',NULL,'Heroes of the Pacific PC Demo',0), - (1228,'hoodzps2',NULL,'Hoodz (PS2)',0), - (1229,'swbfront2pcb',NULL,'Star Wars Battlefront 2 PC Beta',0), - (1230,'swbfront2pcd',NULL,'Star Wars Battlefront 2 PC Demo',0), - (1231,'rtrooperps2',NULL,'Rogue Trooper (PS2)',0), - (1233,'fswps2jp',NULL,'Full Spectrum Warrior (PS2, Japanese)',0), - (1234,'and1sballps2',NULL,'AND1: Streetball Online (PS2)',0), - (1236,'swempiream',NULL,'Star Wars: Empire at War (Automatch)',0), - (1238,'mariokartds',NULL,'Mario Kart (DS)',0), - (1239,'genetrooperpc',NULL,'Gene Trooper (PC)',0), - (1240,'genetrooperps2',NULL,'Gene Troopers (PS2)',0), - (1241,'legionarena',NULL,'Legion Arena',0), - (1242,'kott2pc',NULL,'Knights of the Temple 2 (PC)',0), - (1243,'kott2ps2',NULL,'Knights of the Temple 2 (PS2)',0), - (1244,'hardtruck',NULL,'Hard Truck Tycoon',0), - (1245,'wracing2',NULL,'World Racing 2 (PC)',0), - (1246,'wsoppsp',NULL,'World Series of Poker (PSP)',0), - (1247,'wsoppspam',NULL,'World Series of Poker (PSP) (Automatch)',0), - (1248,'infectedpsp',NULL,'Infected (PSP)',0), - (1249,'infectedpspam',NULL,'Infected (PSP) (Automatch)',0), - (1251,'unavailable',NULL,'Test for disabled games',0), - (1252,'tempunavail',NULL,'Test for temporarily disabled games',0), - (1253,'betonsoldierd',NULL,'Bet On Soldier',0), - (1254,'ghpballps2',NULL,'Greg Hastings Paintball (PS2)',0), - (1255,'flatout',NULL,'FlatOut',0), - (1256,'bfield2xp1',NULL,'Battlefield 2: Special Forces',0), - (1257,'vietcong2pd',NULL,'Vietcong 2 Public Demo',0), - (1258,'thawds',NULL,'Tony Hawks American Wasteland (DS)',0), - (1259,'acrossingds',NULL,'Animal Crossing (DS)',0), - (1260,'coteaglessp',NULL,'War Front: Turning Point (Singleplayer)',0), - (1261,'and1sballps2am',NULL,'AND1: Streetball Online (PS2) (Automatch)',0), - (1262,'mariokartdsam',NULL,'Mario Kart (DS, Automatch)',0), - (1264,'acrossingdsam',NULL,'Animal Crossing (DS, Automatch)',0), - (1265,'xmenleg2psp',NULL,'X-Men: Legends 2 (PSP)',0), - (1266,'lotrbme2',NULL,'Lord of the Rings: The Battle for Middle-earth 2 (Beta)',0), - (1267,'shatteredunion',NULL,'Shattered Union',0), - (1268,'serioussam2d',NULL,'Serious Sam 2 Demo',0), - (1269,'bllrs2005ps2',NULL,'NBA Ballers 2005 (PS2)',0), - (1270,'bllrs2005ps2d',NULL,'NBA Ballers 2005 Demo (PS2)',0), - (1272,'mprimeds',NULL,'Metroid Prime Hunters (DS)',0), - (1273,'racedriver3pc',NULL,'Race Driver 3 (PC)',0), - (1274,'racedriver3pcd',NULL,'Race Driver 3 Demo (PC)',0), - (1275,'scsdw',NULL,'S.C.S. Dangerous Waters',0), - (1276,'scsdwd',NULL,'S.C.S. Dangerous Waters Demo',0), - (1277,'uchaosrrps2',NULL,'Urban Chaos: Riot Response (PS2)',0), - (1278,'uchaosrrps2am',NULL,'Urban Chaos: Riot Response Automatch (PS2)',0), - (1280,'rdriver3ps2',NULL,'Race Driver 3 (PS2)',0), - (1281,'rdriver3ps2d',NULL,'Race Driver 3 Demo (PS2)',0), - (1282,'wptps2pal',NULL,'World Poker Tour PAL (PS2)',0), - (1283,'rtrooperpc',NULL,'Rogue Trooper (PC)',0), - (1284,'rtrooperpcam',NULL,'Rogue Trooper Automatch (PC)',0), - (1285,'bf2sttest',NULL,'Battlefield 2 Snapshot testing',0), - (1289,'dsnattest2',NULL,'ds nat test 2',0), - (1290,'mxun05pc',NULL,'MX vs. ATV Unleashed (PC)',0), - (1291,'mxun05pcam',NULL,'MX vs. ATV Unleashed Automatch (PC)',0), - (1292,'quake4',NULL,'Quake 4',0), - (1293,'paraworld',NULL,'ParaWorld',0), - (1294,'paraworldam',NULL,'ParaWorld Automatch',0), - (1295,'paraworldd',NULL,'ParaWorld Demo',0), - (1296,'callofduty2',NULL,'Call of Duty 2',0), - (1297,'bfield1942ps2am',NULL,'Battlefield Modern Combat Automatch (PS2)',0), - (1298,'slugfest06ps2',NULL,'Slugfest \'06 (PS2)',0), - (1299,'bleachds',NULL,'Bleach (DS)',0), - (1300,'lostmagicds',NULL,'Lost Magic (DS)',0), - (1301,'wofor',NULL,'WOFOR: War on Terror',0), - (1302,'woforam',NULL,'WOFOR: War on Terror Automatch',0), - (1303,'woford',NULL,'WOFOR: War on Terror Demo',0), - (1305,'wofordam',NULL,'WOFOR: War on Terror Demo Automatch',0), - (1306,'Happinuds',NULL,'Happinuvectorone! (DS)',0), - (1307,'thawpc',NULL,'Tony Hawk\'s American Wasteland (PC)',0), - (1308,'ysstrategyds',NULL,'Y\'s Strategy (DS)',0), - (1309,'marvlegps2',NULL,'Marvel Legends (PS2)',0), - (1310,'marvlegps2am',NULL,'Marvel Legends Automatch (PS2)',0), - (1311,'marvlegpsp',NULL,'Marvel Legends (PSP, PAL)',0), - (1312,'marvlegpspam',NULL,'Marvel Legends Automatch (PSP, PAL)',0), - (1313,'marvlegpc',NULL,'Marvel Legends (PC)',0), - (1314,'marvlegpcam',NULL,'Marvel Legends Automatch (PC)',0), - (1315,'marvlegpcd',NULL,'Marvel Legends Demo (PC)',0), - (1316,'marvlegpcdam',NULL,'Marvel Legends Demo Automatch (PC)',0), - (1317,'hustleps2',NULL,'Hustle: Detroit Streets (PS2)',0), - (1318,'hustleps2am',NULL,'Hustle: Detroit Streets Automatch (PS2)',0), - (1320,'koshien2ds',NULL,'PowerPro Pocket Koshien 2 (DS)',0), - (1321,'lotrbme2r',NULL,'Lord of the Rings: The Battle for Middle-earth 2',0), - (1322,'tenchuds',NULL,'Tenchu (DS)',0), - (1323,'contactds',NULL,'Contact JPN (DS)',0), - (1324,'stella',NULL,'Battlefield 2142',0), - (1325,'stellad',NULL,'Battlefield 2142 (Demo)',0), - (1326,'runefactoryds',NULL,'Rune Factory (DS)',0), - (1327,'tetrisds',NULL,'Tetris DS (DS)',0), - (1328,'motogp4ps2',NULL,'MotoGP 4 (PS2)',0), - (1329,'actofwarht',NULL,'Act of War: High Treason',0), - (1330,'actofwarhtam',NULL,'Act of War: High Treason Automatch',0), - (1331,'actofwarhtd',NULL,'Act of War: High Treason Demo',0), - (1332,'actofwarhtdam',NULL,'Act of War: High Treason Demo Automatch',0), - (1333,'Customrobods',NULL,'Custom Robo DS (DS)',0), - (1334,'comrade',NULL,'Comrade',0), - (1335,'greconawf',NULL,'Ghost Recon: Advanced Warfighter',0), - (1336,'greconawfd',NULL,'Ghost Recon: Advanced Warfighter Demo',0), - (1337,'asobids',NULL,'Asobi Taizen (DS)',0), - (1338,'timeshift',NULL,'TimeShift (PC)',0), - (1339,'timeshiftb',NULL,'TimeShift Beta (PC)',0), - (1340,'scsdws',NULL,'S.C.S. Dangerous Waters Steam',0), - (1341,'ffurtdriftps2',NULL,'The Fast and the Furious: Tokyo Drift (PS2)',0), - (1342,'ffurtdriftps2am',NULL,'The Fast and the Furious: Tokyo Drift Automatch (PS2)',0), - (1344,'pokemondpds',NULL,'Pokemon Diamond-Pearl (DS)',0), - (1345,'coteaglesam',NULL,'War Front: Turning Point Automatch',0), - (1346,'facesofwar',NULL,'Faces of War',0), - (1347,'facesofwaram',NULL,'Faces of War Automatch',0), - (1348,'facesofward',NULL,'Faces of War Demo',0), - (1349,'bombermanslds',NULL,'Bomberman Story/Land DS',0), - (1350,'fherjwkk',NULL,'Namco Test',0), - (1351,'tiumeshiftu',NULL,'TimeShift (Unlock codes)',0), - (1352,'digistoryds',NULL,'Digimon Story (DS)',0), - (1353,'touchpanicds',NULL,'Touch Panic (DS)',0), - (1354,'SampAppTest',NULL,'Sample App Developement',0), - (1355,'SampAppTestam',NULL,'Sample App Developement Automatch',0), - (1358,'fearxp1',NULL,'FEAR: Extraction Point',0), - (1359,'narutorpg3ds',NULL,'Naruto RPG 3 (DS)',0), - (1360,'digistorydsam',NULL,'Digimon Story Automatch (DS)',0), - (1361,'redorchestra',NULL,'Red Orchestra Ostfront',0), - (1362,'airwingsds',NULL,'Air Wings (DS)',0), - (1363,'openseasonds',NULL,'OpenSeason DS (DS)',0), - (1364,'mageknight',NULL,'Mage Knight Apocalypse',0), - (1366,'mageknightd',NULL,'Mage Knight Apocalypse Demo',0), - (1367,'starfoxds',NULL,'Starfox DS (DS)',0), - (1368,'rockmanwds',NULL,'Rockman WAVES (DS)',0), - (1369,'medieval2',NULL,'Medieval 2 Total War',0), - (1370,'medieval2am',NULL,'Medieval 2 Total War Automatch',0), - (1371,'taisends',NULL,'Sangokushi Taisen DS (DS)',0), - (1372,'mkarmps2',NULL,'Mortal Kombat: Armageddon (PS2)',0), - (1373,'thps3pcr',NULL,'Tony Hawk 3 PC (Rerelease)',0), - (1374,'mmvdkds',NULL,'Mini Mario vs Donkey Kong (DS)',0), - (1375,'ffantasy3ds',NULL,'Final Fantasy III (DS)',0), - (1376,'marvlegps2p',NULL,'Marvel Legends PAL (PS2)',0), - (1377,'marvlegps2pam',NULL,'Marvel Legends Automatch PAL (PS2)',0), - (1378,'c5',NULL,'Conflict: Denied Ops',0), - (1379,'rfberlin',NULL,'Rush for Berlin',0), - (1380,'swat4xp1_tmp',NULL,'SWAT 4: The Stetchkov Syndicate Temp',0), - (1381,'swordots',NULL,'Sword of the Stars',0), - (1382,'mahjongkcds',NULL,'Mah-Jong Kakuto Club (DS)',0), - (1383,'whammermok',NULL,'Warhammer: Mark of Chaos (OLD)',0), - (1386,'Nushizurids',NULL,'Nushizuri DS Yama no megumi Kawa no seseragi',0), - (1387,'civ4wrld','oQ3v8V','Civilization IV: Warlords',0), - (1388,'civ4wrldam','oQ3v8V','Civilization IV: Warlords Automatch',0), - (1389,'dsiege2bw',NULL,'Dungeon Siege II: Broken World',0), - (1390,'blic2007',NULL,'Brian Lara International Cricket 2007',0), - (1391,'nwn2',NULL,'NeverWinter Nights 2',0), - (1392,'pssake',NULL,'Professional Services Sake Test',0), - (1393,'gmtestcd',NULL,'Test (Chat CD Key validation)',0), - (1394,'gmtestcdam',NULL,'Test Automatch (Chat CD Key validation)',0), - (1395,'yugiohgx2ds',NULL,'Yu-Gi-OH! Duel Monsters GX2 (DS)',0), - (1396,'whammermoc',NULL,'Warhammer: Mark of Chaos',0), - (1397,'whammermocam',NULL,'Warhammer: Mark of Chaos Automatch',0), - (1398,'whammermocd',NULL,'Warhammer: Mark of Chaos Demo',0), - (1399,'flatout2ps2',NULL,'FlatOut 2 (PS2)',0), - (1400,'cruciform',NULL,'Genesis Rising: The Universal Crusade',0), - (1401,'blkhwkdntsps2',NULL,'Delta Force: Black Hawk Down - Team Sabre (PS2)',0), - (1402,'socelevends',NULL,'World Soccer Winning Eleven DS (DS)',0), - (1403,'konductrads',NULL,'Konductra (DS)',0), - (1404,'strongholdl',NULL,'Stronghold Legends',0), - (1405,'wsc2007ps2',NULL,'World Snooker Championship 2007 (PS2)',0), - (1406,'wsc2007ps3',NULL,'World Snooker Championship 2007 (PS3)',0), - (1407,'ninsake',NULL,'Nintendo Sake Test',0), - (1408,'dwctest',NULL,'DWC NintendoTest App',0), - (1409,'FieldOps',NULL,'Field Ops',0), - (1410,'wcpoker2pc',NULL,'World Championship Poker 2 (PC)',0), - (1411,'whammer40kdc',NULL,'Warhammer 40,000: Dark Crusade',0), - (1412,'whammer40kdcam',NULL,'Warhammer 40,000: Dark Crusade Automatch',0), - (1413,'fullautops3',NULL,'Full Auto 2: Battlelines (PS3)',0), - (1414,'civ4jp',NULL,'Civiliation IV (Japanese)',0), - (1415,'civ4jpam',NULL,'Civiliation IV Automatch (Japanese)',0), - (1416,'contactusds',NULL,'Contact US (DS)',0), - (1417,'thps4pcr',NULL,'Tony Hawk: Pro Skater 4 (PC) Rerelease',0), - (1418,'thps4pcram',NULL,'Tony Hawk: Pro Skater 4 Automatch (PC) Rerelease',0), - (1419,'bf2ddostest',NULL,'Battlefield 2 DDoS testing',0), - (1420,'flatout2pc','GtGLyx','FlatOut 2 (PC)',0), - (1421,'smrailroads',NULL,'Sid Meier\'s Railroads!',0), - (1422,'cc3tibwars',NULL,'Command & Conquer 3: Tiberium Wars',0), - (1423,'topspin2pc',NULL,'Top Spin 2 (PC)',0), - (1424,'thdhilljamds',NULL,'Tony Hawk\'s Downhill Jam (DS)',0), - (1425,'aoex',NULL,'Age of Empires Expansion',0), - (1426,'rafcivatwart',NULL,'Rise And Fall: Civilizations at War Test',0), - (1427,'rafcivatwartam',NULL,'Rise And Fall: Civilizations at War Test Automatch',0), - (1428,'bokujomonods',NULL,'Bokujo Monogatari DS2: Wish-ComeTrue Island (DS)',0), - (1429,'tothrainbowds',NULL,'TOTH Rainbow Trail of Light (DS)',0), - (1430,'mkarmpalps2',NULL,'Mortal Kombat: Armageddon PAL (PS2)',0), - (1431,'preyd',NULL,'Prey Demo',0), - (1432,'prey',NULL,'Prey',0), - (1433,'jumpsstars2ds',NULL,'Jump Super Stars 2 (DS)',0), - (1434,'anno1701','Xa6zS3','Anno 1701',0), - (1435,'civ4ru',NULL,'Civiliation IV (Russian)',0), - (1436,'civ4ruam',NULL,'Civiliation IV Automatch (Russian)',0), - (1437,'civ4ch',NULL,'Civiliation IV (Chinese)',0), - (1438,'civ4cham',NULL,'Civiliation IV Automatch (Chinese)',0), - (1439,'cricket2007',NULL,'Brian Lara International Cricket 2007',0), - (1440,'eternalforces',NULL,'Eternal Forces Demo',0), - (1441,'eternalforcesam',NULL,'Eternal Forces Automatch',0), - (1442,'eforcesr',NULL,'Eternal Forces',0), - (1443,'bandbrosds',NULL,'Daiggaso! Band Brothers DX (DS)',0), - (1444,'ptacticsds',NULL,'Panzer Tactics (DS)',0), - (1445,'tankbeatds',NULL,'Tank Beat (JPN) (DS)',0), - (1446,'mdungeonds',NULL,'Mysterious Dungeon: Shiren the Wanderer DS (DS)',0), - (1447,'dqmonjokerds',NULL,'Dragon Quest Monsters: Joker (DS)',0), - (1448,'draculagolds',NULL,'Akumajou Dracula: Gallery of Labyrinth (DS)',0), - (1449,'oishiids',NULL,'Oishii Recipe (DS)',0), - (1450,'stlegacy',NULL,'Star Trek: Legacy',0), - (1451,'NN2Simple',NULL,'NatNeg2 Simple Test',0), - (1452,'yakumands',NULL,'Yakuman DS (DS)',0), - (1453,'marveltcardds',NULL,'Marvel Trading Card Game (DS)',0), - (1454,'ffantasy3usds',NULL,'Final Fantasy III - US (DS)',0), - (1457,'testdriveu',NULL,'Test Drive Unlimited (Unused)',0), - (1458,'test071806',NULL,'Test',0), - (1459,'chocobombds',NULL,'Chocobo & Magic Book (DS)',0), - (1460,'puyopuyods',NULL,'Puyo Puyo! (DS)',0), - (1461,'otonatrainds',NULL,'Imasara hitoniwa kikenai Otona no Jyoshikiryoku Training DS (DS)',0), - (1462,'luckystar2ds',NULL,'Lucky Star 2 (DS)',0), - (1463,'lotrbme2wk',NULL,'Lord of the Rings: The Battle for Middle-earth 2 (Rise of the Witch-King Expansion Pack)',0), - (1464,'crysis','ZvZDcL','Crysis (PC)',0), - (1465,'crysisd','ZvZDcL','Crysis Demo',0), - (1466,'monsterfarmds',NULL,'Monster Farm DS (DS)',0), - (1467,'naruto5ds',NULL,'NARUTO: Saikyou Ninja Daikesshuu 5 (DS)',0), - (1468,'picrossds',NULL,'Picross (DS)',0), - (1469,'wh40kp',NULL,'Warhammer 40,000: Dawn of War Patch',0), - (1470,'wh40kwap',NULL,'Warhammer 40,000: Winter Assault Patch',0), - (1471,'digiwrldds',NULL,'Digimon World DS (DS)',0), - (1472,'pandeponds',NULL,'Panel De Pon DS (DS)',0), - (1473,'moritashogids',NULL,'Morita Shogi DS (DS)',0), - (1474,'wormsow2ds',NULL,'Worms Open Warfare 2 (DS)',0), - (1475,'lithdev',NULL,'Monolith Development',0), - (1476,'lithdevam',NULL,'Monolith Development Automatch',0), - (1477,'bf2142',NULL,'Battlefield 2142',0), - (1478,'bf2142b',NULL,'Battlefield 2142 (Beta)',0), - (1479,'marvlegps3',NULL,'Marvel Legends (PS3)',0), - (1480,'marvlegps3am',NULL,'Marvel Legends Automatch (PS3)',0), - (1481,'marvlegps3p',NULL,'Marvel Legends PAL (PS3)',0), - (1482,'marvlegps3pam',NULL,'Marvel Legends PAL Automatch (PS3)',0), - (1483,'paradisecity',NULL,'Paradise City',0), - (1484,'whammermocdam',NULL,'Warhammer: Mark of Chaos Demo Automatch',0), - (1485,'djangosabds',NULL,'Bokura No Taiyou: Django & Sabata (DS)',0), - (1488,'tqexp1',NULL,'Titan Quest: Immortal Throne',0), - (1489,'tqexp1am',NULL,'Titan Quest: Immortal Throne (Automatch)',0), - (1492,'marveltcard',NULL,'Marvel Trading Card Game (PC & PSP)',0), - (1493,'marveltcardps',NULL,'Marvel Trading Card Game (PSP)',0), - (1494,'heroesmanads',NULL,'Seiken Densetsu: Heroes of Mana (DS)',0), - (1495,'prismgs',NULL,'PRISM: Guard Shield',0), - (1496,'prismgsd',NULL,'PRISM: Guard Shield Demo',0), - (1497,'testdriveub',NULL,'Test Drive Unlimited',0), - (1498,'testdriveud',NULL,'Test Drive Unlimited Demo',0), - (1499,'swempirexp1',NULL,'Star Wars: Empire at War - Forces of Corruption',0), - (1500,'dsakurads',NULL,'Dragon Sakura DS (DS)',0), - (1501,'gopetsvids',NULL,'GoPets: Vacation Island (DS)',0), - (1502,'kurikinds',NULL,'Kurikin (DS)',0), - (1503,'codedarmspsp',NULL,'Coded Arms (PSP)',0), - (1504,'codedarmspspam',NULL,'Coded Arms Automatch (PSP)',0), - (1505,'wiinat',NULL,'Wii NAT Negotiation Testing',0), - (1506,'whtacticspsp',NULL,'Warhammer 40,000: Tactics (PSP)',0), - (1507,'whtacticspspam',NULL,'Warhammer 40,000: Tactics Automatch (PSP)',0), - (1508,'armedass',NULL,'ArmA',0), - (1509,'ffcryschronds',NULL,'Final Fantasy: Crystal Chronicles - Ring of Fate (DS)',0), - (1510,'preystarsds',NULL,'Prey The Stars (DS)',0), - (1511,'bleach2ds',NULL,'Bleach DS 2: Requiem in the black robe (DS)',0), - (1512,'marvlegnpsp',NULL,'Marvel Legends (PSP, NTSC)',0), - (1513,'marvlegnpspam',NULL,'Marvel Legends Automatch (PSP, NTSC)',0), - (1514,'spartaaw',NULL,'Sparta: Ancient Wars',0), - (1515,'spartaawd',NULL,'Sparta: Ancient Wars Demo',0), - (1516,'civ4mac','CWiCbk','Civilization IV (MAC)',0), - (1517,'civ4macam','CWiCbk','Civilization IV Automatch (MAC)',0), - (1518,'civ4wrldmac','QtCpWE','Civilization IV: Warlords (MAC)',0), - (1519,'civ4wrldmacam','QtCpWE','Civilization IV: Warlords Automatch (MAC)',0), - (1520,'pokebattlewii',NULL,'Pokemon Battle Revolution (Wii)',0), - (1521,'puzquestds',NULL,'Puzzle Quest: Challenge of the Warlords (DS)',0), - (1522,'doraemonds',NULL,'Doraemon Nobita no Shinmakai Daiboken DS (DS)',0), - (1523,'eearth3',NULL,'Empire Earth III',0), - (1524,'eearth3d',NULL,'Empire Earth III Demo',0), - (1525,'cc3tibwarsmb',NULL,'Command & Conquer 3: Tiberium Wars Match Broadcast',0), - (1527,'bf2142d',NULL,'Battlefield 2142 Demo',0), - (1528,'anno1701d','taEf7n','Anno 1701 Demo',0), - (1529,'medieval2d',NULL,'Medieval II Demo',0), - (1530,'civ4wrldjp','oQ3v8V','Civilization IV: Warlords (Japan)',0), - (1531,'civ4wrldjpam','oQ3v8V','Civilization IV: Warlords Automatch (Japan)',0), - (1532,'civ4wrldcn','oQ3v8V','Civilization IV: Warlords (Chinese)',0), - (1533,'civ4wrldcnam','oQ3v8V','Civilization IV: Warlords Automatch (Chinese)',0), - (1534,'whammer40ktds',NULL,'Warhammer 40,000 Tactics (DS)',0), - (1535,'mukoubuchids',NULL,'Mukoubuchi - Goburei, Shuryoudesune (DS)',0), - (1536,'cusrobousds',NULL,'Gekitoh! Custom Robo (DS) (US)',0), - (1537,'kurikurimixds',NULL,'Kuri Kuri Mix DS (DS)',0), - (1538,'custoboeuds',NULL,'Custom Robo (EU) (DS)',0), - (1539,'whammermoct',NULL,'Warhammer: Mark of Chaos Test',0), - (1540,'whammermoctam',NULL,'Warhammer: Mark of Chaos Test Automatch',0), - (1541,'sweawfocd',NULL,'Forces of Corruption Demo',0), - (1542,'aoe3wcd',NULL,'Age of Empires 3: The Warchiefs Demo',0), - (1543,'tolmamods',NULL,'Tolmamo (DS)',0), - (1544,'patchtest',NULL,'Patching Test',0), - (1545,'dkracingds',NULL,'Diddy Kong Racing DS (DS)',0), - (1546,'fullautops3d',NULL,'Full Auto 2: Battlelines Demo (PS3)',0), - (1547,'themark',NULL,'The Mark',0), - (1548,'themarkam',NULL,'The Mark Automatch',0), - (1549,'bf2142e',NULL,'Battlefield 2142 (EAD)',0), - (1550,'supcommb',NULL,'Supreme Commander (Beta)',0), - (1551,'dow_dc',NULL,'Dawn of War: Dark Crusade',0), - (1552,'fuusuibands',NULL,'Fuusuiban (DS)',0), - (1553,'sweawfoc',NULL,'Star Wars: Empire at War - Forces of Corruption',0), - (1554,'s_darkmmm',NULL,'Dark Messiah of Might and Magic',0), - (1555,'ppirates',NULL,'Puzzle Pirates',0), - (1556,'mschargedwii',NULL,'Mario Strikers Charged (Wii)',0), - (1557,'8ballstarsds',NULL,'8-Ball Allstars (DS)',0), - (1558,'tmntds',NULL,'Teenage Mutant Ninja Turtles (DS)',0), - (1559,'surfsupds',NULL,'Surf\'s Up (DS)',0), - (1560,'elemonsterds',NULL,'Elemental Monster (DS)',0), - (1561,'cc3tibwarsam',NULL,'Command & Conquer 3: Tiberium Wars Automatch',0), - (1562,'picrossEUds',NULL,'Picross (EU) (DS)',0), - (1563,'greconawf2','qvOwuX','Ghost Recon: Advanced Warfighter 2',0), - (1564,'greconawf2am',NULL,'Ghost Recon: Advanced Warfighter 2 Automatch',0), - (1565,'greconawf2d',NULL,'Ghost Recon: Advanced Warfighter 2 Demo',0), - (1566,'yugiohWC07ds',NULL,'Yu-Gi-Oh! Dual Monsters World Championship 2007 (DS)',0), - (1567,'tgmasterds',NULL,'Table Game Master DS (DS)',0), - (1568,'batwars2wii',NULL,'Battalion Wars II (Wii)',0), - (1569,'Doragureidods',NULL,'Doragureido (DS)',0), - (1570,'armedassd',NULL,'ArmA Demo',0), - (1571,'ffantasy3euds',NULL,'Final Fantasy III - EU (DS)',0), - (1572,'rockstardev',NULL,'Rockstar Development',0), - (1573,'rockstardevam',NULL,'Rockstar Development Automatch',0), - (1575,'mparty1ds',NULL,'Mario Party (DS)',0), - (1576,'stalkerscd',NULL,'STALKER: Shadows of Chernobyl Beta',0), - (1577,'swempiremac',NULL,'Star Wars: Empire at War (Mac)',0), - (1578,'swempiremacam',NULL,'Star Wars: Empire at War Automatch (Mac)',0), - (1579,'marvlegjpps3',NULL,'Marvel Legends (PS3, Japan)',0), - (1580,'marvlegjpps3am',NULL,'Marvel Legends Automatch (PS3, Japan)',0), - (1581,'drmariowii',NULL,'Dr. Mario (WiiWare)',0), - (1582,'springwidgets',NULL,'Spring Widgets',0), - (1583,'springwidgetsam',NULL,'Spring Widgets Automatch',0), - (1584,'lotrbfme2',NULL,'The Rise of The Witch-king',0), - (1585,'wmarkofchaos',NULL,'Warhammer Mark of Chaos',0), - (1586,'warmonger',NULL,'Warmonger',0), - (1587,'everquest2',NULL,'EverQuest II',0), - (1588,'startreklegacy',NULL,'Star Trek: Legacy',0), - (1589,'freessbalpha',NULL,'Freestyle Street Basketball Client Alpha',0), - (1590,'lozphourds',NULL,'The Legend of Zelda: Phantom Hourglass (DS)',0), - (1591,'vanguardbeta',NULL,'Vanguard beta',0), - (1592,'digisunmoonds',NULL,'Digimon Story Sunburst/Moonlight (DS)',0), - (1593,'wmarkofchaosd',NULL,'Warhammer Mark of Chaos Demo',0), - (1594,'cruciformam',NULL,'Genesis Rising: The Universal Crusade Automatch',0), - (1595,'tcghostreconaw',NULL,'tcghostreconaw',0), - (1596,'ghostraw',NULL,'Ghost Recon Advanced Warfighter',0), - (1597,'rainbowsixv',NULL,'Rainbow Six Vegas',0), - (1598,'wmarkofchaosdam',NULL,'Warhammer Mark of Chaos Demo Automatch',0), - (1599,'crysisb',NULL,'Crysis Beta',0), - (1600,'scotttest',NULL,'Scott\'s test gamename',0), - (1601,'rftbomb',NULL,'Rush for the Bomb',0), - (1602,'motogp2007',NULL,'MotoGP 2007',0), - (1603,'motogp2007am',NULL,'MotoGP 2007 Automatch',0), - (1604,'cityofheroes',NULL,'City of Heroes',0), - (1605,'cityofvl',NULL,'City of Villains',0), - (1606,'titanquestit',NULL,'Titan Quest Immortal Throne',0), - (1607,'girlsds',NULL,'Girls (DS)',0), - (1608,'mariokartkods',NULL,'Mario Kart DS (DS) (KOR)',0), - (1609,'mmessagesds',NULL,'Mixed Messages (DS)',0), - (1610,'topanglerwii',NULL,'Top Angler (Wii)',0), - (1611,'swbfffpsp',NULL,'Star Wars Battlefront: Renegade Squadron (PSP)',0), - (1612,'facesow',NULL,'Faces of War',0), - (1615,'dexplorerds',NULL,'Dungeon Explorer (DS)',0), - (1616,'civconps3',NULL,'Civilization Revolution (PS3)',0), - (1617,'civconps3am',NULL,'Civ Console Automatch (PS3)',0), - (1618,'civconps3d',NULL,'Civilization Revolution Demo (PS3)',0), - (1620,'stalkerscb',NULL,'STALKER: Shadows of Chernobyl Beta (Unused)',0), - (1622,'secondlife',NULL,'Second Life',0), - (1623,'tdubeta',NULL,'Test Drive Unlimited Beta',0), - (1624,'elevenkords',NULL,'World Soccer Winning Eleven DS (KOR) (DS)',0), - (1625,'bsmidway',NULL,'Battlestations Midway Demo',0), - (1626,'etforces',NULL,'Eternal Forces',0), - (1627,'genesisrbeta',NULL,'Genesis Rising Beta',0), - (1628,'tankbeatusds',NULL,'Tank Beat (US) (DS)',0), - (1629,'champgamesps3',NULL,'High Stakes on the Vegas Strip: Poker Edition (PS3)',0), - (1631,'eearth3b',NULL,'Empire Earth III Beta',0), - (1632,'eearth3am',NULL,'Empire Earth III Automatch',0), - (1633,'chocmbeuds',NULL,'Chocobo & Magic Book (EU) (DS)',0), - (1634,'supcommdemo',NULL,'Supreme Commander Demo',0), - (1635,'tetriskords',NULL,'Tetris DS (KOR) (DS)',0), - (1636,'jissenpachwii',NULL,'Jissen Pachinko Slot (Wii)',0), - (1637,'wincircleds',NULL,'Winner\'s Circle (DS)',0), - (1638,'itadakistds',NULL,'Itadaki Street DS (DS)',0), - (1639,'smrailroadsjp',NULL,'Sid Meier\'s Railroads! Japan',0), - (1640,'smrailroadsjpam',NULL,'Sid Meier\'s Railroads! Japan Automatch',0), - (1641,'megamansfds',NULL,'Mega Man Star Force (US) (DS)',0), - (1642,'facesofwarxp1',NULL,'Faces of War Standalone (XP1)',0), - (1643,'facesofwarxp1am',NULL,'Faces of War Standalone Automatch (XP1)',0), - (1644,'timeshiftx',NULL,'TimeShift (Xbox 360)',0), - (1645,'timeshiftps3',NULL,'TimeShift (PS3)',0), - (1646,'powerpinconds',NULL,'Powershot Pinball Constructor (DS)',0), - (1647,'kingbeetlesds',NULL,'The King of Beetles Mushiking Super Collection (DS)',0), - (1648,'dragonbzwii',NULL,'Dragonball Z (Wii)',0), - (1649,'atlas_samples',NULL,'ATLAS Sample Apps',0), - (1650,'cc3tibwarsd',NULL,'Command & Conquer 3 Demo',0), - (1651,'supcomm',NULL,'Supreme Commander',0), - (1652,'assaultheroes',NULL,'Assault Heroes',0), - (1653,'assaultheroesam',NULL,'Assault Heroes Automatch',0), - (1654,'pokedungeonds',NULL,'Pokemon Fushigi no Dungeon (DS)',0), - (1655,'PowaPPocketds',NULL,'PowaProkun Pocket10 (DS)',0), - (1656,'GunMahjongZds',NULL,'Kidou Gekidan Haro Ichiza Gundam Mah-jong+Z (DS)',0), - (1657,'fullmatcgds',NULL,'Fullmetal Alchemist Trading Card Game (DS)',0), - (1658,'smashbrosxwii',NULL,'Dairantou Smash Brothers X (Wii)',0), - (1659,'disfriendsds',NULL,'Disney Friends DS (DS)',0), - (1660,'Jyotrainwii',NULL,'Minna de Jyoshiki Training Wii (Wii)',0), - (1661,'roguewarpc',NULL,'Rogue Warrior (PC)',0), - (1662,'roguewarpcam',NULL,'Rogue Warrior Automatch (PC)',0), - (1663,'roguewarpcd',NULL,'Rogue Warrior Demo (PC)',0), - (1664,'roguewarps3',NULL,'Rogue Warrior (PS3)',0), - (1665,'roguewarps3am',NULL,'Rogue Warrior Automatch (PS3)',0), - (1666,'roguewarps3d',NULL,'Rogue Warrior Demo (PS3)',0), - (1667,'archlord',NULL,'Archlord',0), - (1668,'racedriverds',NULL,'Race Driver (DS)',0), - (1669,'kaihatsuds',NULL,'Kaihatsushitsu (DS)',0), - (1670,'ardinokingds',NULL,'Ancient Ruler Dinosaur King (DS)',0), - (1671,'redbaronww1',NULL,'Red Baron WWI',0), - (1672,'greconawf2b',NULL,'Ghost Recon: Advanced Warfighter 2 Beta',0), - (1673,'greconawf2bam',NULL,'Ghost Recon: Advanced Warfighter 2 Beta Automatch',0), - (1674,'ubisoftdev',NULL,'Ubisoft Development',0), - (1675,'ubisoftdevam',NULL,'Ubisoft Development Automatch',0), - (1676,'testdriveuak',NULL,'Test Drive Unlimited (Akella)',0), - (1677,'armaas',NULL,'ArmA: Armed Assault',0), - (1678,'gta4ps3',NULL,'Grand Theft Auto 4 (PS3)',0), - (1679,'gta4ps3am',NULL,'Grand Theft Auto 4 Automatch (PS3)',0), - (1680,'gta4pc',NULL,'Grand Theft Auto 4 (PC)',0), - (1681,'gta4pcam',NULL,'Grand Theft Auto 4 Automatch (PC)',0), - (1682,'flashanzands',NULL,'Flash Anzan Doujou (DS)',0), - (1683,'gta4x',NULL,'Grand Theft Auto 4 (Xbox 360)',0), - (1684,'gta4xam',NULL,'Grand Theft Auto 4 Automatch (Xbox 360)',0), - (1685,'pokerangerds',NULL,'Pokemon Ranger 2 (DS)',0), - (1686,'megamansfeuds',NULL,'Mega Man Star Force (EU) (DS)',0), - (1687,'mariokartwii',NULL,'Mario Kart Wii (Wii)',0), - (1688,'swtakoronwii',NULL,'Shall we Takoron (Wii)',0), - (1689,'phylon',NULL,'Phylon',0), - (1690,'wsc2007pc',NULL,'World Snooker Championship 2007 (PC)',0), - (1691,'warfronttp',NULL,'War Front: Turning Point',0), - (1692,'fearxp2',NULL,'FEAR Perseus Mandate (PC)',0), - (1693,'risingeaglepc',NULL,'Rising Eagle',0), - (1694,'bombls2ds',NULL,'Touch! Bomberman Land 2 / Bomberman DS 2 (DS)',0), - (1695,'momoden16wii',NULL,'Momotaro Dentetsu 16 - Hokkaido Daiido no Maki! (Wii)',0), - (1696,'sonriders2wii',NULL,'Sonic Riders 2 (Wii)',0), - (1697,'sonicrushads',NULL,'Sonic Rush Adventure (DS)',0), - (1698,'ghostsquadwii',NULL,'Ghost Squad (Wii)',0), - (1699,'runefantasyds',NULL,'Rune Factory: A Fantasy Harvest Moon (DS)',0), - (1700,'contrads',NULL,'Contra DS (DS)',0), - (1701,'bleach1USds',NULL,'Bleach DS (US) (DS)',0), - (1702,'bleach2USds',NULL,'Bleach DS 2 (US) (DS)',0), - (1703,'civ4bts','Cs2iIq','Civilization IV: Beyond the Sword',0), - (1704,'civ4btsam','Cs2iIq','Civilization IV: Beyond the Sword Automatch',0), - (1705,'eearth3bam',NULL,'Empire Earth III Beta Automatch',0), - (1706,'eearth3dam',NULL,'Empire Earth III Demo Automatch',0), - (1707,'thetsuriwii',NULL,'The Tsuri (Wii)',0), - (1708,'theracewii',NULL,'The Race (Wii)',0), - (1709,'tankbeat2ds',NULL,'Tank Beat 2 (DS)',0), - (1710,'onslaughtpc',NULL,'Onslaught: War of the Immortals',0), - (1711,'onslaughtpcam',NULL,'Onslaught: War of the Immortals Automatch',0), - (1712,'onslaughtpcd',NULL,'Onslaught: War of the Immortals Demo',0), - (1713,'jikkyoprowii',NULL,'Jikkyo Powerful Pro Yakyu Wii (Wii)',0), - (1714,'cc3dev',NULL,'Command & Conquer 3 Dev Environment',0), - (1715,'cc3devam',NULL,'Command & Conquer 3 Dev Environment Automatch',0), - (1716,'wsc2007',NULL,'World Snooker Championship 2007',0), - (1717,'luminarcUSds',NULL,'Luminous Arc (US) (DS)',0), - (1718,'bleach1EUds',NULL,'Bleach DS (EU) (DS)',0), - (1719,'MSolympicds',NULL,'Mario & Sonic at the Olympic Games (DS)',0), - (1720,'keuthendev',NULL,'Keuthen.net Development',0), - (1721,'keuthendevam',NULL,'Keuthen.net Development Automatch',0), - (1722,'mclub4ps3',NULL,'Midnight Club 4 (PS3)',0), - (1723,'mclub4ps3am',NULL,'Midnight Club 4 Automatch (PS3)',0), - (1724,'mclub4xbox',NULL,'Midnight Club 4 (Xbox360)',0), - (1725,'mclub4xboxam',NULL,'Midnight Club 4 Automatch (Xbox360)',0), - (1726,'girlssecretds',NULL,'Girls Secret Diary (DS)',0), - (1727,'ut3pc',NULL,'Unreal Tournament 3 (PC)',0), - (1728,'ut3pcam',NULL,'Unreal Tournament 3 Automatch (PC)',0), - (1729,'ut3pcd',NULL,'Unreal Tournament 3 Demo (PC)',0), - (1730,'ecorisds',NULL,'Ecoris (DS)',0), - (1731,'ww2btanks',NULL,'WWII Battle Tanks: T-34 vs Tiger',0), - (1732,'genesisr',NULL,'Genesis Rising',0), - (1733,'tpfolpc',NULL,'Turning Point: Fall of Liberty (PC)',0), - (1734,'tpfolpcam',NULL,'Turning Point: Fall of Liberty Automatch (PC)',0), - (1735,'tpfolpcd',NULL,'Turning Point: Fall of Liberty Demo (PC)',0), - (1736,'tpfolps3',NULL,'Turning Point: Fall of Liberty (PS3)',0), - (1737,'tpfolps3am',NULL,'Turning Point: Fall of Liberty Automatch (PS3)',0), - (1738,'hsmusicalds',NULL,'High School Musical (DS)',0), - (1739,'cardheroesds',NULL,'Card Heroes (DS)',0), - (1740,'metprime3wii',NULL,'Metroid Prime 3 (Wii)',0), - (1741,'Digidwndskds',NULL,'Digimon World Dawn/Dusk (DS)',0), - (1742,'worldshiftpc',NULL,'WorldShift (PC)',0), - (1743,'worldshiftpcam',NULL,'WorldShift Automatch (PC)',0), - (1744,'worldshiftpcd',NULL,'WorldShift Demo (PC)',0), - (1745,'kingclubsds',NULL,'King of Clubs (DS)',0), - (1746,'MSolympicwii',NULL,'Mario & Sonic at the Olympic Games (Wii)',0), - (1747,'ingenious',NULL,'Ingenious',0), - (1748,'potco',NULL,'Pirates of the Caribbean Online',0), - (1749,'madden08ds',NULL,'Madden NFL 08 (DS)',0), - (1750,'vanguardsoh',NULL,'Vanguard Saga of Heroes',0), - (1751,'fury',NULL,'Fury',0), - (1752,'twoods08ds',NULL,'Tiger Woods 08 (DS)',0), - (1753,'otonazenshuds',NULL,'Otona no DS Bungaku Zenshu (DS)',0), - (1754,'bestfriendds',NULL,'Best Friend - Main Pferd (DS)',0), - (1755,'nindev',NULL,'Nintendo Network Development Testing',0), - (1756,'quakewarset',NULL,'Enemy Territory: Quake Wars',0), - (1757,'momotarodends',NULL,'Momotaro Dentetsu 16 ~ Hokkaido Daiido no Maki! (DS)',0), - (1758,'gwgalaxiesds',NULL,'Geometry Wars Galaxies (DS)',0), - (1759,'gwgalaxieswii',NULL,'Geometry Wars Galaxies (Wii)',0), - (1760,'hrollerzds',NULL,'Homies Rollerz (DS)',0), - (1761,'dungeonr',NULL,'Dungeon Runners',0), - (1762,'dirtdemo',NULL,'DiRT Demo',0), - (1763,'nameneverds',NULL,'Nameless Neverland (DS)',0), - (1764,'proyakyuds',NULL,'Pro Yakyu Famisute DS (DS)',0), - (1765,'foreverbwii',NULL,'Forever Blue (Wii)',0), - (1766,'ee3alpha',NULL,'Empire Earth III Alpha',0), - (1767,'rachelwood',NULL,'Rachel Wood Test Game Name',0), - (1768,'officersgwupc',NULL,'Officers: God With Us',0), - (1769,'officersgwupcam',NULL,'Officers: God With Us Automatch',0), - (1770,'swordotnw',NULL,'Sword of the New World',0), - (1771,'nfsprostds',NULL,'Need for Speed Pro Street (DS)',0), - (1772,'commandpc',NULL,'Commanders: Attack!',0), - (1773,'commandpcam',NULL,'Commanders: Attack! Automatch',0), - (1774,'whamdowfr',NULL,'Warhammer 40,000: Dawn of War - Soulstorm',0), - (1775,'whamdowfram',NULL,'Warhammer 40,000: Dawn of War - Final Reckoning Automatch',0), - (1776,'shirenUSEUds',NULL,'Mysterious Dungeon: Shiren the Wanderer DS (US-EU) (DS)',0), - (1777,'sporeds',NULL,'Spore (DS)',0), - (1778,'mysecretsds',NULL,'My Secrets (DS)',0), - (1779,'nights2wii',NULL,'NiGHTS: Journey of Dreams (Wii)',0), - (1780,'tgstadiumwii',NULL,'Table Game Stadium (Wii)',0), - (1781,'lovegolfwii',NULL,'Wii Love Golf (Wii)',0), - (1782,'hookedfishwii',NULL,'Hooked! Real Motion Fishing (Wii)',0), - (1783,'tankbattlesds',NULL,'Tank Battles (DS)',0), - (1784,'anarchyonline',NULL,'Anarchy Online',0), - (1785,'hookedEUwii',NULL,'Hooked! Real Motion Fishing (EU) (Wii)',0), - (1786,'hookedJPNwii',NULL,'Hooked! Real Motion Fishing (JPN) (Wii)',0), - (1787,'tankbeatEUds',NULL,'Tank Beat (EU) (DS)',0), - (1788,'farcry',NULL,'Far Cry',0), - (1789,'yugiohwc08ds',NULL,'Yu-Gi-Oh! World Championship 2008 (DS)',0), - (1790,'trackfieldds',NULL,'International Track & Field (DS)',0), - (1791,'quakewarsetb',NULL,'Enemy Territory: Quake Wars Beta',0), - (1792,'RKMvalleyds',NULL,'River King: Mystic Valley (DS)',0), - (1793,'DSwars2ds',NULL,'DS Wars 2 (DS)',0), - (1794,'cdkeys',NULL,'CD Key Admin Site Testing',0), - (1795,'wordjongds',NULL,'Word Jong - US (DS)',0), - (1796,'raymanrr2wii',NULL,'Rayman Raving Rabbids 2 (Wii)',0), - (1797,'nanostray2ds',NULL,'Nanostray 2 (DS)',0), - (1798,'guitarh3wii',NULL,'Guitar Hero 3 (Wii)',0), - (1799,'suddenstrike3',NULL,'Sudden Strike 3: Arms for Victory',0), - (1800,'segatennisps3',NULL,'Sega SuperStars Tennis (PS3)',0), - (1801,'segatennisps3am',NULL,'Sega SuperStars Tennis Automatch',0), - (1802,'dfriendsEUds',NULL,'Disney Friends DS (EU)',0), - (1803,'fifa08ds',NULL,'FIFA 08 Soccer (DS)',0), - (1804,'suitelifeds',NULL,'Suite Life of Zack & Cody: Circle of Spies (DS)',0), - (1805,'dragladeds',NULL,'Draglade (DS)',0), - (1806,'takoronUSwii',NULL,'Takoron (US) (Wii)',0), - (1807,'dragonbzUSwii',NULL,'Dragonball Z: Tenkaichi 3 (US) (Wii)',0), - (1808,'arkanoidds',NULL,'Arkanoid DS (DS)',0), - (1809,'rfactory2ds',NULL,'Rune Factory 2 (DS)',0), - (1810,'dow',NULL,'Dawn of War',0), - (1811,'nitrobikewii',NULL,'Nitrobike (Wii)',0), - (1812,'bokujyods',NULL,'Bokujyo Monogatari Himawari Shoto wa Oosawagi! (DS)',0), - (1813,'WSWelevenwii',NULL,'World Soccer Winning Eleven Wii (Wii)',0), - (1814,'cc3xp1',NULL,'Command & Conquer 3: Expansion Pack 1',0), - (1815,'cc3xp1am',NULL,'Command & Conquer 3: Expansion Pack 1 Automatch',0), - (1816,'pachgundamwii',NULL,'Pachisuro Kido Senshi Gundam Aisenshi Hen (Wii)',0), - (1817,'newgamename',NULL,'dhdh',0), - (1818,'newgamenameam',NULL,'dhdh Automatch',0), - (1819,'gsTiaKreisDS',NULL,'Genso Suikokuden TiaKreis (DS)',0), - (1820,'ultimateMKds',NULL,'Ultimate Mortal Kombat (DS)',0), - (1821,'MLBallstarsds',NULL,'Major League Baseball Fantasy All-Stars (DS)',0), - (1822,'wicb',NULL,'World in Conflict Beta',0), - (1823,'ee3beta',NULL,'Empire Earth III Beta',0), - (1824,'WSWeleven07ds',NULL,'World Soccer Winning Eleven DS 2007 (DS)',0), - (1825,'mafia2pc',NULL,'Mafia 2 (PC)',0), - (1826,'mafia2pcam',NULL,'Mafia 2 Automatch (PC)',0), - (1827,'mafia2ps3',NULL,'Mafia 2 (PS3)',0), - (1828,'mafia2ps3am',NULL,'Mafia 2 Automatch (PS3)',0), - (1829,'chocotokiwii',NULL,'Chocobo no Fushigina Dungeon: Toki-Wasure no Meikyu (Wii)',0), - (1830,'zeroGds',NULL,'ZeroG (DS)',0), - (1831,'suitelifeEUds',NULL,'Suite Life of Zack & Cody: Circle of Spies (EU) (DS)',0), - (1832,'furaishi3wii',NULL,'Furai no Shiren 3 Karakuri Yashiki no Nemuri Hime (Wii)',0), - (1833,'ben10bb',NULL,'Ben 10 Bounty Battle',0), - (1834,'ben10bbam',NULL,'Ben 10 Bounty Battle Automatch',0), - (1835,'risingeagleg',NULL,'Rising Eagle',0), - (1836,'timeshiftg',NULL,'Timeshift',0), - (1837,'cadZ2JPwii',NULL,'Caduceus Z2 (Wii)',0), - (1838,'rockmanBSDds',NULL,'Rockman 2 - Berserk: Shinobi / Dinosaur (DS)',0), - (1839,'THPGds',NULL,'Tony Hawks Proving Ground (DS)',0), - (1840,'birhhpc',NULL,'Brothers In Arms: Hell\'s Highway (PC)',0), - (1841,'birhhpcam',NULL,'Brothers In Arms: Hell\'s Highway Automatch (PC)',0), - (1842,'birhhps3',NULL,'Brothers In Arms: Hell\'s Highway (PS3)',0), - (1843,'birhhps3am',NULL,'Brothers In Arms: Hell\'s Highway Clone Automatch (PS3)',0), - (1844,'sakuraTDDds',NULL,'Sakura Taisen Dramatic Dungeon - Kimiarugatame (DS)',0), - (1845,'fsxa',NULL,'Flight Simulator X: Acceleration',0), - (1846,'fsxaam',NULL,'Flight Simulator X: Acceleration Automatch',0), - (1847,'ee3',NULL,'Empire Earth 3',0), - (1848,'nwn2mac',NULL,'NeverWinter Nights 2 (MAC)',0), - (1849,'nwn2macam',NULL,'NeverWinter Nights 2 Automatch (MAC)',0), - (1850,'greconawf2g',NULL,'Ghost Recon Advanced Warfighter 2',0), - (1851,'quakewarsetd',NULL,'Enemy Territory: Quake Wars Demo',0), - (1852,'evosoccer08ds',NULL,'Pro Evolution Soccer 2008 (DS)',0), - (1853,'cohofbeta',NULL,'Company of Heroes: Opposing Fronts MP Beta',0), - (1854,'tetrisppwii',NULL,'Tetris++ (WiiWare)',0), - (1855,'bioshock',NULL,'Bioshock Demo',0), - (1856,'bioshockd',NULL,'Bioshock',0), - (1857,'civrevods',NULL,'Sid Meier\'s Civilization Revolution (DS)',0), - (1858,'ninjagaidends',NULL,'Ninja Gaiden: Dragon Sword (DS)',0), - (1859,'MOHADemo',NULL,'Medal of Honor Airborne Demo',0), - (1860,'clubgameKORds',NULL,'Clubhouse Games (KOR) (DS)',0), - (1861,'wic',NULL,'World in Conflict Demo',0), - (1862,'wicd',NULL,'World in Conflict Demo',0), - (1863,'ut3pcdam',NULL,'Unreal Tournament 3 Demo Automatch (PC)',0), - (1864,'evosoc08USds',NULL,'Pro Evolution Soccer 2008 (US) (DS)',0), - (1865,'wormsasowii',NULL,'Worms: A Space Oddity (Wii)',0), - (1866,'painkillerod',NULL,'Painkiller Overdose',0), - (1867,'painkillerodam',NULL,'Painkiller Overdose Automatch',0), - (1868,'cnpanzers2cw',NULL,'Codename Panzers 2: Cold Wars (PC)',0), - (1869,'cnpanzers2cwam',NULL,'Codename Panzers 2: Cold Wars Automatch',0), - (1870,'cnpanzers2cwd',NULL,'Codename Panzers 2: Cold Wars Demo',0), - (1871,'luminarc2ds',NULL,'Luminous Arc 2 Will (DS)',0), - (1872,'noahprods',NULL,'Noah\'s Prophecy (DS)',0), - (1873,'wiibombmanwii',NULL,'Wii Bomberman / WiiWare Bomberman / Bomberman Land Wii 2 (Wii)',0), - (1874,'thesactionwii',NULL,'The Shooting Action (Wii)',0), - (1875,'Asonpartywii',NULL,'Asondewakaru THE Party/Casino (Wii)',0), - (1876,'sptouzokuds',NULL,'Steel Princess Touzoku Koujyo (DS)',0), - (1877,'heiseikyods',NULL,'Heisei Kyoiku Iinkai DS Zenkoku Touitsu Moshi Special (DS)',0), - (1878,'famstadiumwii',NULL,'Family Stadium Wii (Wii)',0), - (1879,'ut3ps3',NULL,'Unreal Tournament 3 (PS3)',0), - (1880,'ut3ps3am',NULL,'Unreal Tournament 3 Automatch (PS3)',0), - (1881,'ut3ps3d',NULL,'Unreal Tournament 3 Demo (PS3)',0), - (1882,'ecocreatureds',NULL,'Eco-Creatures: Save the Forest (DS)',0), - (1883,'mohairborne',NULL,'Medal of Honor: Airborne',0), - (1884,'whamdowfrb',NULL,'Warhammer 40,000: Dawn of War - Final Reckoning Beta',0), - (1885,'whamdowfrbam',NULL,'Warhammer 40,000: Dawn of War - Final Reckoning Beta Automatch',0), - (1886,'puyobomberds',NULL,'Puyo Puyo Bomber (DS)',0), - (1887,'s_tf2',NULL,'Team Fortress 2',0), - (1888,'painkillerodd',NULL,'Painkiller Overdose Demo',0), - (1889,'goreAV',NULL,'Gore (Ad version)',0), - (1890,'goreAVam',NULL,'Gore Automatch (Ad version)',0), - (1891,'goreAVd',NULL,'Gore Demo (Ad version)',0), - (1892,'fstreetv3ds',NULL,'FIFA Street v3 (DS)',0), - (1893,'dragladeEUds',NULL,'Draglade (EU) (DS)',0), - (1894,'culdceptds',NULL,'Culdcept DS (DS)',0), - (1895,'ffwcbeta',NULL,'Frontlines: Fuel of War Beta',0), - (1896,'ffowbeta',NULL,'Frontlines: Fuel of War Beta',0), - (1897,'painkilleroddam',NULL,'Painkiller Overdose Demo Automatch',0), - (1901,'pkodgerman',NULL,'Painkiller Overdose (German)',0), - (1902,'pkodgermanam',NULL,'Painkiller Overdose Automatch (German)',0), - (1903,'pkodgermand',NULL,'Painkiller Overdose Demo (German)',0), - (1904,'cohof',NULL,'Company of Heroes: Opposing Fronts',0), - (1905,'puzzlernumds',NULL,'Puzzler Number Placing Fun & Oekaki Logic 2 (DS)',0), - (1906,'supcomfabeta',NULL,'Supreme Commander: Forged Alliance beta',0), - (1907,'condemned2bs',NULL,'Condemned 2: Bloodshot (PS3)',0), - (1908,'condemned2bsam',NULL,'Condemned 2: Bloodshot Automatch',0), - (1909,'condemned2bsd',NULL,'Condemned 2: Bloodshot Demo (PS3)',0), - (1910,'potbs',NULL,'Pirates of the Burning Sea',0), - (1911,'mxvsatvutps2',NULL,'MX vs ATV Untamed (PS2)',0), - (1912,'mxvsatvutps2am',NULL,'MX vs ATV Untamed Automatch (PS2)',0), - (1913,'jikkyopprowii',NULL,'Jikkyo Powerful Pro Yakyu Wii Kettei ban (Wii)',0), - (1914,'ut3demo',NULL,'Unreal Tournament 3 Demo',0), - (1915,'ut3',NULL,'Unreal Tournament 3',0), - (1916,'valknightswii',NULL,'Valhalla Knights (Wii)',0), - (1917,'amfbowlingds',NULL,'AMF Bowling: Pinbusters! (DS)',0), - (1918,'ducatimotods',NULL,'Ducati Moto (DS)',0), - (1919,'arkwarriors',NULL,'Arkadian Warriors',0), - (1920,'arkwarriorsam',NULL,'Arkadian Warriors Automatch',0), - (1921,'mxvsatvutwii',NULL,'MX vs ATV Untamed (Wii)',0), - (1922,'cheetah3ds',NULL,'The Cheetah Girls 3 (DS)',0), - (1923,'whammermocbm',NULL,'Warhammer: Mark of Chaos - Battle March',0), - (1924,'whammermocbmam',NULL,'Warhammer: Mark of Chaos - Battle March Automatch',0), - (1925,'whammermocbmd',NULL,'Warhammer: Mark of Chaos - Battle March Demo',0), - (1926,'linksds',NULL,'Links (DS)',0), - (1927,'swbfront3pc',NULL,'Star Wars Battlefront 3 (PC)',0), - (1928,'swbfront3pcam',NULL,'Star Wars Battlefront 3 Automatch (PC)',0), - (1929,'siextremeds',NULL,'Space Invaders Extreme',0), - (1931,'redsteel2wii',NULL,'Red Steel 2 (Wii)',0), - (1932,'gorese',NULL,'Gore Special Edition',0), - (1933,'dinokingEUds',NULL,'Ancient Ruler Dinosaur King (EU) (DS)',0), - (1934,'civ4btsjp','Cs2iIq','Civilization IV: Beyond the Sword (Japanese)',0), - (1935,'civ4btsjpam','Cs2iIq','Civilization IV: Beyond the Sword Automatch (Japanese)',0), - (1936,'charcollectds',NULL,'Character Collection! DS (DS)',0), - (1937,'timeshiftd',NULL,'TimeShift Demo (PC)',0), - (1938,'gtacwarsds',NULL,'Grand Theft Auto: Chinatown Wars (DS)',0), - (1939,'fireemblemds',NULL,'Fire Emblem DS (DS)',0), - (1940,'soccerjamds',NULL,'Soccer Jam (DS)',0), - (1941,'gravitronwii',NULL,'Gravitronix (WiiWare)',0), - (1942,'mdamiiwalkds',NULL,'Minna de Aruku! Mii Walk (DS)',0), - (1943,'puzzlemojiwii',NULL,'Kotoba no Puzzle Moji Pittan Wii (WiiWare)',0), - (1944,'nitrobikeps2',NULL,'Nitrobike (PS2)',0), - (1945,'nitrobikeps2am',NULL,'Nitrobike Automatch (PS2)',0), - (1946,'dinokingUSds',NULL,'Dinosaur King (US) (DS)',0), - (1947,'harvfishEUds',NULL,'Harvest Fishing (EU) (DS)',0), - (1948,'harmooniohds',NULL,'Harvest Moon : Island of Happiness (US) (DS)',0), - (1949,'harmoon2ds',NULL,'Harvest Moon DS 2 (EU) (DS)',0), - (1950,'sbk08pc',NULL,'SBK \'08: Superbike World Championship (PC)',0), - (1951,'sbk08pcam',NULL,'SBK \'08: Superbike World Championship Automatch (PC)',0), - (1952,'sbk08pcd',NULL,'SBK \'08: Superbike World Championship Demo (PC)',0), - (1953,'sbk08ps3',NULL,'SBK \'08: Superbike World Championship (PS3)',0), - (1954,'sbk08ps3am',NULL,'SBK \'08: Superbike World Championship Automatch (PS3)',0), - (1955,'exitds',NULL,'Hijyoguchi: EXIT DS (DS)',0), - (1956,'spectrobes2ds',NULL,'Kaseki Choshinka Spectrobes 2 (DS)',0), - (1957,'nanost2EUds',NULL,'Nanostray 2 (EU) (DS)',0), - (1958,'crysisspd',NULL,'Crysis SP Demo',0), - (1959,'evosoc08EUwii',NULL,'Pro Evolution Soccer 2008 (EU) (Wii)',0), - (1960,'evosoc08USwii',NULL,'Pro Evolution Soccer 2008 (US) (Wii)',0), - (1961,'sdamigowii',NULL,'Samba de Amigo (Wii)',0), - (1962,'timeshiftps3d',NULL,'TimeShift Demo (PS3)',0), - (1963,'chesswii',NULL,'Wii Chess (Wii)',0), - (1964,'ecolisEUds',NULL,'Ecolis (EU) (DS)',0), - (1965,'rdgridds',NULL,'Race Driver: Grid (DS)',0), - (1966,'swbfront3wii',NULL,'Star Wars: Battlefront 3 (Wii)',0), - (1967,'guitarh3xpwii',NULL,'Guitar Hero 3 Expansion Pack (Wii)',0), - (1968,'callofduty4',NULL,'Call of Duty 4: Modern Warfare',0), - (1969,'mmadnessexps3',NULL,'Monster Madness EX (PS3)',0), - (1970,'mmadnessexps3am',NULL,'Monster Madness EX Automatch (PS3)',0), - (1971,'mmadexps3d',NULL,'Monster Madness EX Demo (PS3)',0), - (1972,'terrortkdwn2',NULL,'Terrorist Takedown 2',0), - (1973,'terrortkdwn2am',NULL,'Terrorist Takedown 2 Automatch',0), - (1974,'terrortkdwn2d',NULL,'Terrorist Takedown 2 Demo',0), - (1975,'cc3xp1mb',NULL,'Command & Conquer 3: Kane\'s Wrath Match Broadcast Clone',0), - (1976,'dstallionds',NULL,'Derby Stallion DS (DS)',0), - (1977,'blkuzushiwii',NULL,'THE Block Kuzushi - With the Stage Creation feature (Wii)',0), - (1978,'thecombatwii',NULL,'SIMPLE Wii Series Vol.6 THE Minna de Waiwai Combat (Wii)',0), - (1979,'cc3kw',NULL,'Command and Conquer 3 Kanes Wrath',0), - (1980,'ballers3ps3',NULL,'NBA Ballers: Chosen One (PS3)',0), - (1981,'ballers3ps3am',NULL,'NBA Ballers: Chosen One Automatch (PS3)',0), - (1982,'ballers3ps3d',NULL,'NBA Ballers: Chosen One Demo (PS3)',0), - (1983,'cc3kwmb',NULL,'Command and Conquer 3 Kanes Wrath Match Broadcast',0), - (1984,'scourgepc',NULL,'The Scourge Project (PC)',0), - (1985,'scourgepcam',NULL,'The Scourge Project Automatch (PC)',0), - (1986,'scourgepcd',NULL,'The Scourge Project Demo (PC)',0), - (1987,'scourgeps3',NULL,'The Scourge Project (PS3)',0), - (1988,'scourgeps3am',NULL,'The Scourge Project Automatch (PS3)',0), - (1989,'scourgeps3d',NULL,'The Scourge Project Demo (PS3)',0), - (1990,'rfactoryEUds',NULL,'Rune Factory: A Fantasy Harverst Moon (EU) (DS)',0), - (1991,'popwii',NULL,'Pop (WiiWare)',0), - (1992,'tenchu4wii',NULL,'Tenchu 4 (Wii)',0), - (1993,'ssoldierrwii',NULL,'Star Soldier R (WiiWare)',0), - (1994,'2kboxingds',NULL,'2K Boxing (DS)',0), - (1995,'bldragonds',NULL,'Blue Dragon (DS)',0), - (1996,'elebitsds',NULL,'Elebits DS - Kai to Zero no Fushigi na Bus (DS)',0), - (1997,'nobunagapktds',NULL,'Nobunaga no Yabou DS Pocket Senshi (DS)',0), - (1998,'kqmateDS',NULL,'KaitoranmaQ Mate! (DS)',0), - (1999,'digichampds',NULL,'Digimon Championship (DS)',0), - (2000,'yakumanwii',NULL,'Yakuman Wii (WiiWare)',0), - (2001,'mxvatvuPALps2',NULL,'MX vs ATV Untamed PAL (PS2)',0), - (2002,'mxvatvuPALps2am',NULL,'MX vs ATV Untamed PAL Automatch (PS2)',0), - (2003,'mezasetm2wii',NULL,'Mezase!! Tsuri Master 2 (Wii)',0), - (2004,'raw2009wii',NULL,'WWE Smackdown! vs RAW 2009 (Wii)',0), - (2005,'redbaronps3',NULL,'Red Baron WWI (PS3)',0), - (2006,'redbaronps3am',NULL,'Red Baron WWI Automatch (PS3)',0), - (2007,'memansf2USDS',NULL,'Mega Man Star Force 2: Zerker x Shinobi / Saurian (US)',0), - (2008,'mxvatvutEUwii',NULL,'MX vs ATV Untamed (EU) (Wii)',0), - (2009,'lostmagicwii',NULL,'Lost Magic Wii (Wii)',0), - (2010,'shirends2ds',NULL,'Fushigi no Dungeon: Furai no Shiren DS2 (DS)',0), - (2011,'worldshiftpcb',NULL,'WorldShift Beta (PC)',0), - (2012,'worldshiftpcbam',NULL,'WorldShift Beta Automatch (PC)',0), - (2013,'blitz08ps3',NULL,'Blitz: The League 08 (PS3)',0), - (2014,'blitz08ps3am',NULL,'Blitz: The League 08 Automatch (PS3)',0), - (2015,'blitz08ps3d',NULL,'Blitz: The League 08 Demo (PS3)',0), - (2016,'sangotends',NULL,'Sangokushitaisen Ten (DS)',0), - (2017,'lonposwii',NULL,'Lonpos (WiiWare)',0), - (2018,'cvania08ds',NULL,'Castlevania 2008 (DS)',0), - (2019,'nplusds',NULL,'N+ (DS)',0), - (2020,'gauntletds',NULL,'Gauntlet (DS)',0), - (2021,'finertiaps3',NULL,'Fatal Inertia (PS3)',0), - (2022,'finertiaps3am',NULL,'Fatal Inertia Automatch (PS3)',0), - (2023,'topspin3usds',NULL,'Top Spin 3 (US) (DS)',0), - (2024,'topspin3euds',NULL,'Top Spin 3 (EU) (DS)',0), - (2025,'wiilinkwii',NULL,'Wii Link (Wii)',0), - (2026,'simcitywii',NULL,'SimCity Creator (Wii)',0), - (2027,'tpfolEUpc',NULL,'Turning Point: Fall of Liberty (EU) (PC)',0), - (2028,'tpfolEUpcam',NULL,'Turning Point: Fall of Liberty Automatch (EU) (PC)',0), - (2029,'tpfolEUpcd',NULL,'Turning Point: Fall of Liberty Demo (EU) (PC)',0), - (2030,'tpfolEUps3',NULL,'Turning Point: Fall of Liberty (EU) (PS3)',0), - (2031,'tpfolEUps3am',NULL,'Turning Point: Fall of Liberty Automatch (EU) (PS3)',0), - (2032,'parabellumpc',NULL,'Parabellum (PC)',0), - (2033,'parabellumpcam',NULL,'Parabellum Automatch (PC)',0), - (2034,'parabellumpcd',NULL,'Parabellum Demo (PC)',0), - (2035,'parabellumps3',NULL,'Parabellum (PS3)',0), - (2036,'parabellumps3am',NULL,'Parabellum Automatch (PS3)',0), - (2037,'monlabwii',NULL,'Monster Lab (Wii)',0), - (2038,'necrovisionpc',NULL,'NecroVision (PC)',0), - (2039,'necrovisionpcam',NULL,'NecroVision Automatch (PC)',0), - (2040,'necrovisionpcd',NULL,'NecroVision Demo (PC)',0), - (2041,'necrovisionpd',NULL,'NecroVision (PC) Demo',0), - (2042,'necrovisionpdam',NULL,'NecroVision Automatch (PC) Demo',0), - (2043,'damnationpc',NULL,'DamNation (PC)',0), - (2044,'damnationpcam',NULL,'DamNation Automatch (PC)',0), - (2045,'damnationpcd',NULL,'DamNation Demo (PC)',0), - (2046,'damnationps3',NULL,'DamNation (PS3)',0), - (2047,'damnationps3am',NULL,'DamNation Automatch (PS3)',0), - (2048,'strongholdce',NULL,'Stronghold: Crusader Extreme',0), - (2049,'parabellumpcdam',NULL,'Parabellum Demo Automatch (PC)',0), - (2050,'madeinoreds',NULL,'Made in Ore (DS)',0), - (2051,'guinnesswrds',NULL,'Guinness World Records: The Video Game (DS)',0), - (2052,'guinnesswrwii',NULL,'Guinness World Records: The Video Game (Wii)',0), - (2053,'mclub4ps3dev',NULL,'Midnight Club 4 Dev (PS3)',0), - (2054,'mclub4ps3devam',NULL,'Midnight Club 4 Dev Automatch (PS3)',0), - (2055,'mclub4xboxdev',NULL,'Midnight Club 4 Dev (Xbox360)',0), - (2056,'mclub4xboxdevam',NULL,'Midnight Club 4 Dev Automatch (Xbox360)',0), - (2057,'gta4pcdev',NULL,'Grand Theft Auto 4 Dev (PC)',0), - (2058,'gta4pcdevam',NULL,'Grand Theft Auto 4 Dev Automatch (PC)',0), - (2059,'gta4ps3dev',NULL,'Grand Theft Auto 4 Dev (PS3)',0), - (2060,'gta4ps3devam',NULL,'Grand Theft Auto 4 Dev Automatch (PS3)',0), - (2061,'gts4xdev',NULL,'Grand Theft Auto 4 Dev (Xbox 360)',0), - (2062,'gts4xdevam',NULL,'Grand Theft Auto 4 Dev Automatch (Xbox 360)',0), - (2063,'monfarm2ds',NULL,'Monster Farm DS 2 (DS)',0), - (2064,'plunderpc',NULL,'Age of Booty (PC)',0), - (2065,'plunderpcam',NULL,'Plunder Automatch (PC)',0), - (2066,'plunderpcd',NULL,'Plunder Demo (PC)',0), - (2067,'legendaryps3',NULL,'Legendary (PS3)',0), - (2068,'legendaryps3am',NULL,'Legendary Automatch (PS3)',0), - (2069,'callofduty4d2d',NULL,'Call of Duty 4: Modern Warfare',0), - (2070,'sekainodokods',NULL,'Sekai no Dokodemo Shaberu! DS Oryori Navi (DS)',0), - (2071,'glracerwii',NULL,'GameLoft\'s Racer (WiiWare)',0), - (2072,'beijing08pc',NULL,'Beijing 2008 (PC)',0), - (2073,'beijing08pcam',NULL,'Beijing 2008 Automatch (PC)',0), - (2074,'beijing08pcd',NULL,'Beijing 2008 Demo (PC)',0), - (2075,'beijing08ps3',NULL,'Beijing 2008 (PS3)',0), - (2076,'beijing08ps3am',NULL,'Beijing 2008 Automatch (PS3)',0), - (2077,'beijing08ps3d',NULL,'Beijing 2008 Demo (PS3)',0), - (2078,'hail2chimps3',NULL,'Hail to the Chimp (PS3)',0), - (2079,'hail2chimps3am',NULL,'Hail to the Chimp Automatch (PS3)',0), - (2080,'wlclashpc',NULL,'War Leaders: Clash of Nations (PC)',0), - (2081,'wlclashpcam',NULL,'War Leaders: Clash of Nations Automatch (PC)',0), - (2082,'wlclashpcd',NULL,'War Leaders: Clash of Nations Demo (PC)',0), - (2083,'bomberman20ds',NULL,'Bomberman 2.0 (DS)',0), - (2084,'heistpc',NULL,'Heist (PC)',0), - (2085,'heistpcam',NULL,'Heist Automatch (PC)',0), - (2086,'heistpcd',NULL,'Heist Demo (PC)',0), - (2087,'heistps3',NULL,'Heist (PS3)',0), - (2088,'heistps3am',NULL,'Heist Automatch (PS3)',0), - (2089,'bstrikeotspc',NULL,'Battlestrike: Operation Thunderstorm (PC)',0), - (2090,'bstrikeotspcam',NULL,'Battlestrike: Operation Thunderstorm Automatch (PC)',0), - (2091,'bstrikeotspcd',NULL,'Battlestrike: Operation Thunderstorm Demo (PC)',0), - (2092,'Decathletesds',NULL,'Decathletes (DS)',0), - (2093,'mleatingwii',NULL,'Major League Eating: The Game (EU/US) (WiiWare)',0), - (2094,'cc3kwcd',NULL,'Command and Conquer 3 Kanes Wrath CD Key Auth',0), - (2095,'cc3kwcdam',NULL,'Command and Conquer 3 Kanes Wrath CD Key Auth Automatch',0), - (2096,'gta4ps3grm',NULL,'Grand Theft Auto 4 German (PS3)',0), - (2097,'gta4ps3grmam',NULL,'Grand Theft Auto 4 German Automatch (PS3)',0), - (2098,'gta4xgrm',NULL,'Grand Theft Auto 4 German (Xbox 360)',0), - (2099,'gta4xgrmam',NULL,'Grand Theft Auto 4 German Automatch (Xbox 360)',0), - (2100,'cc3tibwarscd',NULL,'Command & Conquer 3: Tiberium Wars CD Key Auth',0), - (2101,'cc3tibwarscdam',NULL,'Command & Conquer 3: Tiberium Wars CD Key Auth Automatch',0), - (2102,'arkaUSEUds',NULL,'Arkanoid DS (US/EU) (DS)',0), - (2103,'madden09ds',NULL,'Madden NFL 09 (DS)',0), - (2104,'tetpartywii',NULL,'Tetris Party (WiiWare)',0), - (2105,'frontlinesfow',NULL,'Frontlines: Fuel of War',0), - (2106,'simspartywii',NULL,'MySims Party (Wii)',0), - (2107,'momotaro20ds',NULL,'Momotaro Dentetsu 20 Shuunen (DS)',0), - (2108,'srow2ps3',NULL,'Saint\'s Row 2 (PS3)',0), - (2109,'srow2ps3am',NULL,'Saint\'s Row 2 Automatch',0), - (2110,'srow2pc',NULL,'Saint\'s Row 2 (PC)',0), - (2111,'srow2pcam',NULL,'Saint\'s Row 2 Automatch (PC)',0), - (2112,'srow2xb360',NULL,'Saint\'s Row 2 (Xbox 360)',0), - (2113,'srow2xb360am',NULL,'Saint\'s Row 2 Automatch (Xbox 360)',0), - (2116,'aliencrashwii',NULL,'Alien Crash (WiiWare)',0), - (2117,'nakedbrbndds',NULL,'Naked Brothers Band World of Music Tour (DS)',0), - (2118,'legendarypc',NULL,'Legendary (PC)',0), - (2119,'legendarypcam',NULL,'Legendary Automatch (PC)',0), - (2120,'legendarypcd',NULL,'Legendary Demo (PC)',0), - (2121,'megaman9wii',NULL,'Mega Man 9 (WiiWare)',0), - (2122,'dqmonjoker2ds',NULL,'Dragon Quest Monsters: Joker 2 (DS)',0), - (2123,'quizmagicds',NULL,'Quiz Magic Academy DS (DS)',0), - (2124,'Narutonin2ds',NULL,'Naruto: Path of the Ninja 2 (DS)',0), - (2125,'draglade2ds',NULL,'Custom Beat Battle: Draglade 2 (DS)',0), - (2126,'mfcoachwii',NULL,'My Fitness Coach (Wii)',0), - (2127,'othellods',NULL,'Othello de Othello DS',0), - (2128,'redalert3pc',NULL,'Red Alert 3 (PC)',0), - (2129,'redalert3pcam',NULL,'Red Alert 3 Automatch (PC)',0), - (2130,'redalert3pcd',NULL,'Red Alert 3 Demo (PC)',0), - (2131,'redalert3ps3',NULL,'Red Alert 3 (PS3)',0), - (2132,'redalert3ps3am',NULL,'Red Alert 3 Automatch (PS3)',0), - (2133,'plunderps3',NULL,'Age of Booty (PS3)',0), - (2134,'plunderps3am',NULL,'Plunder Automatch (PS3)',0), - (2135,'plunderps3d',NULL,'Plunder Demo (PS3)',0), - (2136,'svsr09ps3',NULL,'WWE Smackdown vs. RAW 2009 (PS3)',0), - (2137,'wordjongFRds',NULL,'Word Jong - FR (DS)',0), - (2138,'bbangminids',NULL,'Big Bang Mini (DS)',0), - (2139,'swbf3psp',NULL,'Star Wars: Battlefront 3 (PSP)',0), - (2140,'swbf3pspam',NULL,'Star Wars: Battlefront 3 Automatch (PSP)',0), - (2141,'CMwrldkitwii',NULL,'Cooking Mama: World Kitchen (Wii)',0), - (2142,'shootantowii',NULL,'Shootanto (Wii)',0), - (2143,'punchoutwii',NULL,'Punch-Out!! (Wii)',0), - (2144,'cod5victoryds',NULL,'Call of Duty 5: Victory (DS)',0), - (2145,'ultibandwii',NULL,'Ultimate Band (Wii)',0), - (2146,'CVjudgmentwii',NULL,'Castlevania: Judgment (Wii)',0), - (2147,'ageofconanb',NULL,'Age of Conan beta',0), - (2148,'wrldgoowii',NULL,'World of Goo (WiiWare)',0), - (2149,'saadtestam',NULL,'SaadsTest',0), - (2151,'digichampUSds',NULL,'Digimon Championship (US) (DS)',0), - (2152,'scotttestam',NULL,'Scott\'s test gamename Automatch',0), - (2153,'testam',NULL,'Test Automatch',0), - (2154,'tpfolEUpcB',NULL,'Turning Point: Fall of Liberty (EU-B) (PC)',0), - (2155,'tpfolEUpcBam',NULL,'Turning Point: Fall of Liberty Automatch (EU-B) (PC)',0), - (2156,'tpfolEUpcBd',NULL,'Turning Point: Fall of Liberty Demo (EU-B) (PC)',0), - (2157,'tpfolpcB',NULL,'Turning Point: Fall of Liberty (B) (PC)',0), - (2158,'tpfolpcBam',NULL,'Turning Point: Fall of Liberty Automatch (B) (PC)',0), - (2159,'tpfolpcBd',NULL,'Turning Point: Fall of Liberty Demo (B) (PC)',0), - (2160,'cc3arenapc',NULL,'Command & Conquer: Arena',0), - (2161,'cc3arenapcam',NULL,'Command & Conquer: Arena Automatch',0), - (2162,'cc3arenapcd',NULL,'Command & Conquer: Arena Demo',0), - (2163,'swbfront3ps3',NULL,'Star Wars Battlefront 3 (PS3)',0), - (2164,'swbfront3pcCam',NULL,'Star Wars Battlefront 3 Automatch (PS3)',0), - (2165,'coh2pc',NULL,'Code of Honor 2 (PC)',0), - (2166,'coh2pcam',NULL,'Code of Honor 2 Automatch (PC)',0), - (2167,'dimensitypc',NULL,'Dimensity (PC)',0), - (2168,'dimensitypcam',NULL,'Dimensity Automatch (PC)',0), - (2169,'dimensitypcd',NULL,'Dimensity Demo (PC)',0), - (2170,'gta4ps3test',NULL,'Grand Theft Auto 4 Test (PS3)',0), - (2171,'50centsandps3',NULL,'50 Cent: Blood on the Sand (PS3)',0), - (2172,'50centsandps3am',NULL,'50 Cent: Blood on the Sand Automatch (PS3)',0), - (2173,'locksquestds',NULL,'Construction Combat: Lock\'s Quest',0), - (2174,'srow2ps3d',NULL,'Saint\'s Row 2 (PS3) Demo',0), - (2175,'srow2ps3dam',NULL,'Saint\'s Row 2 Automatch (PS3) Demo',0), - (2176,'nobuyabou2ds',NULL,'Nobunaga no Yabou DS 2 (DS)',0), - (2177,'memansf2EUDS',NULL,'Mega Man Star Force 2: Zerker x Shinobi / Saurian (EU)',0), - (2178,'bleach2EUds',NULL,'Bleach DS 2: Requiem in the black robe (EU) (DS)',0), - (2179,'reichpc',NULL,'Reich (PC)',0), - (2180,'reichpcam',NULL,'Reich Automatch (PC)',0), - (2181,'reichps3',NULL,'Reich (PS3)',0), - (2182,'reichps3am',NULL,'Reich Automatch (PS3) Clone',0), - (2183,'gloftpokerwii',NULL,'Gameloft Poker (WiiWare)',0), - (2184,'saspc',NULL,'SAS (PC)',0), - (2185,'saspcam',NULL,'SAS Automatch (PC)',0), - (2186,'toribashwii',NULL,'Toribash (WiiWare)',0), - (2187,'acrossingwii',NULL,'Animal Crossing Wii (Wii)',0), - (2188,'poriginps3',NULL,'Fear 2: Project Origin (PS3)',0), - (2189,'poriginps3am',NULL,'Fear 2: Project Origin Automatch (PS3)',0), - (2190,'poriginps3d',NULL,'Fear 2: Project Origin Demo (PS3)',0), - (2191,'poriginpc',NULL,'Fear 2: Project Origin (PC)',0), - (2192,'poriginpcam',NULL,'Fear 2: Project Origin Automatch (PC)',0), - (2193,'poriginpcd',NULL,'Fear 2: Project Origin Demo (PC)',0), - (2194,'civ4xp3','lgNJU7','Civilization IV: 3rd Expansion',0), - (2195,'civ4xp3am','lgNJU7','Civilization IV: 3rd Expansion Automatch',0), - (2196,'civ4xp3d','lgNJU7','Civilization IV: 3rd Expansion Demo',0), - (2197,'necrovision',NULL,'NecroVision',0), - (2198,'tecmoblkickds',NULL,'Tecmo Bowl Kickoff (DS)',0), - (2199,'bballarenaps3',NULL,'Supersonic Acrobatic Rocket-Powered BattleCars: BattleBall Arena',0), - (2200,'bballarenaps3am',NULL,'Supersonic Acrobatic Rocket-Powered BattleCars: BattleBall Arena Automatch',0), - (2201,'ragunonlineds',NULL,'Ragunaroku Online DS (DS)',0), - (2202,'mlb2k9ds',NULL,'Major League Baseball 2K9 Fantasy All-Stars (DS)',0), - (2203,'kororinpa2wii',NULL,'Kororinpa 2 (Wii)',0), - (2204,'stlprincessds',NULL,'Steal Princess (DS)',0), - (2205,'aoemythds',NULL,'Age of Empires: Mythologies (DS)',0), - (2206,'raymanRR3wii',NULL,'Rayman Raving Rabbids 3 (Wii)',0), - (2207,'pitcrewwii',NULL,'Pit Crew Panic (WiiWare)',0), - (2208,'crysiswars','zKbZiM','Crysis Wars',0), - (2209,'menofwarpc',NULL,'Men of War (PC)',0), - (2210,'menofwarpcam',NULL,'Men of War Automatch (PC)',0), - (2211,'sakatsukuds',NULL,'Sakatsuku DS (DS)',0), - (2212,'wtrwarfarewii',NULL,'Water Warfare (WiiWare)',0), - (2213,'civ4colpc','2yheDS','Sid Meier\'s Civilization IV: Colonization (PC/Mac)',0), - (2214,'civ4colpcam','2yheDS','Sid Meier\'s Civilization IV: Colonization Automatch (PC)',0), - (2215,'civ4colpcd','2yheDS','Sid Meier\'s Civilization IV: Colonization Demo (PC)',0), - (2216,'tablegamestds',NULL,'Table Game Stadium (D3-Yuki) (Wii)',0), - (2217,'ppkpocket11ds',NULL,'PowerPro-kun Pocket 11 (DS)',0), - (2218,'bleach2wii',NULL,'BLEACH Wii2 (Wii)',0), - (2219,'cuesportswii',NULL,'Cue Sports (WiiWare)',0), - (2220,'svsr09x360',NULL,'WWE Smackdown vs. RAW 2009 (Xbox 360)',0), - (2221,'hail2chimps3d',NULL,'Hail to the Chimp Demo (PS3)',0), - (2222,'cod5wii',NULL,'Call of Duty 5 (Wii)',0), - (2223,'bgeverwii',NULL,'Best Game Ever (WiiWare)',0), - (2224,'spinvgewii',NULL,'Space Invaders: Get Even (WiiWare)',0), - (2225,'tstgme',NULL,'test game',0), - (2226,'TerroristT2',NULL,'Terrorist Takedown 2',0), - (2227,'pokemonplatds',NULL,'Pokemon Platinum (DS)',0), - (2228,'redalert3pcmb',NULL,'Red Alert 3 (PC) Match Broadcast',0), - (2229,'redalert3pcdmb',NULL,'Red Alert 3 Demo (PC) Match Broadcast',0), - (2230,'jbond08wii',NULL,'James Bond 2008 (Wii)',0), - (2231,'assultwii',NULL,'Assult (Wii)',0), - (2232,'mmartracewii',NULL,'Mega Mart Race (WiiWare)',0), - (2233,'fifa09ds',NULL,'FIFA 09 Soccer (DS)',0), - (2234,'bboarderswii',NULL,'Battle Boarders (WiiWare)',0), - (2235,'cellfactorpsn',NULL,'CellFactor: Ignition (PSN)',0), - (2236,'cellfactorpsnam',NULL,'CellFactor: Ignition Automatch (PSN)',0), - (2237,'witcher',NULL,'The Witcher',0), - (2238,'redalert3pcb',NULL,'Red Alert 3 Beta (PC)',0), - (2239,'redalert3pcbam',NULL,'Red Alert 3 Beta (PC) Automatch',0), - (2241,'redalert3pcbmb',NULL,'Red Alert 3 Beta (PC) Match Broadcast',0), - (2242,'redalert3pcdam',NULL,'Red Alert 3 Demo Automatch (PC)',0), - (2243,'opblitz',NULL,'Operation Blitzsturm',0), - (2244,'shogiwii',NULL,'Shogi (Wii) (WiiWare)',0), - (2245,'redfactionwii',NULL,'Red Faction Wii (Wii)',0), - (2246,'ryantest',NULL,'Ryan\'st test gamename',0), - (2247,'ryantestam',NULL,'Ryan\'st test gamename Automatch',0), - (2248,'mkvsdcps3',NULL,'Mortal Kombat vs. DC Universe (PS3)',0), - (2249,'mkvsdcps3am',NULL,'Mortal Kombat vs. DC Universe Automatch (PS3)',0), - (2250,'mkvsdcxbox',NULL,'Mortal Kombat vs. DC Universe (Xbox)',0), - (2251,'mkvsdcxboxam',NULL,'Mortal Kombat vs. DC Universe Automatch (Xbox)',0), - (2252,'blzrdriverds',NULL,'Blazer Drive (DS)',0), - (2253,'micchannelwii',NULL,'Mic Chat Channel (Wii)',0), - (2254,'rman2blkredds',NULL,'Ryusei no Rockman 3: Black Ace / Red Joker (JP) (DS)',0), - (2255,'jnglspeedwii',NULL,'Jungle Speed (WiiWare)',0), - (2259,'kingtigerspc',NULL,'King Tigers (PC)',0), - (2260,'kingtigerspcam',NULL,'King Tigers Automatch (PC)',0), - (2261,'kingtigerspcd',NULL,'King Tigers Demo (PC)',0), - (2262,'hail2chimps3r',NULL,'Hail to the Chimp Retail (PS3)',0), - (2263,'hail2chimps3ram',NULL,'Hail to the Chimp Retail Automatch (PS3)',0), - (2264,'stalkercs',NULL,'Stalker: Clear Sky (PC)',0), - (2265,'stalkercsam',NULL,'Stalker: Clear Sky Automatch (PC)',0), - (2266,'stalkercsd',NULL,'Stalker: Clear Sky Demo (PC)',0), - (2267,'gradiusrbwii',NULL,'Gradius ReBirth (WiiWare)',0), - (2268,'radiohitzwii',NULL,'Radiohitz: Guess That Song! (WiiWare)',0), - (2269,'kkhrebornwii',NULL,'Katei Kyoshi Hitman REBORN! Kindan no Yami no Delta (Wii)',0), - (2270,'fstarzerods',NULL,'Fantasy Star ZERO (DS)',0), - (2271,'igowii',NULL,'Igo (Wii) (WiiWare)',0), - (2272,'bokujyomonds',NULL,'Bokujyo Monogatari Youkoso! Kaze no Bazzare (DS)',0), - (2273,'hotncoldds',NULL,'Hot \'n\' Cold (DS)',0), - (2274,'ut3jpps3',NULL,'Unreal Tournament 3 Japanese (PS3)',0), - (2275,'ut3jpps3am',NULL,'Unreal Tournament 3 Japanese Automatch (PS3)',0), - (2276,'ut3jppc',NULL,'Unreal Tournament 3 Japanese (PC)',0), - (2277,'ut3jppcam',NULL,'Unreal Tournament 3 Japanese Automatch (PC)',0), - (2278,'AliensCMPC',NULL,'Aliens: Colonial Marines (PC)',0), - (2279,'AliensCMPCam',NULL,'Aliens: Colonial Marines Automatch (PC)',0), - (2280,'AliensCMPCd',NULL,'Aliens: Colonial Marines Demo (PC)',0), - (2281,'AliensCMPS3',NULL,'Aliens: Colonial Marines (PS3)',0), - (2282,'AliensCMPS3am',NULL,'Aliens: Colonial Marines Automatch (PS3)',0), - (2283,'AliensCMPS3d',NULL,'Aliens: Colonial Marines Demo (PS3)',0), - (2284,'Majesty2PC',NULL,'Majesty 2 (PC)',0), - (2285,'Majesty2PCam',NULL,'Majesty 2 Automatch (PC)',0), - (2286,'Majesty2PCd',NULL,'Majesty 2 Demo (PC)',0), - (2287,'FlockPC',NULL,'Flock (PC)',0), - (2288,'FlockPCam',NULL,'Flock Automatch (PC)',0), - (2289,'FlockPCd',NULL,'Flock Demo (PC)',0), - (2290,'FlockPSN',NULL,'Flock (PSN)',0), - (2293,'FlockPSNd',NULL,'Flock Demo (PSN)',0), - (2294,'FlockPSNam',NULL,'Flock Automatch (PSN)',0), - (2295,'bbobblewii',NULL,'Bubble Bobble Wii (WiiWare)',0), - (2296,'cellfactorpc',NULL,'CellFactor: Ignition (PC)',0), - (2297,'cellfactorpcam',NULL,'CellFactor: Ignition Automatch (PSN) Clone',0), - (2298,'wormspsp',NULL,'Worms (PSP)',0), - (2299,'wormspspam',NULL,'Worms Automatch (PSP)',0), - (2300,'MotoGP08PC',NULL,'MotoGP08 (PC)',0), - (2301,'MotoGP08PCam',NULL,'MotoGP08 Automatch (PC)',0), - (2302,'MotoGP08PS3',NULL,'MotoGP08 (PS3)',0), - (2303,'MotoGP08PS3am',NULL,'MotoGP08 Automatch (PS3)',0), - (2304,'sonicbkwii',NULL,'Sonic and the Black Knight (Wii)',0), - (2305,'ghero4wii',NULL,'Guitar Hero 4 (Wii)',0), - (2306,'digichampKRds',NULL,'Digimon Championship (KOR) (DS)',0), - (2307,'mswinterwii',NULL,'Mario & Sonic at the Olympic Winter Games (Wii)',0), - (2309,'mswinterds',NULL,'Mario & Sonic at the Olympic Winter Games (DS)',0), - (2310,'fmasterwtwii',NULL,'Fishing Master: World Tour (Wii)',0), - (2311,'starpballwii',NULL,'Starship Pinball (WiiWare)',0), - (2312,'nfsmwucoverds',NULL,'Need for Speed Most Wanted: Undercover (DS)',0), - (2313,'neopetspapc',NULL,'Neopets Puzzle Adventure (PC)',0), - (2314,'neopetspapcam',NULL,'Neopets Puzzle Adventure Automatch (PC)',0), - (2315,'neopetspapcd',NULL,'Neopets Puzzle Adventure Demo (PC)',0), - (2316,'luminarc2USds',NULL,'Luminous Arc 2 Will (US) (DS)',0), - (2317,'chocotokids',NULL,'Shido to Chocobo no Fushigina Dungeon Tokiwasure no Meikyu DS+(DS)',0), - (2318,'monkmayhemwii',NULL,'Maniac Monkey Mayhem (WiiWare)',0), - (2319,'takoronKRwii',NULL,'Takoron (KOR) (Wii)',0), - (2321,'kaosmpr',NULL,'Kaos MPR',0), - (2322,'kaosmpram',NULL,'Kaos MPR Automatch',0), - (2323,'kaosmprd',NULL,'Kaos MPR Demo',0), - (2324,'mcdcrewds',NULL,'McDonald\'s DS Crew Development Program (DS)',0), - (2325,'ufc09ps3',NULL,'UFC 2009 (PS3)',0), - (2326,'ufc09ps3am',NULL,'UFC 2009 Automatch (PS3)',0), - (2327,'ufc09ps3d',NULL,'UFC 2009 Demo (PS3)',0), - (2328,'ufc09x360',NULL,'UFC 2009 (Xbox 360)',0), - (2329,'ufc09x360am',NULL,'UFC 2009 Automatch (Xbox 360)',0), - (2330,'ufc09x360d',NULL,'UFC 2009 Demo (Xbox 360)',0), - (2331,'skateitds',NULL,'Skate It (DS)',0), - (2332,'robolypsewii',NULL,'Robocalypse (WiiWare)',0), - (2333,'puffinsds',NULL,'Puffins: Island Adventures (DS)',0), - (2334,'koinudewii',NULL,'Koinu de Kururin Wii (WiiWare)',0), - (2335,'lonposUSwii',NULL,'Lonpos (US) (WiiWare)',0), - (2336,'wwkuzushiwii',NULL,'SIMPLE THE Block Kuzushi (WiiWare)',0), - (2337,'wwpuzzlewii',NULL,'Simple: The Number - Puzzle',0), - (2338,'snightxds',NULL,'Summon Night X (DS)',0), - (2339,'hotrodwii',NULL,'High Voltage Hod Rod Show (WiiWare)',0), - (2340,'hotrodwiiam',NULL,'High Voltage Hod Rod Show Automatch (WiiWare)',0), - (2341,'spbobbleds',NULL,'Space Puzzle Bobble (DS)',0), - (2342,'bbarenaEUps3',NULL,'Supersonic Acrobatic Rocket-Powered BattleCars (PSN) (EU)',0), - (2343,'bbarenaEUps3am',NULL,'Supersonic Acrobatic Rocket-Powered BattleCars Automatch (PSN) (EU)',0), - (2344,'bbarenaJPNps3',NULL,'Supersonic Acrobatic Rocket-Powered BattleCars (PSN) (JPN)',0), - (2345,'bbarenaJPNps3am',NULL,'Supersonic Acrobatic Rocket-Powered BattleCars Automatch (PSN) (JPN)',0), - (2346,'girlssecEUds',NULL,'Winx Club Secret Diary 2009 (EU) (DS)',0), - (2347,'ffccechods',NULL,'Final Fantasy Crystal Chronicles: Echos of Time (Wii/DS)',0), - (2348,'unbballswii',NULL,'Unbelievaballs (Wii)',0), - (2349,'hokutokenwii',NULL,'Hokuto no Ken (WiiWare)',0), - (2350,'monracersds',NULL,'Monster Racers (DS)',0), - (2351,'tokyoparkwii',NULL,'Tokyo Friend Park II Wii (Wii)',0), - (2352,'derbydogwii',NULL,'Derby Dog (WiiWare)',0), - (2353,'bbarenaEUps3d',NULL,'Supersonic Acrobatic Rocket-Powered BattleCars Demo (PSN) (EU)',0), - (2354,'bbarenaJPps3d',NULL,'Supersonic Acrobatic Rocket-Powered BattleCars Demo (PSN) (JPN)',0), - (2355,'ballarenaps3d',NULL,'Supersonic Acrobatic Rocket-Powered BattleCars: BattleBall Arena Demo',0), - (2356,'fuelpc',NULL,'FUEL (PC)',0), - (2357,'fuelpcam',NULL,'FUEL Automatch (PC)',0), - (2358,'fuelpcd',NULL,'FUEL Demo (PC)',0), - (2359,'fuelps3',NULL,'FUEL (PS3)',0), - (2360,'fuelps3am',NULL,'FUEL Automatch (PS3)',0), - (2361,'fuelps3d',NULL,'FUEL Demo (PS3)',0), - (2362,'mleatingJPwii',NULL,'Major League Eating: The Game (JPN) (WiiWare)',0), - (2363,'mleatingJPwiiam',NULL,'Major League Eating: The Game Automatch (JPN) (WiiWare)',0), - (2364,'octoEUwii',NULL,'Octomania (EU) (Wii)',0), - (2365,'sbkUSps3',NULL,'SBK \'08 (US) (PS3)',0), - (2366,'sbkUSps3am',NULL,'SBK \'08 Automatch (US) (PS3)',0), - (2367,'sbkUSps3d',NULL,'SBK \'08 Demo (US) (PS3)',0), - (2368,'sbkUSpc',NULL,'SBK \'08 (US) (PC)',0), - (2369,'sbkUSpcam',NULL,'SBK \'08 Automatch (US) (PC)',0), - (2370,'sbkUSpcd',NULL,'SBK \'08 Demo (US) (PC)',0), - (2371,'medarotds',NULL,'MedaRot DS (DS)',0), - (2372,'idolmasterds',NULL,'The Idolmaster DS (DS)',0), - (2373,'ekorisu2ds',NULL,'Ekorisu 2 (DS)',0), - (2374,'redalert3pccd',NULL,'Red Alert 3 (PC, CDKey)',0), - (2375,'redalert3pccdam',NULL,'Red Alert 3 Automatch (PC, CDKey)',0), - (2376,'bbladeds',NULL,'Bay Blade (DS)',0), - (2377,'takameijinwii',NULL,'Takahashi Meijin no Boukenshima (WiiWare)',0), - (2379,'texasholdwii',NULL,'Texas Hold\'em Tournament (WiiWare)',0), - (2380,'legofwreps3',NULL,'WWE Legends of Wrestlemania (PS3)',0), - (2381,'legofwreps3am',NULL,'WWE Legends of Wrestlemania Automatch (PS3)',0), - (2382,'legofwrex360',NULL,'WWE Legends of Wrestlemania (Xbox 360)',0), - (2383,'legofwrex360am',NULL,'Legends of Wrestlemania Automatch (Xbox 360)',0), - (2384,'warnbriads',NULL,'Warnbria no Maho Kagaku (DS)',0), - (2385,'tsurimasterds',NULL,'Mezase!! Tsuri Master DS (DS)',0), - (2386,'jikkyonextwii',NULL,'Jikkyo Powerful Pro Yakyu NEXT (Wii)',0), - (2387,'mua2wii',NULL,'Marvel Ultimate Alliance 2: Fusion (Wii)',0), - (2388,'civrevasiaps3',NULL,'Civilization Revolution (Asia) (PS3)',0), - (2391,'pocketwrldds',NULL,'My Pocket World (DS)',0), - (2392,'segaracingds',NULL,'Sega Superstars Racing (DS)',0), - (2393,'segaracingwii',NULL,'Sega Superstars Racing (Wii)',0), - (2394,'3dpicrossds',NULL,'3D Picross (DS)',0), - (2395,'mkvsdcEUps3',NULL,'Mortal Kombat vs. DC Universe (EU) (PS3)',0), - (2396,'mkvsdcEUps3am',NULL,'Mortal Kombat vs. DC Universe Automatch (EU) (PS3)',0), - (2397,'mkvsdcEUps3b',NULL,'Mortal Kombat vs. DC Universe Beta (EU) (PS3)',0), - (2398,'mkvsdcps3b',NULL,'Mortal Kombat vs. DC Universe Beta (PS3)',0), - (2399,'mkvsdcps3bam',NULL,'Mortal Kombat vs. DC Universe Beta Automatch (PS3)',0), - (2400,'liightwii',NULL,'Liight (WiiWare)',0), - (2401,'mogumonwii',NULL,'Tataite! Mogumon (WiiWare)',0), - (2402,'weleplay09wii',NULL,'Winning Eleven PLAY MAKER 2009 (Wii)',0), - (2403,'mini4wdds',NULL,'Mini 4WD DS (DS)',0), - (2404,'puzzshangwii',NULL,'Puzzle Games Shanghai Wii (WiiWare)',0), - (2405,'crystalw1wii',NULL,'Crystal - Defender W1 (WiiWare)',0), - (2406,'crystalw2wii',NULL,'Crystal - Defender W2 (WiiWare)',0), - (2407,'overturnwii',NULL,'Overturn (WiiWare)',0), - (2408,'vtennisacewii',NULL,'Virtua Tennis: Ace (Wii)',0), - (2409,'yugioh5dds',NULL,'Yu-Gi-Oh 5Ds (DS)',0), - (2410,'im1pc',NULL,'Interstellar Marines (PC)',0), - (2411,'im1pcam',NULL,'Interstellar Marines Automatch (PC)',0), - (2412,'im1pcd',NULL,'Interstellar Marines Demo (PC)',0), - (2413,'civrevasips3d',NULL,'Civilization Revolution Demo (Asia) (PS3)',0), - (2414,'civrevoasiads',NULL,'Sid Meier\'s Civilization Revolution (DS, Asia)',0), - (2415,'50ctsndlvps3',NULL,'50 Cent: Blood on the Sand - Low Violence (PS3)',0), - (2416,'50ctsndlvps3am',NULL,'50 Cent: Blood on the Sand - Low Violence Automatch (PS3)',0), - (2417,'sawpc',NULL,'SAW (PC)',0), - (2418,'sawpcam',NULL,'SAW Automatch (PC)',0), - (2419,'sawpcd',NULL,'SAW Demo (PC)',0), - (2420,'sawps3',NULL,'SAW (PS3)',0), - (2421,'sawps3am',NULL,'SAW Automatch (PS3)',0), - (2422,'sawps3d',NULL,'SAW Demo (PS3)',0), - (2423,'ssmahjongwii',NULL,'Simple Series: The Mah-Jong (WiiWare)',0), - (2424,'carnivalkwii',NULL,'Carnival King (WiiWare)',0), - (2425,'pubdartswii',NULL,'Pub Darts (WiiWare)',0), - (2426,'biahhJPps3',NULL,'Brothers In Arms: Hell\'s Highway (PS3) (JPN)',0), - (2427,'biahhJPps3am',NULL,'Brothers In Arms: Hell\'s Highway Automatch (PS3) (JPN)',0), - (2428,'biahhJPps3d',NULL,'Brothers In Arms: Hell\'s Highway Demo (PS3) (JPN)',0), - (2429,'codwawbeta',NULL,'Call of Duty: World at War Beta',0), - (2430,'fallout3',NULL,'Fallout 3',0), - (2431,'taprace',NULL,'Tap Race (iPhone Sample)',0), - (2432,'tapraceam',NULL,'Tap Race Automatch (iPhone Sample)',0), - (2433,'callofduty5',NULL,'Call of Duty 5',0), - (2434,'cnpanzers2cwb',NULL,'Codename Panzers 2: Cold Wars BETA (PC)',0), - (2435,'cnpanzers2cwbam',NULL,'Codename Panzers 2: Cold Wars BETA Automatch (PC)',0), - (2436,'biahhPRps3',NULL,'Brothers In Arms: Hell\'s Highway (PS3) (RUS)',0), - (2437,'biahhPRps3am',NULL,'Brothers In Arms: Hell\'s Highway Automatch (PS3) (POL/RUS)',0), - (2438,'biahhPRps3d',NULL,'Brothers In Arms: Hell\'s Highway Demo (PS3) (RUS)',0), - (2439,'biahhPCHpc',NULL,'Brothers In Arms: Hell\'s Highway (PC) (POL/CZE/HUNG)',0), - (2440,'biahhPCHpcam',NULL,'Brothers In Arms: Hell\'s Highway Automatch (PC) (POL/CZE/HUNG)',0), - (2441,'biahhRUSpc',NULL,'Brothers In Arms: Hell\'s Highway (PC) (RUS)',0), - (2442,'biahhRUSpcam',NULL,'Brothers In Arms: Hell\'s Highway Automatch (PC) (RUS)',0), - (2443,'stormrisepc',NULL,'Stormrise (PC)',0), - (2444,'stormrisepcam',NULL,'Stormrise Automatch (PC)',0), - (2445,'stormrisepcd',NULL,'Stormrise Demo (PC)',0), - (2446,'stlprinKORds',NULL,'Steal Princess (KOR) (DS)',0), - (2447,'kaiwanowads',NULL,'KAIWANOWA (DS)',0), - (2448,'mvsdk25ds',NULL,'Mario vs Donkey Kong 2.5 (DS)',0), - (2449,'stlprinEUds',NULL,'Steal Princess (EU) (DS)',0), - (2450,'gh4metalwii',NULL,'Guitar Hero 4: Metallica (Wii)',0), - (2451,'psyintdevpc',NULL,'Psyonix Internal Development (PC)',0), - (2452,'psyintdevpcam',NULL,'Psyonix Internal Development Automatch (PC)',0), - (2453,'psyintdevpcd',NULL,'Psyonix Internal Development Demo (PC)',0), - (2454,'simsracingds',NULL,'MySims Racing DS (DS)',0), - (2455,'airhockeywii',NULL,'World Air Hockey Challenge! (WiiWare)',0), - (2456,'evaspacewii',NULL,'Evasive Space (WiiWare)',0), - (2457,'spaceremixds',NULL,'Space Invaders Extreme Remix (DS)',0), - (2458,'menofwarpcb',NULL,'Men of War (PC) BETA',0), - (2459,'menofwarpcbam',NULL,'Men of War Automatch (PC) BETA',0), - (2460,'codwaw',NULL,'Call of Duty: World at War',0), - (2461,'kentomashods',NULL,'Ide Yohei no Kento Masho DS (DS)',0), - (2462,'beatrunnerwii',NULL,'Beat Runner (WiiWare)',0), - (2463,'hunterdanwii',NULL,'Hunter Dan\'s Triple Crown Tournament Fishing (Wii)',0), - (2464,'rainbowislwii',NULL,'Rainbow Island Tower! (WiiWare)',0), - (2465,'srgakuends',NULL,'Super Robot Gakuen (DS)',0), - (2466,'srgakuendsam',NULL,'Super Robot Gakuen Automatch (DS)',0), - (2467,'cstaisends',NULL,'Chotto Sujin Taisen (DS)',0), - (2468,'winx2010ds',NULL,'Winx Club Secret Diary 2010 (DS)',0), - (2469,'mxravenpsp',NULL,'MX Reflex (Raven) (PSP)',0), - (2470,'mxravenpspam',NULL,'MX Raven Automatch (PSP)',0), - (2471,'sukashikds',NULL,'Sukashikashipanman DS (DS)',0), - (2472,'famista09ds',NULL,'Pro Yakyu Famista DS 2009 (DS)',0), - (2473,'hawxpc',NULL,'Tom Clancy\'s HAWX',0), - (2474,'fxtrainingds',NULL,'FX Training DS (DS)',0), - (2475,'monhuntergwii',NULL,'Monster Hunter G (Wii)',0), - (2476,'dinerdashwii',NULL,'Diner Dash (WiiWare)',0), - (2477,'s_l4d',NULL,'Steam Left 4 Dead',0), - (2478,'guinnesswriph',NULL,'Guinness World Records: The Video Game (iPhone)',0), - (2479,'guinnesswripham',NULL,'Guinness World Records: The Video Game Automatch (iPhone)',0), - (2480,'guinnesswriphd',NULL,'Guinness World Records: The Video Game Demo (iPhone)',0), - (2481,'konsportswii',NULL,'Konami Sports Club @ Home (WiiWare)',0), - (2482,'cpenguin2ds',NULL,'Club Penguin 2 (DS)',0), - (2483,'biahhPOLps3',NULL,'Brothers In Arms: Hell\'s Highway (PS3) (POL)',0), - (2484,'biahhPOLps3am',NULL,'Brothers In Arms: Hell\'s Highway Automatch (PS3) (POL)',0), - (2485,'biahhPOLps3d',NULL,'Brothers In Arms: Hell\'s Highway Demo (PS3) (POL)',0), - (2486,'exciteracewii',NULL,'Excite Racing (Wii)',0), - (2487,'cpenguin2wii',NULL,'Club Penguin 2 (Wii)',0), - (2488,'tcounterwii',NULL,'Tecmo Counter',0), - (2489,'h2cdigitalps3',NULL,'Hail to the Chimp (PSN)',0), - (2490,'h2cdigitalps3d',NULL,'Hail to the Chimp Demo (PSN)',0), - (2491,'motogp09ps3',NULL,'Moto GP 09 (PS3)',0), - (2492,'motogp09ps3am',NULL,'Moto GP 09 Automatch (PS3)',0), - (2493,'motogp09ps3d',NULL,'Moto GP 09 Demo (PS3)',0), - (2494,'motogp09pc',NULL,'Moto GP 09 (PC)',0), - (2495,'motogp09pcam',NULL,'Moto GP 09 Automatch (PC)',0), - (2496,'motogp09pcd',NULL,'Moto GP 09 Demo (PC)',0), - (2497,'spectro2wii',NULL,'Spectrobes 2 (Wii)',0), - (2498,'ninTest/',NULL,'Nintendo Development Testing masterID 0',0), - (2499,'ninTest/am',NULL,'Nintendo Development Testing masterID 0 Automatch',0), - (2500,'ninTest0',NULL,'Nintendo Development Testing masterID 1',0), - (2501,'ninTest0am',NULL,'Nintendo Development Testing masterID 1 Automatch',0), - (2502,'ninTest1',NULL,'Nintendo Development Testing masterID 2',0), - (2503,'ninTest1am',NULL,'Nintendo Development Testing masterID 2 Automatch',0), - (2504,'ninTest2',NULL,'Nintendo Development Testing masterID 3',0), - (2505,'ninTest2am',NULL,'Nintendo Development Testing masterID 3 Automatch',0), - (2506,'ninTest3',NULL,'Nintendo Development Testing masterID 4',0), - (2507,'ninTest3am',NULL,'Nintendo Development Testing masterID 4 Automatch',0), - (2508,'ninTest4',NULL,'Nintendo Development Testing masterID 5',0), - (2509,'ninTest4am',NULL,'Nintendo Development Testing masterID 5 Automatch',0), - (2510,'ninTest5',NULL,'Nintendo Development Testing masterID 6',0), - (2511,'ninTest5am',NULL,'Nintendo Development Testing masterID 6 Automatch',0), - (2512,'ninTest6',NULL,'Nintendo Development Testing masterID 7',0), - (2513,'ninTest6am',NULL,'Nintendo Development Testing masterID 7 Automatch',0), - (2514,'ninTest7',NULL,'Nintendo Development Testing masterID 8',0), - (2515,'ninTest7am',NULL,'Nintendo Development Testing masterID 8 Automatch',0), - (2516,'ninTest8',NULL,'Nintendo Development Testing masterID 9',0), - (2517,'ninTest8am',NULL,'Nintendo Development Testing masterID 9 Automatch',0), - (2518,'ninTest9',NULL,'Nintendo Development Testing masterID 10',0), - (2519,'ninTest9am',NULL,'Nintendo Development Testing masterID 10 Automatch',0), - (2521,'ninTest:am',NULL,'Nintendo Development Testing masterID 11 Automatch',0), - (2522,'ninTest;',NULL,'Nintendo Development Testing masterID 12',0), - (2523,'ninTest;am',NULL,'Nintendo Development Testing masterID 12 Automatch',0), - (2524,'ninTest<',NULL,'Nintendo Development Testing masterID 13',0), - (2525,'ninTest',NULL,'Nintendo Development Testing masterID 15',0), - (2529,'ninTest>am',NULL,'Nintendo Development Testing masterID 15 Automatch',0), - (2530,'ninTest?',NULL,'Nintendo Development Testing masterID 16',0), - (2531,'ninTest?am',NULL,'Nintendo Development Testing masterID 16 Automatch',0), - (2532,'ninTest@',NULL,'Nintendo Development Testing masterID 17',0), - (2533,'ninTest@am',NULL,'Nintendo Development Testing masterID 17 Automatch',0), - (2534,'ninTest-',NULL,'Nintendo Development Testing masterID 18',0), - (2535,'ninTest-am',NULL,'Nintendo Development Testing masterID 18 Automatch',0), - (2536,'ninTest.',NULL,'Nintendo Development Testing masterID 19',0), - (2537,'ninTest.am',NULL,'Nintendo Development Testing masterID 19 Automatch',0), - (2538,'dartspartywii',NULL,'Darts Wii Party (Wii)',0), - (2539,'3celsiuswii',NULL,'3* Celsius (WiiWare)',0), - (2540,'acejokerUSds',NULL,'Mega Man Star Force 3: Black Ace/Red Joker (US) (DS)',0), - (2541,'Rabgohomewii',NULL,'Rabbids Go Home (Wii)',0), - (2542,'tmntsmashwii',NULL,'TMNT Smash Up (Wii)',0), - (2543,'simplejudowii',NULL,'Simple The Ju-Do (WiiWare)',0), - (2544,'menofwarpcd',NULL,'Men of War MP DEMO (PC)',0), - (2545,'menofwarpcdam',NULL,'Men of War MP DEMO Automatch (PC)',0), - (2547,'rdr2ps3',NULL,'Red Dead Redemption (PS3)',0), - (2548,'rdr2ps3am',NULL,'Red Dead Redemption Automatch (PS3)',0), - (2549,'gh4vhalenwii',NULL,'Guitar Hero 4: Van Halen (Wii)',0), - (2550,'gh4vhalenwiiam',NULL,'Guitar Hero 4: Van Halen Automatch (Wii)',0), - (2551,'escviruswii',NULL,'Escape Virus (WiiWare)',0), - (2552,'rfactoryKRds',NULL,'Rune Factory: A Fantasy Harverst Moon (KOR) (DS)',0), - (2553,'banburadxds',NULL,'Banbura DX Photo Frame Radio (DS)',0), - (2554,'mebiuswii',NULL,'Mebius Drive (WiiWare)',0), - (2555,'okirakuwii',NULL,'Okiraku Daihugou Wii (WiiWare)',0), - (2556,'sbk09pc',NULL,'SBK \'09 (PC)',0), - (2557,'sbk09ps3',NULL,'SBK \'09 (PS3)',0), - (2558,'sbk09ps3am',NULL,'SBK \'09 Automatch (PS3)',0), - (2559,'sbk09pcam',NULL,'SBK \'09 Automatch (PC)',0), - (2560,'poriginpcjp',NULL,'Fear 2: Project Origin (JP) (PC)',0), - (2561,'poriginpcjpam',NULL,'Fear 2: Project Origin Automatch (JP) (PC)',0), - (2562,'poriginpcjpd',NULL,'Fear 2: Project Origin Demo (JP) (PC)',0), - (2563,'poriginps3jp',NULL,'Fear 2: Project Origin (JP) (PS3)',0), - (2564,'poriginps3jpam',NULL,'Fear 2: Project Origin Automatch (JP) (PS3)',0), - (2565,'poriginps3jpd',NULL,'Fear 2: Project Origin Demo (JP) (PS3)',0), - (2566,'section8pc',NULL,'Section 8 (PC)',0), - (2567,'section8pcam',NULL,'Section 8 Automatch (PC)',0), - (2568,'section8pcd',NULL,'Section 8 Demo (PC)',0), - (2569,'section8ps3',NULL,'Section 8 (PS3)',0), - (2570,'section8ps3am',NULL,'Section 8 Automatch (PS3)',0), - (2571,'section8ps3d',NULL,'Section 8 Demo (PS3)',0), - (2572,'section8x360',NULL,'Section 8 (Xbox360)',0), - (2573,'section8x360am',NULL,'Section 8 Automatch (Xbox360)',0), - (2574,'section8x360d',NULL,'Section 8 Demo (Xbox360)',0), - (2575,'buccaneerpc',NULL,'Buccaneer (PC)',0), - (2576,'buccaneerpcam',NULL,'Buccaneer Automatch (PC)',0), - (2577,'buccaneerpcd',NULL,'Buccaneer Demo (PC)',0), - (2578,'civ4coljp','5wddmt','Sid Meier\'s Civilization IV: Colonization (PC Japanese)',0), - (2579,'civ4coljpam','5wddmt','Sid Meier\'s Civilization IV: Colonization Automatch (PC Japanese)',0), - (2580,'beateratorpsp',NULL,'Beaterator (PSP)',0), - (2581,'beateratorpspam',NULL,'Beaterator Automatch (PSP)',0), - (2582,'beateratorpspd',NULL,'Beaterator Demo (PSP)',0), - (2583,'sonicrkords',NULL,'Sonic Rush Adventure (KOR) (DS)',0), - (2584,'mmadnesswii',NULL,'Military Madness (WiiWare)',0), - (2585,'chesschalwii',NULL,'Chess Challenge! (WiiWare)',0), - (2586,'chesschalwiiam',NULL,'Chess Challenge! Automatch (WiiWare)',0), - (2587,'narutorev3wii',NULL,'Naruto Shippuden: Clash of Ninja Revolution 3 (Wii)',0), - (2588,'decasport2wii',NULL,'Deca Sports 2 (Wii)',0), - (2589,'suparobods',NULL,'Suparobo Gakuen (DS)',0), - (2590,'gh4ghitswii',NULL,'Guitar Hero 4: Greatest Hits (Wii)',0), - (2591,'simsraceEUds',NULL,'MySims Racing DS (EU) (DS)',0), - (2592,'blockrushwii',NULL,'Blockrush! (WiiWare)',0), - (2593,'simsraceJPNds',NULL,'MySims Racing DS (JPN) (DS)',0), - (2594,'superv8pc',NULL,'Superstars V8 Racing (PC)',0), - (2595,'superv8pcam',NULL,'Superstars V8 Racing Automatch (PC)',0), - (2596,'superv8pcd',NULL,'Superstars V8 Racing Demo (PC)',0), - (2597,'superv8ps3',NULL,'Superstars V8 Racing (PS3)',0), - (2598,'superv8ps3am',NULL,'Superstars V8 Racing Automatch (PS3)',0), - (2599,'superv8ps3d',NULL,'Superstars V8 Racing Demo (PS3)',0), - (2600,'boardgamesds',NULL,'The Best of Board Games (DS)',0), - (2601,'cardgamesds',NULL,'The Best of Card Games (DS)',0), - (2602,'colcourseds',NULL,'Collision Course (DS)',0), - (2603,'brigades',NULL,'Gamespy Brigades',0), - (2604,'puyopuyo7ds',NULL,'PuyoPuyo 7 (DS/Wii)',0), - (2605,'qsolace',NULL,'Quantum of Solace',0), - (2606,'tcendwar',NULL,'Tom Clancy\'s EndWar',0), - (2607,'kidslearnwii',NULL,'Kids Learning Desk (WiiWare)',0), - (2608,'svsr10ps3',NULL,'WWE Smackdown vs. Raw 2010 (PS3)',0), - (2609,'svsr10ps3am',NULL,'WWE Smackdown vs. Raw 2010 Automatch (PS3)',0), - (2610,'svsr10ps3d',NULL,'WWE Smackdown vs. Raw 2010 Demo (PS3)',0), - (2611,'svsr10x360',NULL,'WWE Smackdown vs. Raw 2010 (Xbox 360)',0), - (2612,'svsr10x360am',NULL,'WWE Smackdown vs. Raw 2010 Automatch (Xbox 360)',0), - (2613,'svsr10x360d',NULL,'WWE Smackdown vs. Raw 2010 Demo (Xbox 360)',0), - (2614,'momo2010wii',NULL,'Momotaro Dentetsu 2010 Nendoban (Wii)',0), - (2615,'cardherods',NULL,'Card Hero DSi (DS)',0), - (2616,'cardherodsam',NULL,'Card Hero DSi Automatch (DS)',0), - (2617,'smball2iph',NULL,'Super Monkey Ball 2 (iPhone)',0), - (2618,'smball2ipham',NULL,'Super Monkey Ball 2 Automatch (iPhone)',0), - (2619,'smball2iphd',NULL,'Super Monkey Ball 2 Demo (iPhone)',0), - (2620,'beateratoriph',NULL,'Beaterator (iPhone)',0), - (2621,'beateratoripham',NULL,'Beaterator Automatch (iPhone)',0), - (2622,'beateratoriphd',NULL,'Beaterator Demo (iPhone)',0), - (2623,'conduitwii',NULL,'The Conduit (Wii)',0), - (2624,'hookagainwii',NULL,'Hooked Again! (Wii)',0), - (2625,'rfactory3ds',NULL,'Rune Factory 3 (DS)',0), - (2626,'disneydev',NULL,'Disney Development/Testing',0), - (2627,'disneydevam',NULL,'Disney Development/Testing Automatch',0), - (2628,'sporearenads',NULL,'Spore Hero Arena (DS)',0), - (2629,'treasurewldds',NULL,'Treasure World (DS)',0), - (2630,'unowii',NULL,'UNO (WiiWare)',0), - (2631,'mekurucawii',NULL,'Mekuruca (WiiWare)',0), - (2632,'bderlandspc',NULL,'Borderlands (PC)',0), - (2633,'bderlandspcam',NULL,'Borderlands Automatch (PC)',0), - (2634,'bderlandspcd',NULL,'Borderlands Demo (PC)',0), - (2635,'bderlandsps3',NULL,'Borderlands (PS3)',0), - (2636,'bderlandsps3am',NULL,'Borderlands Automatch (PS3)',0), - (2637,'bderlandsps3d',NULL,'Borderlands Demo (PS3)',0), - (2638,'bderlandsx360',NULL,'Borderlands (360)',0), - (2639,'bderlands360am',NULL,'Borderlands Automatch (360)',0), - (2640,'bderlandsx360d',NULL,'Borderlands Demo (360)',0), - (2641,'simsportsds',NULL,'MySims Sports (DS)',0), - (2642,'simsportswii',NULL,'MySims Sports (Wii)',0), - (2643,'pokedngnwii',NULL,'Pokemon Dungeon (Wii)',0), - (2644,'arma2pc',NULL,'Arma II (PC)',0), - (2645,'arma2pcam',NULL,'Arma II Automatch (PC)',0), - (2646,'arma2pcd',NULL,'Arma II Demo (PC)',0), - (2647,'rubikguidewii',NULL,'Rubik\'s Puzzle World: Guide (WiiWare)',0), - (2648,'quizmagic2ds',NULL,'Quiz Magic Academy DS2 (DS)',0), - (2649,'bandbrosEUds',NULL,'Daiggaso! Band Brothers DX (EU) (DS)',0), - (2650,'swsnow2wii',NULL,'Shaun White Snowboarding 2 (Wii)',0), - (2651,'scribnautsds',NULL,'Scribblenauts (DS)',0), - (2652,'fifasoc10ds',NULL,'FIFA Soccer 10 (DS)',0), - (2653,'foreverbl2wii',NULL,'Forever Blue 2 (Wii)',0), - (2654,'namcotest',NULL,'Namco SDK Test',0), - (2655,'namcotestam',NULL,'Namco SDK Test Automatch',0), - (2656,'namcotestd',NULL,'Namco SDK Test Demo',0), - (2657,'blindpointpc',NULL,'Blind Point (PC)',0), - (2658,'blindpointpcam',NULL,'Blind Point Automatch (PC)',0), - (2659,'blindpointpcd',NULL,'Blind Point Demo (PC)',0), - (2660,'propocket12ds',NULL,'PowerPro-kun Pocket 12 (DS)',0), - (2661,'seafarmwii',NULL,'Seafarm (WiiWare)',0), - (2662,'dragquestsds',NULL,'Dragon Quest S (DSiWare)',0), - (2663,'dawnheroesds',NULL,'Dawn of Heroes (DS)',0), - (2664,'monhunter3wii',NULL,'Monster Hunter 3 (JPN) (Wii)',0), - (2665,'appletest',NULL,'Apple SDK test',0), - (2666,'appletestam',NULL,'Apple SDK test Automatch',0), - (2667,'appletestd',NULL,'Apple SDK test Demo',0), - (2668,'harbunkods',NULL,'Harlequin Bunko (DS)',0), - (2669,'unodsi',NULL,'UNO (DSiWare)',0), - (2670,'beaterator',NULL,'Beaterator (PSP/iphone)',0), - (2671,'beateratoram',NULL,'Beaterator Automatch (PSP/iphone)',0), - (2672,'beateratord',NULL,'Beaterator Demo (PSP/iphone)',0), - (2673,'ragonlineKRds',NULL,'Ragunaroku Online DS (KOR) (DS)',0), - (2674,'dragoncrwnwii',NULL,'Dragon\'s Crown (Wii)',0), - (2675,'ascensionpc',NULL,'Ascension (PC)',0), - (2676,'ascensionpcam',NULL,'Ascension Automatch (PC)',0), - (2677,'ascensionpcd',NULL,'Ascension Demo (PC)',0), - (2678,'swbfespsp',NULL,'Star Wars: Battlefront - Elite Squadron (PSP)',0), - (2679,'swbfespspam',NULL,'Star Wars: Battlefront - Elite Squadron Automatch (PSP)',0), - (2680,'swbfespspd',NULL,'Star Wars: Battlefront - Elite Squadron Demo (PSP)',0), - (2681,'nba2k10wii',NULL,'NBA 2K10 (Wii)',0), - (2682,'nhl2k10wii',NULL,'NHL 2K10 (Wii)',0), - (2683,'mk9test',NULL,'Midway MK9 Test',0), - (2684,'mk9testam',NULL,'Midway MK9 Test Automatch',0), - (2685,'mk9testd',NULL,'Midway MK9 Test Demo',0), - (2686,'kateifestds',NULL,'Katei Kyoshi Hitman Reborn DS Vongole Festival Online (DS)',0), - (2687,'luminarc2EUds',NULL,'Luminous Arc 2 Will (EU) (DS)',0), - (2688,'tatvscapwii',NULL,'Tatsunoko vs. Capcom Ultimate All Stars (Wii)',0), - (2689,'petz09ds',NULL,'Petz Catz/Dogz/Hamsterz/Babiez 2009 (DS)',0), - (2690,'rtlwsportswii',NULL,'RTL Winter Sports 2010 (Wii)',0), - (2691,'tomenasawii',NULL,'Tomenasanner (WiiWare)',0), - (2692,'luchalibrepc',NULL,'Lucha Libre AAA 2010 (PC)',0), - (2693,'luchalibrepcam',NULL,'Lucha Libre AAA 2010 Automatch (PC)',0), - (2694,'luchalibrepcd',NULL,'Lucha Libre AAA 2010 Demo (PC)',0), - (2695,'luchalibreps3',NULL,'Lucha Libre AAA 2010 (PS3)',0), - (2696,'luchalibreps3am',NULL,'Lucha Libre AAA 2010 Automatch (PS3)',0), - (2697,'luchalibreps3d',NULL,'Lucha Libre AAA 2010 Demo (PS3)',0), - (2698,'simsflyerswii',NULL,'MySims Flyers (Wii)',0), - (2699,'ludicrouspc',NULL,'Ludicrous (PC)',0), - (2700,'ludicrouspcam',NULL,'Ludicrous Automatch (PC)',0), - (2701,'ludicrouspcd',NULL,'Ludicrous Demo (PC)',0), - (2702,'ludicrousmac',NULL,'Ludicrous (MAC)',0), - (2703,'ludicrousmacam',NULL,'Ludicrous Automatch (MAC)',0), - (2704,'ludicrousmacd',NULL,'Ludicrous Demo (MAC)',0), - (2705,'pbellumr1',NULL,'Parabellum Region 1 (PC)',0), - (2706,'pbellumr2',NULL,'Parabellum Region 2 (PC)',0), - (2707,'pbellumr3',NULL,'Parabellum Region 3 (PC)',0), - (2708,'imaginejdds',NULL,'Imagine: Jewelry Designer (DS)',0), - (2709,'imagineartds',NULL,'Imagine: Artist (DS)',0), - (2710,'tvshwking2wii',NULL,'TV Show King 2 (WiiWare)',0), - (2711,'sballrevwii',NULL,'Spaceball: Revolution (WiiWare)',0), - (2712,'orderofwarpc',NULL,'Order of War (PC)',0), - (2713,'orderofwarpcam',NULL,'Order of War Automatch (PC)',0), - (2714,'orderofwarpcd',NULL,'Order of War Demo (PC)',0), - (2715,'lbookofbigsds',NULL,'Little Book of Big Secrets (DS)',0), - (2716,'scribnauteuds',NULL,'Scribblenauts (EU) (DS)',0), - (2717,'buccaneer',NULL,'Buccaneer The Pursuit of Infamy',0), - (2718,'kenteitvwii',NULL,'Kentei! TV Wii (Wii)',0), - (2719,'yugioh5dwii',NULL,'Yu-Gi-Oh! 5D\'s Duel Simulator (Wii)',0), - (2720,'fairyfightps3',NULL,'Fairytale Fights (PS3)',0), - (2721,'fairyfightps3am',NULL,'Fairytale Fights Automatch (PS3)',0), - (2722,'fairyfightps3d',NULL,'Fairytale Fights Demo (PS3)',0), - (2723,'fairyfightpc',NULL,'Fairytale Fights (PC)',0), - (2724,'fairyfightpcam',NULL,'Fairytale Fights Automatch (PC)',0), - (2725,'fairyfightpcd',NULL,'Fairytale Fights Demo (PC)',0), - (2726,'50centjpnps3',NULL,'50 Cent: Blood on the Sand (JPN) (PS3)',0), - (2727,'50centjpnps3am',NULL,'50 Cent: Blood on the Sand Automatch (JPN) (PS3)',0), - (2728,'50centjpnps3d',NULL,'50 Cent: Blood on the Sand Demo (JPN) (PS3)',0), - (2729,'codmw2ds',NULL,'Call of Duty: Modern Warfare 2 (DS)',0), - (2730,'jbond2009ds',NULL,'James Bond 2009 (DS)',0), - (2731,'resevildrkwii',NULL,'Resident Evil: The Darkside Chronicles (Wii)',0), - (2732,'musicmakerwii',NULL,'Music Maker (Wii)',0), - (2733,'figlandds',NULL,'Figland (DS)',0), - (2734,'bonkwii',NULL,'Bonk (Wii)',0), - (2735,'bomberman2wii',NULL,'Bomberman 2 (Wii)',0), - (2736,'bomberman2wiid',NULL,'Bomberman 2 Demo (Wii)',0), - (2737,'dreamchronwii',NULL,'Dream Chronicle (Wii)',0), - (2738,'gokuidsi',NULL,'Gokui (DSiWare)',0), - (2739,'usingwii',NULL,'U-Sing (Wii)',0), - (2740,'shikagariwii',NULL,'Shikagari (Wii)',0), - (2741,'puyopuyo7wii',NULL,'Puyopuyo 7 (Wii)',0), - (2742,'winelev10wii',NULL,'Winning Eleven Play Maker 2010 (Wii)',0), - (2743,'section8pcb',NULL,'Section 8 Beta (PC)',0), - (2744,'section8pcbam',NULL,'Section 8 Beta Automatch (PC)',0), - (2745,'section8pcbd',NULL,'Section 8 Beta Demo (PC)',0), - (2746,'ubraingamesds',NULL,'Ultimate Brain Games (DS)',0), - (2747,'ucardgamesds',NULL,'Ultimate Card Games (DS)',0), - (2748,'postpetds',NULL,'PostPetDS Yumemiru Momo to Fushigi no Pen (DS)',0), - (2749,'mfightbbultds',NULL,'Metal Fight Bay Blade ULTIMATE (DS)',0), - (2750,'strategistwii',NULL,'Strategist (Wii)',0), - (2751,'bmbermanexdsi',NULL,'Bomberman Express (DSiWare)',0), - (2752,'blockoutwii',NULL,'Blockout (Wii)',0), - (2753,'rdr2x360',NULL,'Red Dead Redemption (x360)',0), - (2754,'rdr2x360am',NULL,'Red Dead Redemption Automatch (x360)',0), - (2757,'fairyfightspc',NULL,'Fairytale Fights (PC)',0), - (2758,'fairyfightspcam',NULL,'Fairytale Fights Automatch (PC)',0), - (2759,'fairyfightspcd',NULL,'Fairytale Fights Demo (PC)',0), - (2760,'stalkercoppc',NULL,'STALKER: Call of Pripyat (PC)',0), - (2761,'stalkercoppcam',NULL,'STALKER: Call of Pripyat Automatch (PC)',0), - (2762,'stalkercoppcd',NULL,'STALKER: Call of Pripyat Demo (PC)',0), - (2763,'strategistpc',NULL,'The Strategist (PC)',0), - (2764,'strategistpcam',NULL,'The Strategist Automatch (PC)',0), - (2765,'strategistpcd',NULL,'The Strategist Demo (PC)',0), - (2766,'strategistpsn',NULL,'The Strategist (PSN)',0), - (2767,'strategistpsnam',NULL,'The Strategist Automatch (PSN)',0), - (2768,'strategistpsnd',NULL,'The Strategist Demo (PSN)',0), - (2769,'tataitemogwii',NULL,'Tataite! Mogumon US/EU (WiiWare)',0), - (2770,'ufc10ps3',NULL,'UFC 2010 (PS3)',0), - (2771,'ufc10ps3am',NULL,'UFC 2010 Automatch (PS3)',0), - (2772,'ufc10ps3d',NULL,'UFC 2010 Demo (PS3)',0), - (2773,'ufc10x360',NULL,'UFC 2010 (x360)',0), - (2774,'ufc10x360am',NULL,'UFC 2010 Automatch (x360)',0), - (2775,'ufc10x360d',NULL,'UFC 2010 Demo (x360)',0), - (2776,'mmtest',NULL,'Matchmaking Backend Test',0), - (2777,'mmtestam',NULL,'Matchmaking Backend Test Automatch',0), - (2778,'talesofgrawii',NULL,'Tales of Graces (Wii)',0), - (2779,'dynamiczanwii',NULL,'Dynamic Zan (Wii)',0), - (2780,'fushigidunds',NULL,'Fushigi no Dungeon Furai no Shiren 4 Kami no Me to Akama no Heso (DS)',0), - (2781,'idraculawii',NULL,'iDracula (WiiWare)',0), - (2782,'metalfightds',NULL,'Metal Fight Bayblade (DS)',0), - (2783,'wormswiiware',NULL,'Worms (WiiWare)',0), - (2784,'wormswiiwaream',NULL,'Worms Automatch (WiiWare)',0), - (2785,'justsingds',NULL,'Just Sing! (DS)',0), - (2786,'gtacwarspsp',NULL,'Grand Theft Auto: Chinatown Wars (PSP)',0), - (2787,'gtacwarspspam',NULL,'Grand Theft Auto: Chinatown Wars Automatch (PSP)',0), - (2788,'gtacwarspspd',NULL,'Grand Theft Auto: Chinatown Wars Demo (PSP)',0), - (2789,'gtacwiphone',NULL,'Grand Theft Auto: Chinatown Wars (iPhone)',0), - (2790,'gtacwiphoneam',NULL,'Grand Theft Auto: Chinatown Wars Automatch (iPhone)',0), - (2791,'gtacwiphoned',NULL,'Grand Theft Auto: Chinatown Wars Demo (iPhone)',0), - (2792,'trkmaniads',NULL,'Trackmania (DS)',0), - (2793,'trkmaniawii',NULL,'Trackmania (Wii)',0), - (2794,'megaman10wii',NULL,'Mega Man 10 (WiiWare)',0), - (2795,'aarmy3',NULL,'America\'s Army 3',0), - (2796,'tycoonnyc',NULL,'Tycoon City - New York',0), - (2797,'sinpunish2wii',NULL,'Sin & Punishment 2 (Wii)',0), - (2798,'fuelps3ptchd',NULL,'FUEL (PS3) Patched version',0), - (2799,'fuelps3ptchdam',NULL,'FUEL Automatch (PS3) Patched version',0), - (2800,'sonicdlwii',NULL,'Sonic DL (WiiWare)',0), - (2801,'demonforgeps3',NULL,'Demon\'s Forge (PS3)',0), - (2802,'demonforgeps3am',NULL,'Demon\'s Forge Automatch (PS3)',0), - (2803,'demonforgeps3d',NULL,'Demon\'s Forge Demo (PS3)',0), - (2804,'demonforgepc',NULL,'Demon\'s Forge (PC)',0), - (2805,'demonforgepcam',NULL,'Demon\'s Forge Automatch (PC)',0), - (2806,'demonforgepcd',NULL,'Demon\'s Forge Demo (PC)',0), - (2807,'hooploopwii',NULL,'HooperLooper (WiiWare)',0), - (2809,'test1',NULL,'test1',0), - (2810,'maxpayne3pc',NULL,'Max Payne 3 (PC)',0), - (2811,'maxpayne3pcam',NULL,'Max Payne 3 Automatch (PC)',0), - (2812,'maxpayne3pcd',NULL,'Max Payne 3 Demo (PC)',0), - (2813,'maxpayne3ps3',NULL,'Max Payne 3 (PS3)',0), - (2814,'maxpayne3ps3am',NULL,'Max Payne 3 Automatch (PS3)',0), - (2815,'maxpayne3ps3d',NULL,'Max Payne 3 Demo (PS3)',0), - (2816,'maxpayne3x360',NULL,'Max Payne 3 (360)',0), - (2817,'maxpayne3x360am',NULL,'Max Payne 3 Automatch (360)',0), - (2818,'maxpayne3x360d',NULL,'Max Payne 3 Demo (360)',0), - (2819,'wordjongeuds',NULL,'Wordjong EU (DS)',0), - (2820,'sengo3wii',NULL,'Sengokumuso 3',0), - (2821,'bewarewii',NULL,'Beware (WiiWare)',0), - (2822,'hinterland',NULL,'Hinterland',0), - (2823,'hastpaint2wii',NULL,'Greg Hastings Paintball 2 (Wii)',0), - (2824,'rockstarsclub',NULL,'Rockstar Social Club',0), - (2825,'rockstarsclubam',NULL,'Rockstar Social Club Automatch',0), - (2826,'plandmajinds',NULL,'Professor Layton and Majin no Fue (DS)',0), - (2827,'powerkoushds',NULL,'Powerful Koushien (DS)',0), - (2828,'cavestorywii',NULL,'Cave Story (WiiWare)',0), - (2829,'blahblahtest',NULL,'Just another test for masterid',0), - (2830,'blahtest',NULL,'Just another test for masterid',0), - (2831,'blahmasterid',NULL,'Just another test for masterid',0), - (2832,'bädmasterid',NULL,'',0), - (2833,'explomäntest',NULL,'blah',0), - (2836,'3dpicrosseuds',NULL,'3D Picross (EU) (DS)',0), - (2837,'gticsfestwii',NULL,'GTI Club Supermini Festa (Wii)',0), - (2838,'narutor3euwii',NULL,'Naruto Shippuden: Clash of Ninja Revolution 3 EU (Wii)',0), - (2840,'sparta2pc',NULL,'Sparta 2: The Conquest of Alexander the Great (PC)',0), - (2841,'sparta2pcam',NULL,'Sparta 2: The Conquest of Alexander the Great Automatch (PC)',0), - (2842,'sparta2pcd',NULL,'Sparta 2: The Conquest of Alexander the Great Demo (PC)',0), - (2843,'superv8ncpc',NULL,'Superstars V8 Next Challenge (PC)',0), - (2844,'superv8ncpcam',NULL,'Superstars V8 Next Challenge Automatch (PC)',0), - (2845,'superv8ncpcd',NULL,'Superstars V8 Next Challenge Demo (PC)',0), - (2846,'superv8ncps3',NULL,'Superstars V8 Next Challenge (PS3)',0), - (2847,'superv8ncps3am',NULL,'Superstars V8 Next Challenge Automatch (PS3)',0), - (2848,'superv8ncps3d',NULL,'Superstars V8 Next Challenge Demo (PS3)',0), - (2849,'ikaropc',NULL,'Ikaro (PC)',0), - (2850,'ikaropcam',NULL,'Ikaro Automatch (PC)',0), - (2851,'ikaropcd',NULL,'Ikaro Demo (PC)',0), - (2852,'ufc10ps3DEV',NULL,'UFC 2010 DEV (PS3-DEV)',0), - (2853,'ufc10ps3DEVam',NULL,'UFC 2010 DEV Automatch (PS3-DEV)',0), - (2854,'ufc10ps3DEVd',NULL,'UFC 2010 DEV Demo (PS3-DEV)',0), - (2855,'ufc10x360dev',NULL,'UFC 2010 DEV (360-DEV)',0), - (2856,'ufc10x360devam',NULL,'UFC 2010 DEV Automatch (360-DEV)',0), - (2857,'ufc10x360devd',NULL,'UFC 2010 DEV Demo (360-DEV)',0), - (2858,'ragonlinenads',NULL,'Ragunaroku Online DS (NA) (DS)',0), - (2859,'hoopworldwii',NULL,'Hoopworld (Wii)',0), - (2860,'foxtrotpc',NULL,'Foxtrot (PC)',0), - (2861,'foxtrotpcam',NULL,'Foxtrot Automatch (PC)',0), - (2862,'foxtrotpcd',NULL,'Foxtrot Demo (PC)',0), - (2863,'civ5',NULL,'Civilization 5',0), - (2864,'heroeswii',NULL,'Heroes (Wii)',0), - (2865,'yugiohwc10ds',NULL,'Yu-Gi-Oh! World Championship 2010 (DS)',0), - (2866,'sbkxpc',NULL,'SBK X: Superbike World Championship (PC)',0), - (2867,'sbkxpcam',NULL,'SBK X: Superbike World Championship Automatch (PC)',0), - (2868,'sbkxpcd',NULL,'SBK X: Superbike World Championship Demo (PC)',0), - (2869,'sbkxps3',NULL,'SBK X: Superbike World Championship (PS3)',0), - (2870,'sbkxps3am',NULL,'SBK X: Superbike World Championship Automatch (PS3)',0), - (2871,'sbkxps3d',NULL,'SBK X: Superbike World Championship Demo (PS3)',0), - (2872,'famista2010ds',NULL,'Famista 2010 (DS)',0), - (2873,'bokutwinvilds',NULL,'Bokujyo Monogatari Twin Village (DS)',0), - (2874,'destruction',NULL,'Destruction 101 (Namco Bandai)',0), - (2875,'destructionam',NULL,'Destruction 101 Automatch',0), - (2876,'lumark3eyesds',NULL,'Luminous Ark 3 Eyes (DS)',0), - (2877,'othellowii',NULL,'Othello (WiiWare)',0), - (2878,'painkresurrpc',NULL,'Painkiller Resurrection (PC)',0), - (2879,'painkresurrpcam',NULL,'Painkiller Resurrection Automatch (PC)',0), - (2880,'painkresurrpcd',NULL,'Painkiller Resurrection Demo (PC)',0), - (2881,'fantcubewii',NULL,'Fantastic Cube (WiiWare)',0), - (2882,'3dpicrossUSds',NULL,'3D Picross (US) (DS)',0), - (2883,'svsr11ps3',NULL,'Smackdown vs Raw 2011 (PS3)',0), - (2884,'svsr11ps3am',NULL,'Smackdown vs Raw 2011 Automatch (PS3)',0), - (2885,'svsr11ps3d',NULL,'Smackdown vs Raw 2011 Demo (PS3)',0), - (2886,'svsr11x360',NULL,'Smackdown vs Raw 2011 (x360)',0), - (2887,'svsr11x360am',NULL,'Smackdown vs Raw 2011 Automatch (x360)',0), - (2888,'svsr11x360d',NULL,'Smackdown vs Raw 2011 Demo (x360)',0), - (2889,'bderlandruspc',NULL,'Borderlands RUS (PC)',0), - (2890,'bderlandruspcam',NULL,'Borderlands RUS Automatch (PC)',0), - (2891,'bderlandruspcd',NULL,'Borderlands RUS Demo (PC)',0), - (2892,'krabbitpcmac',NULL,'KrabbitWorld Origins (PC/Mac)',0), - (2893,'krabbitpcmacam',NULL,'KrabbitWorld Origins Automatch (PC/Mac)',0), - (2894,'krabbitpcmacd',NULL,'KrabbitWorld Origins Demo (PC/Mac)',0), - (2895,'gunnylamacwii',NULL,'GUNBLADE NY & L.A. MACHINEGUNS (Wii)',0), - (2896,'rbeaverdefwii',NULL,'Robocalypse - Beaver Defense (WiiWare)',0), - (2897,'surkatamarwii',NULL,'Surinukeru Katamari (WiiWare)',0), - (2898,'snackdsi',NULL,'Snack (DSiWare)',0), - (2899,'rpgtkooldsi',NULL,'RPG tkool DS (DSi)',0), - (2900,'mh3uswii',NULL,'Monster Hunter 3 (US/EU) (Wii)',0), - (2901,'lanoireps3',NULL,'L.A. Noire (PS3)',0), - (2902,'lanoireps3am',NULL,'L.A. Noire Automatch (PS3)',0), - (2903,'lanoireps3d',NULL,'L.A. Noire Demo (PS3)',0), - (2904,'lanoirex360',NULL,'L.A. Noire (x360)',0), - (2905,'lanoirex360am',NULL,'L.A. Noire Automatch (x360)',0), - (2906,'lanoirex360d',NULL,'L.A. Noire Demo (x360)',0), - (2907,'lanoirepc',NULL,'L.A. Noire (PC)',0), - (2908,'lanoirepcam',NULL,'L.A. Noire Automatch (PC)',0), - (2909,'lanoirepcd',NULL,'L.A. Noire Demo (PC)',0), - (2910,'digimonsleds',NULL,'Digimon Story Lost Evolution (DS)',0), - (2911,'syachi2ds',NULL,'syachi 2 (DS)',0), - (2912,'puzzleqt2ds',NULL,'Puzzle Quest 2 (DS)',0), - (2913,'phybaltraiwii',NULL,'Physiofun Balance Trainer (WiiWare)',0), - (2914,'decasport3wii',NULL,'Deca Sports 3 (Wii)',0), - (2915,'tetrisdeluxds',NULL,'Tetris Party Deluxe (DSiWare)',0), - (2916,'gsiphonefw',NULL,'GameSpy iPhone Framework',0), - (2917,'necrolcpc',NULL,'NecroVisioN: Lost Company (PC)',0), - (2918,'necrolcpcam',NULL,'NecroVisioN: Lost Company Automatch (PC)',0), - (2919,'necrolcpcd',NULL,'NecroVisioN: Lost Company Demo (PC)',0), - (2920,'startrekmac',NULL,'Star Trek: D-A-C (MAC)',0), - (2921,'startrekmacam',NULL,'Star Trek Automatch (MAC)',0), - (2922,'captsubasads',NULL,'Captain tsubasa (DS)',0), - (2923,'cb2ds',NULL,'CB2 (DS)',0), - (2924,'katekyohitds',NULL,'katekyo hitman REBORN! DS FLAME RUMBLE XX (DS)',0), - (2925,'cardiowrk2wii',NULL,'Cardio Workout 2 (Wii)',0), - (2926,'boyvgirlcwii',NULL,'Boys vs Girls Summer Camp (Wii)',0), - (2927,'keenracerswii',NULL,'Keen Racers (WiiWare)',0), - (2928,'scribnaut2pc',NULL,'Scribblenauts 2 (PC)',0), - (2929,'scribnaut2pcam',NULL,'Scribblenauts 2 Automatch (PC)',0), - (2930,'agentps3',NULL,'Agent (PS3)',0), - (2931,'agentps3am',NULL,'Agent Automatch (PS3)',0), - (2932,'girlskoreads',NULL,'Girls_Korea (DS)',0), - (2933,'jyankenparwii',NULL,'Jyanken (rock-paper-scissors) Party Paradise (WiiWare)',0), - (2934,'protocolwii',NULL,'Protocol (WiiWare)',0), - (2935,'DeathtoSpies',NULL,'Death to Spies',0), - (2936,'svsr11x360dev',NULL,'Smackdown vs Raw 2011 DEV (x360)',0), - (2937,'svsr11x360devam',NULL,'Smackdown vs Raw 2011 DEV Automatch (x360)',0), - (2938,'svsr11ps3dev',NULL,'Smackdown vs Raw 2011 DEV (PS3)',0), - (2939,'svsr11ps3devam',NULL,'Smackdown vs Raw 2011 DEV Automatch (PS3)',0), - (2940,'dynaztrialwii',NULL,'Dynamic Zan TRIAL (Wii)',0), - (2941,'molecontrolpc',NULL,'Mole Control (PC)',0), - (2942,'molecontrolpcam',NULL,'Mole Control Automatch (PC)',0), - (2943,'sakwcha2010ds',NULL,'Sakatsuku DS WorldChallenge 2010 (DS)',0), - (2944,'MenofWar',NULL,'Men of War',0), - (2945,'na2rowpc',NULL,'NAT2 Row (PC)',0), - (2946,'na2rowpcam',NULL,'NAT2 Row Automatch (PC)',0), - (2947,'na2runpc',NULL,'NAT2 Run (PC)',0), - (2948,'na2runpcam',NULL,'NAT2 Run Automatch (PC)',0), - (2949,'trackmania2ds',NULL,'Trackmania DS 2 (DS)',0), - (2950,'pangmagmichds',NULL,'Pang: Magical Michael (DS)',0), - (2951,'mysimsflyerds',NULL,'MySims Flyers (DS)',0), - (2952,'mysimsflyEUds',NULL,'MySims Flyers EU (DS)',0), - (2953,'kodawar2010ds',NULL,'Kodawari Saihai Simulation Ochanoma Pro Yakyu DS 2010 Verison (DS)',0), - (2954,'topspin4wii',NULL,'TOPSPIN 4 (Wii)',0), - (2955,'ut3onlive',NULL,'Unreal Tournament 3 ONLIVE',0), - (2956,'ut3onliveam',NULL,'Unreal Tournament 3 ONLIVE Automatch',0), - (2957,'combatzonepc',NULL,'Combat Zone - Special Forces (PC)',0), - (2958,'combatzonepcam',NULL,'Combat Zone - Special Forces Automatch (PC)',0), - (2959,'combatzonepcd',NULL,'Combat Zone - Special Forces Demo (PC)',0), - (2960,'sinpun2NAwii',NULL,'Sin & Punishment 2 NA (Wii)',0), - (2962,'capricornam',NULL,'Crysis 2 Automatch (PC)',0), - (2963,'crysis2pcd',NULL,'Crysis 2 Demo (PC)',0), - (2964,'crysis2ps3',NULL,'Crysis 2 (PS3)',0), - (2965,'crysis2ps3am',NULL,'Crysis 2 Automatch (PS3)',0), - (2966,'crysis2ps3d',NULL,'Crysis 2 Demo (PS3)',0), - (2967,'crysis2x360',NULL,'Crysis 2 (Xbox 360)',0), - (2968,'crysis2x360am',NULL,'Crysis 2 Automatch (Xbox 360)',0), - (2969,'crysis2x360d',NULL,'Crysis 2 Demo (Xbox 360)',0), - (2970,'ZumaDeluxe',NULL,'Zuma Deluxe',0), - (2971,'cellfacttwpc',NULL,'Cell Factor:TW (PC)',0), - (2972,'cellfacttwpcam',NULL,'Cell Factor:TW Automatch (PC)',0), - (2973,'firearmsevopc',NULL,'Firearms Evolution (PC)',0), - (2974,'firearmsevopcam',NULL,'Firearms Evolution Automatch (PC)',0), - (2975,'winel10jpnwii',NULL,'Winning Eleven PLAY MAKER 2010 Japan Edition (Wii)',0), - (2976,'winel10jpnwiiam',NULL,'Winning Eleven PLAY MAKER 2010 Japan Edition Automatch (Wii)',0), - (2977,'bldragonNAds',NULL,'Blue Dragon - Awakened Shadow',0), - (2978,'bldragonNAdsam',NULL,'Blue Dragon - Awakened Shadow Automatch',0), - (2979,'sonic2010wii',NULL,'SONIC 2010 (Wii)',0), - (2980,'sonic2010wiiam',NULL,'SONIC 2010 Automatch (Wii)',0), - (2981,'harmoon2kords',NULL,'Harvest Moon 2 Korea (DS)',0), - (2982,'harmoon2kordsam',NULL,'Harvest Moon 2 Korea Automatch (DS)',0), - (2983,'jbondmv2ds',NULL,'James Bond Non Movie 2 (2010) (DS)',0), - (2984,'jbondmv2dsam',NULL,'James Bond Non Movie 2 Automatch (2010) (DS)',0), - (2985,'casinotourwii',NULL,'Casino Tournament (Wii)',0), - (2986,'casinotourwiiam',NULL,'Casino Tournament Automatch (Wii)',0), - (3300,'capricorn','8TTq4M','Crysis 2 (PC)',0); -UNLOCK TABLES; - - -LOCK TABLES `grouplist` WRITE; -INSERT INTO `grouplist` (`groupid`, `gameid`, `roomname`) VALUES - (1,5,'daikatana test group'), - (2,1,'Newbies'), - (3,1,'Experts'), - (4,1,'Farm Animals'), - (5,256,'Skirmish'), - (6,256,'Domination'), - (7,192,'Test VP3 Tourney'), - (9,192,'this'), - (18,192,'b'), - (19,192,'b'), - (20,285,'Rookies'), - (21,285,'Amateurs'), - (22,285,'Pros'), - (24,192,'b'), - (25,256,'Slaughter'), - (26,256,'Soul Harvest'), - (27,256,'Allied'), - (30,192,'LumberJack VP3 Test Tourney'), - (44,192,'test6ladder'), - (57,192,'asdf'), - (63,192,'BillsTest2'), - (64,192,'BillsTest2'), - (101,192,'this'), - (102,308,'Beginner'), - (103,308,'Intermediate'), - (104,308,'Advanced'), - (105,192,'this'), - (106,192,'hello'), - (107,192,'mytest'), - (108,192,'arts ladder'), - (109,192,'Seans Ladder'), - (110,192,'seans test ladder'), - (111,192,'Seans Test Ladder'), - (112,192,'9-Ball Challenge'), - (113,192,'TestOct23'), - (114,192,'abcd'), - (115,192,'Lumberjack VP3 Test Tourny #2'), - (116,192,'9-Ball Heaven'), - (117,192,'QA Test Ladder'), - (118,192,'GSI Test - do not join'), - (119,192,'reload test'), - (122,192,'Tonys 9-Ball tourney'), - (123,192,'Tonys 9-Ball tourney 2'), - (124,192,'Tonys Moved Database Test'), - (125,192,'outputdir test tourney'), - (127,192,'b'), - (141,192,'aphexweb1 test'), - (143,192,'registration test'), - (144,192,'w'), - (147,192,'arts ladder test'), - (148,192,'gsi test ladder nov 1'), - (149,192,'test'), - (150,192,'arts ladder'), - (151,192,'gsi test ladder'), - (152,192,'tonys ladder'), - (153,192,'9-Ball Ladder: Public Test'), - (154,192,'Interplay QA test'), - (155,192,'Interplay QA test'), - (156,192,'Qa Test 2'), - (157,192,'QA DEDICATED TEST'), - (158,192,'TEN BALL - QA TEST'), - (159,192,'BILLIARDS'), - (160,192,'IP Rotation'), - (161,192,'10 BALL - QA TEST'), - (162,192,'Savy & Sean'), - (163,192,'Willow & Erik'), - (164,192,'Savy'), - (165,192,'6 Ball game'), - (166,192,'VP3 Private Patch Testing'), - (167,192,'Patch (#2) Final Testing'), - (168,337,'Main Lobby'), - (169,337,'{01}Cadet'), - (170,337,'{02}Captain'), - (171,337,'{03}Admiral'), - (172,412,'{01}General Chat'), - (173,412,'{04}Teen Chat'), - (176,412,'{02}Family And Friends'), - (177,412,'{03}College Chat'), - (189,15,'{01}Half-Life Room 1'), - (190,15,'{02}Half-Life Room 2'), - (191,15,'{01}Counter-Strike: Special Air Service'), - (192,15,'{01}Counter-Strike: GSG-9'), - (193,15,'{01}Counter-Strike: Counter-Terrorist Force'), - (194,15,'{01}Counter-Strike: Seal Team 6'), - (195,15,'{11}Firearms Room'), - (196,15,'{13}TeamFortress Classic Room'), - (197,15,'{10}Day of Defeat Room'), - (198,15,'{12}Front Line Force Room'), - (199,412,'{01}Action Games'), - (200,412,'{02}Role Playing Games'), - (201,412,'{03}Strategy Games'), - (202,412,'{04}Sports Games'), - (203,412,'{05}Simulation Games'), - (204,412,'{06}Tactical Games'), - (206,15,'{03}Help With Half-Life'), - (207,323,'{01}Counter-Terrorist Force'), - (208,323,'{01}Seal Team Six'), - (209,323,'{02}Help with Counter-Strike'), - (210,22,'{02}Quake 3 Veterans Room'), - (211,22,'{01}Quake 3 Main Room'), - (212,22,'{05}Rocket Arena 3 Room'), - (213,22,'{02}Freeze Tag'), - (214,22,'{04}Quake 3 Fortress Room'), - (215,22,'{06}Threewave CTF'), - (216,22,'{07}Urban Terror Beta 2 Room'), - (217,22,'{08}Weapons Factory Arena Room'), - (218,22,'{01}Excessive Room'), - (219,401,'{03}Spades Advanced Lobby'), - (220,401,'{01}Spades Newbie Lobby'), - (221,401,'{04}Spades Ranked Lobby'), - (222,401,'{02}Spades Social Lobby'), - (223,403,'{02}Backgammon Ranked Lobby'), - (224,403,'{01}Backgammon General Lobby'), - (225,400,'Poker Advanced Lobby'), - (226,400,'Poker Newbies Lobby'), - (227,400,'Poker Ranked Lobby'), - (228,400,'Poker Social Lobby'), - (229,402,'{01}Hearts General Lobby'), - (230,402,'{02}Hearts Ranked Lobby'), - (231,22,'{06}Help with Quake 3'), - (232,22,'{05}Team Deathmatch'), - (233,15,'{01}Counter-Strike: For Great Justice!'), - (234,15,'{01}Counter-Strike: Clan Battle Room'), - (236,15,'{13}Action Half-Life Room'), - (241,15,'{03}Opposing Force Room'), - (242,15,'{04}PlanetHalfLife Arcade Event Lobby'), - (243,401,'{05}Spades Tournament Lobby'), - (244,402,'{03}Hearts Tournament Lobby'), - (245,403,'{03}Backgammon Tournament Lobby'), - (246,192,'Squish Test ladder'), - (247,292,'Main'), - (248,292,'Tournaments'), - (250,361,'{01}Geral'), - (251,361,'{02}Jogos PC'), - (252,15,'{14}Deathmatch Classic'), - (259,414,'{01}Everon'), - (260,414,'{01}Malden'), - (261,414,'{02}Dedicated Servers'), - (262,414,'{03}Co-op'), - (263,414,'{04}Capture the Flag'), - (264,414,'{05}Test Zone'), - (265,361,'{03}Jogos Consolas'), - (266,361,'{04}Hardware'), - (267,361,'{05}Torneios e Eventos'), - (269,361,'{06}Comunidade'), - (270,483,'THPS3 Internet'), - (271,400,'Poker Tournament Lobby'), - (272,22,'{03}Orange Smoothie'), - (273,504,'Main'), - (274,328,'{01}Action'), - (275,328,'{02}Roleplaying'), - (276,328,'{03}Team (N vs. N)'), - (277,328,'{04}Social'), - (278,328,'{05}Persistent World Action'), - (279,328,'{06}Alternative'), - (280,292,'Korean'), - (281,509,'The Downs'), - (288,509,'Forest Heart'), - (295,509,'Tharsis'), - (299,523,'Main Lobby'), - (300,523,'{01}Cadet'), - (301,523,'{02}Captain'), - (302,523,'{03}Admiral'), - (303,22,'{03}Capture the Flag'), - (304,22,'{04}Deathmatch'), - (305,292,'Français'), - (306,292,'Deutsch'), - (307,292,'KIS'), - (308,292,'KAG'), - (310,362,'{01}Juegos'), - (311,362,'{02}Adolescentes'), - (312,362,'{03}Encuentros'), - (313,362,'{04}Maduritos'), - (314,362,'{05}Sexo'), - (315,564,'Tony Hawk 2x'), - (316,564,'Halo'), - (317,564,'NASCAR Heat 2002'), - (318,568,'{01}Eastern Front'), - (319,568,'{01}Western Front'), - (320,568,'{01}North African Campaign'), - (321,568,'{01}Pacific Campaign'), - (322,568,'{01}Guadalcanal Campaign'), - (323,568,'{01}Soviet Winter Offensive'), - (324,363,'{01}Juegos'), - (325,363,'{02}Adolescentes'), - (326,363,'{03}Encuentros'), - (327,363,'{04}Maduritos'), - (328,363,'{05}Romance'), - (329,492,'{01}Eastern Front'), - (330,492,'{01}Western Front'), - (331,492,'{02}Round-based Match'), - (332,492,'{04}Objective-based Match'), - (333,492,'{01}Deathmatch'), - (334,492,'{03}Team Match'), - (335,492,'{01}North Africa'), - (336,492,'{01}Siegfried Line'), - (337,492,'{03}Team Match'), - (338,492,'{04}Objective-based Match'), - (339,590,'(01)Power Plant'), - (340,590,'(01)Tiberium Refinery'), - (341,590,'(01)Weapons Factory'), - (342,590,'(01)Infantry Barracks'), - (343,590,'(01)GDI Guard Tower'), - (344,590,'(01)Construction Yard'), - (345,590,'(01)Hand of Nod'), - (346,590,'(01)Nod Airstrip'), - (347,15,'{15}Desert Crisis'), - (352,577,'(01)Power Plant'), - (353,577,'(01)Tiberium Refinery'), - (354,577,'(01)Weapons Factory'), - (355,577,'(01)Infantry Barracks'), - (356,577,'(01)GDI Guard Tower'), - (357,577,'(01)Construction Yard'), - (358,577,'(01)Hand of Nod'), - (359,577,'(01)Nod Airstrip'), - (361,564,'Tony Hawk 3'), - (362,564,'MotoGP'), - (363,328,'{07}Story'), - (364,328,'{08}Story Lite'), - (365,328,'{09}Melee (1 vs. N)'), - (366,328,'{10}Arena (1 vs. N)'), - (367,328,'{11}Persistent World Story'), - (368,328,'{12}Solo'), - (369,412,'{05}Romance'), - (370,328,'{13}Tech Support'), - (371,15,'{16}Ricochet'), - (372,564,'Australia'), - (373,564,'Europe'), - (374,564,'United Kingdom'), - (375,610,'{01}Infantry'), - (376,610,'{01}Combat Engineering'), - (377,610,'{01}Combat Operations'), - (378,610,'{01}Special Forces'), - (379,610,'{01}Armor'), - (380,610,'{01}Aviation Operations'), - (381,610,'{05}MOUT McKenna'), - (382,610,'{05}MOUT McKenna'), - (383,610,'{01}Bridge Crossing'), - (384,610,'{03}Headquarters Raid'), - (385,610,'{04}Insurgent Camp'), - (386,610,'{06}Pipeline'), - (387,610,'{02}Collapsed Tunnel'), - (388,610,'{01}Bridge Crossing'), - (389,675,'GroupRoom1'), - (390,675,'GroupRoom2'), - (391,675,'GroupRoom3'), - (392,675,'QuickMatch'), - (393,564,'NFL Fever 2003'), - (394,684,'Los Angeles (Newbies)'), - (395,684,'Los Angeles (Experts)'), - (396,684,'Tokyo (Newbies)'), - (397,684,'Tokyo (Experts)'), - (398,684,'Paris (Newbies)'), - (399,684,'Paris (Experts)'), - (400,684,'Battle (Newbies)'), - (401,684,'Battle (Experts)'), - (402,671,'(01)Allies Lobby'), - (403,671,'(01)Allies Lobby'), - (404,671,'(01)Axis Lobby'), - (405,671,'(01)Axis Lobby'), - (409,617,'Rookie'), - (410,617,'Intermediate'), - (411,617,'Expert'), - (412,541,'{01}Axis Lobby'), - (413,541,'{01}Allies Lobby'), - (414,541,'{03}Pacific Theater'), - (415,541,'{02}European Theater'), - (417,541,'{04}Russian Theater'), - (418,541,'Capture the Flag'), - (419,541,'Conquest'), - (420,541,'Co-Op'), - (421,541,'Team Deathmatch'), - (422,541,'{01}African Theater'), - (423,636,'Main Lobby'), - (424,636,'ATI Tournament Lobby'), - (441,564,'TimeSplitters 2'), - (442,564,'Tony Hawk 4'), - (443,15,'{17}Natural Selection'), - (444,716,'GroupRoom1'), - (445,716,'GroupRoom2'), - (446,716,'GroupRoom3'), - (447,564,'Deathrow'), - (448,712,'{01}General Lobby'), - (449,712,'{01}General Lobby'), - (450,712,'Free-For-All Servers'), - (451,712,'Team Deathmatch'), - (452,712,'Round-based Match'), - (453,712,'Objective Match'), - (454,712,'Tug of War'), - (455,641,'{01}General Lobby'), - (456,641,'{01}General Lobby'), - (457,641,'Free-For-All Servers'), - (458,641,'Team Deathmatch'), - (459,641,'Round-based Match'), - (460,641,'Objective Match'), - (461,641,'Tug of War'), - (462,564,'MechAssault'), - (463,564,'Unreal Championship'), - (464,564,'Ghost Recon'), - (471,617,'Rated'), - (472,617,'Unrated'), - (473,617,'Unrated Expert'), - (474,617,'Unrated Intermediate'), - (475,617,'Unrated Beginner'), - (476,730,'Beginner'), - (477,730,'Intermediate'), - (478,730,'Advanced'), - (479,721,'Rated 0'), - (480,721,'Rated 1'), - (481,721,'Rated 2'), - (483,721,'Rated 3'), - (485,557,'Ryan\'s Room'), - (486,557,'Donnie\'s Room'), - (487,541,'Desert Combat'), - (488,713,'{01}Allies Lobby'), - (489,713,'{01}Axis Lobby'), - (490,713,'{01}African Theater'), - (491,713,'{02}European Theater'), - (492,713,'{03}Italian Theater'), - (493,713,'{04}Pacific Theater'), - (494,713,'{05}Russian Theater'), - (496,675,'GroupRoom4'), - (497,675,'GroupRoom5'), - (498,675,'GroupRoom6'), - (499,675,'GroupRoom7'), - (500,675,'GroupRoom8'), - (501,675,'GroupRoom9'), - (502,675,'GroupRoom10'), - (503,675,'GroupRoom11'), - (504,675,'GroupRoom12'), - (506,557,'Kyle\'s Room'), - (507,557,'Bobby\'s Room'), - (508,557,'Nick\'s Room'), - (509,557,'Linda\'s Room'), - (510,557,'Melanie\'s Room'), - (511,557,'Cannonball\'s Room'), - (512,557,'Paulie\'s Room'), - (513,557,'Cuban Joe\'s Room'), - (514,541,'Galactic Conquest'), - (515,770,'Ryan\'s Room'), - (516,770,'Bobby\'s Room'), - (517,722,'Anything Goes'), - (519,722,'Team17'), - (523,722,'Professional League'), - (524,722,'Elite League'), - (525,721,'Rated 4'), - (527,721,'Rated 6'), - (528,721,'Rated 7'), - (529,721,'Rated 8'), - (530,721,'Rated 9'), - (531,721,'Unrated 0'), - (532,721,'Unrated 1'), - (533,721,'Unrated 2'), - (534,721,'Unrated 3'), - (535,721,'Unrated 4'), - (536,721,'Rated 5'), - (537,721,'Unrated 5'), - (538,721,'Unrated 6'), - (539,721,'Unrated 7'), - (540,721,'Unrated 8'), - (541,721,'Unrated 9'), - (542,765,'tier1'), - (543,765,'tier2'), - (544,765,'tier3'), - (545,765,'tier4'), - (546,765,'tier5'), - (547,776,'West'), - (548,776,'East'), - (549,776,'Europe'), - (550,776,'Asia'), - (551,776,'Beginner'), - (552,776,'Expert'), - (553,15,'{18}Vampire Slayer'), - (554,772,'Action Room'), - (555,772,'Asian Room'), - (556,772,'Deathmatch Room'), - (557,797,'{01}Main Lobby'), - (558,797,'{03}Tour Lobby'), - (559,797,'{02}Ladder Lobby'), - (560,564,'Wolfenstein Tides of War'), - (561,564,'Brute Force'), - (562,541,'Eve of Destruction'), - (563,564,'Midnight Club 2'), - (564,564,'Moto GP 2'), - (565,564,'Inside Pitch 2003'), - (566,564,'Star Wars: The Clone Wars'), - (567,564,'Midtown Madness 3'), - (568,541,'ActionBattlefield'), - (569,792,'Conquest Scenarios'), - (570,792,'Battle Scenarios'), - (571,823,'GroupRoom1'), - (572,824,'Unrated 0'), - (573,824,'Unrated 1'), - (575,824,'Unrated 2'), - (576,824,'Unrated 3'), - (577,824,'Unrated 4'), - (578,824,'Unrated 5'), - (579,824,'Unrated 6'), - (580,824,'Unrated 7'), - (581,824,'Unrated 8'), - (582,824,'Unrated 9'), - (586,823,'GroupRoom2'), - (587,823,'GroupRoom3'), - (588,823,'GroupRoom4'), - (589,823,'GroupRoom5'), - (590,823,'GroupRoom6'), - (591,823,'GroupRoom7'), - (592,823,'GroupRoom8'), - (593,823,'GroupRoom9'), - (594,823,'GroupRoom10'), - (595,823,'GroupRoom11'), - (596,823,'GroupRoom12'), - (597,823,'QuickMatch'), - (598,823,'GroupRoom13'), - (599,840,'Advanced'), - (600,840,'Intermediate'), - (601,840,'Beginner'), - (602,823,'GroupRoom14'), - (606,832,'Social Room'), - (607,832,'Beginner Room'), - (608,832,'Intermediate Room'), - (609,832,'Advanced Room'), - (610,851,'West'), - (611,851,'East'), - (612,851,'Europe'), - (613,851,'Asia'), - (614,851,'Beginner'), - (615,851,'Expert'), - (616,22,'{09}Urban Terror Beta 3 Room'), - (619,15,'{19}The Specialists'), - (620,15,'{20}MonkeyStrike'), - (621,15,'{21}Earth Special Forces'), - (622,722,'Amateur League'), - (623,722,'Shopping'), - (624,842,'Beginner'), - (625,842,'Casual'), - (626,842,'Expert'), - (627,842,'Elite'), - (628,832,'Practice Room'), - (631,871,'Newbies'), - (632,871,'Pros'), - (633,871,'Moto 1'), - (634,871,'Moto 2'), - (635,845,'Zaramoth'), - (636,845,'Zaramoth'), - (637,845,'Azunai'), - (638,845,'Azunai'), - (639,845,'Xeria'), - (640,845,'Xeria'), - (641,845,'Isteru'), - (642,772,'Empire Builder Room'), - (643,772,'European Room'), - (644,772,'Free For All Room'), - (645,772,'German Room'), - (646,772,'Ladder Room'), - (647,772,'No Rush Room'), - (648,772,'Tournament Room'), - (649,843,'European Public League'), - (650,843,'Massive Test Leauge'), - (651,843,'North American Public League'), - (652,843,'Asian Public League'), - (660,870,'LobbyRoom1'), - (661,870,'LobbyRoom2'), - (662,870,'QuickMatch'), - (664,891,'Group Room 2'), - (665,564,'Amped 2'), - (666,564,'Crimson Skies'), - (667,564,'NFL Fever 2004'), - (668,564,'Soldier of Fortune II'), - (669,564,'Ghost Recon: Island Thunder'), - (670,564,'Rainbow Six 3'), - (671,564,'Tony Hawk Underground'), - (672,564,'Top Spin'), - (673,791,'Conquest Scenarios'), - (674,791,'Battle Scenarios'), - (675,15,'{23}Counter-Strike: Clan Battle Room'), - (676,15,'{23}Counter-Strike: For Great Justice!'), - (677,15,'{23}Counter-Strike: GSG-9'), - (678,15,'{23}Counter-Strike: Counter-Terrorist Force'), - (679,15,'{23}Counter-Strike: Seal Team 6'), - (680,15,'{23}Counter-Strike: Special Air Service'), - (684,793,'{01}Main Lobby'), - (685,793,'{02}Halo Tournament'), - (696,886,'Main'), - (697,886,'Tournament'), - (698,868,'Main'), - (699,868,'Tournament'), - (715,852,'Search and Destroy'), - (716,852,'Behind Enemy Lines'), - (717,852,'Retrieval'), - (718,852,'Deathmatch'), - (719,924,'Rated 0'), - (720,924,'Rated 1'), - (721,924,'Rated 2'), - (722,924,'Rated 3'), - (723,924,'Rated 4'), - (724,924,'Rated 5'), - (725,924,'Rated 6'), - (726,924,'Rated 7'), - (727,924,'Rated 8'), - (728,924,'Rated 9'), - (729,924,'Unrated 0'), - (730,924,'Unrated 1'), - (731,924,'Unrated 2'), - (732,924,'Unrated 3'), - (733,924,'Unrated 4'), - (734,924,'Unrated 5'), - (735,924,'Unrated 6'), - (736,924,'Unrated 7'), - (737,924,'Unrated 8'), - (738,924,'Unrated 9'), - (739,806,'Headquarters'), - (740,806,'Briefing Room'), - (741,806,'The Bunker'), - (742,806,'Mess Hall'), - (743,946,'Room 1'), - (744,946,'Room 2'), - (745,922,'Competitive'), - (746,922,'Friendly'), - (747,918,'US - Eastern'), - (748,918,'US - Central'), - (749,918,'US - Western'), - (750,918,'Europe - English'), - (751,918,'Europe - French'), - (752,918,'Europe - Italian'), - (753,918,'Europe - German'), - (754,918,'Europe - Spanish'), - (755,976,'Beginners'), - (756,976,'Intermediate'), - (757,908,'Beginners'), - (758,908,'Experts'), - (759,908,'Europe'), - (760,908,'America'), - (761,908,'Asia'), - (766,960,'Casual Play'), - (767,960,'Rated Play'), - (768,960,'Can of Spam'), - (769,1008,'Public Demo League'), - (770,1008,'Public Demo League'), - (771,1008,'Public Demo League'), - (776,1004,'Amateur'), - (786,1004,'Rookie'), - (796,1004,'Pro'), - (812,1004,'Legend'), - (816,946,'Room 3'), - (817,1030,'Beginner'), - (818,1030,'Intermediate'), - (819,1030,'Expert'), - (820,878,'News and Events#1'), - (821,878,'News and Events#2'), - (822,878,'News and Events#3'), - (823,878,'News and Events#4'), - (824,878,'News and Events#5'), - (830,878,'Medal of Honor Chat#1'), - (831,878,'Medal of Honor Chat#2'), - (832,878,'Medal of Honor Chat#3'), - (833,878,'Medal of Honor Chat#4'), - (834,878,'Medal of Honor Chat#5'), - (840,878,'EA Chat#1'), - (841,878,'EA Chat#2'), - (850,878,'Tech Support & Help#1'), - (851,878,'Tech Support & Help#2'), - (860,878,'Clan Arena#1'), - (861,878,'Clan Arena#2'), - (862,878,'Clan Arena#3'), - (863,878,'Clan Arena#4'), - (864,878,'Clan Arena#5'), - (865,878,'Clan Arena#6'), - (866,878,'Clan Arena#7'), - (867,878,'Clan Arena#8'), - (868,878,'Clan Arena#9'), - (869,878,'Clan Arena#10'), - (870,878,'Boot Camp Training#1'), - (871,878,'Boot Camp Training#2'), - (872,878,'Boot Camp Training#3'), - (873,878,'Boot Camp Training#4'), - (874,878,'Boot Camp Training#5'), - (880,878,'Officers Club#1'), - (881,878,'Officers Club#2'), - (882,878,'Officers Club#3'), - (883,878,'Officers Club#4'), - (886,878,'Officers Club#5'), - (890,878,'The War Room#1'), - (891,878,'The War Room#2'), - (892,878,'The War Room#3'), - (893,878,'The War Room#4'), - (894,878,'The War Room#5'), - (900,878,'Off Topic Discussion#1'), - (901,878,'Off Topic Discussion#2'), - (902,878,'Off Topic Discussion#3'), - (903,878,'Off Topic Discussion#4'), - (904,878,'Off Topic Discussion#5'), - (916,1043,'Amateur'), - (925,1043,'Rookie'), - (935,1043,'Pro'), - (951,1043,'Legend'), - (955,1042,'Conquest'), - (956,1042,'King of the Hill'), - (957,1042,'Territory Control'), - (960,843,'Reliance WebWorld Tournament'), - (963,946,'Room 4'), - (964,946,'Room 5'), - (965,946,'Room 6'), - (966,946,'Room 7'), - (967,946,'Room 8'), - (968,946,'Room 9'), - (969,946,'Room 10'), - (970,1064,'Main'), - (971,1064,'Tournament'), - (972,955,'Airliners'), - (973,955,'Adventures'), - (974,955,'Bush Flying'), - (975,955,'Competitions'), - (976,955,'Flight Training'), - (977,955,'Fly-Ins'), - (978,955,'Free Flight'), - (979,955,'Helicopter Ops'), - (983,827,'AoX chat'), - (984,827,'AoX AUS'), - (985,827,'AoX CAN'), - (986,827,'AoX CHN'), - (987,827,'AoX CZE'), - (988,827,'AoX DEU'), - (989,827,'AoX ESP'), - (990,827,'AoX FRA'), - (991,827,'AoX GBR'), - (992,827,'AoX HUN'), - (993,827,'AoX ITA'), - (994,827,'AoX KOR'), - (995,827,'AoX POL'), - (996,827,'AoX RUS'), - (997,827,'AoX USA'), - (998,827,'AoX AFRICA'), - (999,827,'AoX AMERICA'), - (1000,827,'AoX ASIA'), - (1001,827,'AoX EUROPE'), - (1002,870,'LobbyRoom3'), - (1003,870,'LobbyRoom4'), - (1004,870,'LobbyRoom5'), - (1005,870,'LobbyRoom6'), - (1006,870,'LobbyRoom7'), - (1007,870,'LobbyRoom8'), - (1008,870,'LobbyRoom9'), - (1009,870,'ChatRoom1'), - (1010,870,'ChatRoom2'), - (1011,870,'ChatRoom3'), - (1012,870,'ChatRoom4'), - (1013,870,'ChatRoom5'), - (1014,870,'ChatRoom6'), - (1015,870,'ChatRoom7'), - (1016,870,'ChatRoom8'), - (1017,870,'ChatRoom9'), - (1018,870,'ChatRoom10'), - (1019,1070,'Amateur 01'), - (1020,1070,'Amateur 02'), - (1021,1070,'Amateur 03'), - (1022,1070,'Amateur 04'), - (1023,1070,'Amateur 05'), - (1029,1070,'Rookie 01'), - (1030,1070,'Rookie 02'), - (1031,1070,'Rookie 03'), - (1032,1070,'Rookie 04'), - (1033,1070,'Rookie 05'), - (1034,1070,'Pro 01'), - (1035,1070,'Pro 02'), - (1036,1070,'Pro 03'), - (1037,1070,'Pro 04'), - (1038,1070,'Pro 05'), - (1049,1070,'Legend 01'), - (1050,1070,'Legend 02'), - (1051,1070,'Legend 03'), - (1052,1070,'Legend 04'), - (1053,1070,'Legend 05'), - (1057,1071,'Amateur 01'), - (1058,1071,'Amateur 02'), - (1059,1071,'Amateur 03'), - (1060,1071,'Amateur 04'), - (1061,1071,'Amateur 05'), - (1062,1071,'Amateur 06'), - (1063,1071,'Amateur 07'), - (1064,1071,'Amateur 08'), - (1065,1071,'Amateur 09'), - (1066,1071,'Amateur 10'), - (1067,1071,'Rookie 01'), - (1068,1071,'Rookie 02'), - (1069,1071,'Rookie 03'), - (1070,1071,'Rookie 04'), - (1071,1071,'Rookie 05'), - (1072,1071,'Rookie 06'), - (1073,1071,'Rookie 07'), - (1074,1071,'Rookie 08'), - (1075,1071,'Rookie 09'), - (1076,1071,'Rookie 10'), - (1077,1071,'Pro 01'), - (1078,1071,'Pro 02'), - (1079,1071,'Pro 03'), - (1080,1071,'Pro 04'), - (1081,1071,'Pro 05'), - (1082,1071,'Pro 06'), - (1083,1071,'Pro 07'), - (1084,1071,'Pro 08'), - (1085,1071,'Pro 09'), - (1086,1071,'Pro 10'), - (1087,1071,'Pro 11'), - (1088,1071,'Pro 12'), - (1089,1071,'Pro 13'), - (1090,1071,'Pro 14'), - (1091,1071,'Pro 15'), - (1092,1071,'Pro 16'), - (1093,1071,'Legend 01'), - (1094,1071,'Legend 02'), - (1095,1079,'Amateur 01'), - (1096,1079,'Amateur 02'), - (1097,1079,'Amateur 03'), - (1098,1079,'Amateur 04'), - (1099,1079,'Amateur 05'), - (1100,1079,'Amateur 06'), - (1105,1079,'Rookie 01'), - (1106,1079,'Rookie 02'), - (1107,1079,'Rookie 03'), - (1108,1079,'Rookie 04'), - (1109,1079,'Rookie 05'), - (1110,1079,'Rookie 06'), - (1115,1079,'Pro 01'), - (1116,1079,'Pro 02'), - (1117,1079,'Pro 03'), - (1118,1079,'Pro 04'), - (1119,1079,'Pro 05'), - (1120,1079,'Pro 06'), - (1131,1079,'Legend 01'), - (1132,1079,'Legend 02'), - (1133,1079,'Legend 03'), - (1134,1079,'Legend 04'), - (1135,922,'Chat Lobby'), - (1136,1080,'Main'), - (1137,1080,'Tournament'), - (1151,1088,'Welcome'), - (1152,1094,'AoX chat'), - (1153,1094,'AoX AUS'), - (1154,1094,'AoX CAN'), - (1155,1094,'AoX CHN'), - (1156,1094,'AoX CZE'), - (1157,1094,'AoX DEU'), - (1158,1094,'AoX ESP'), - (1159,1094,'AoX FRA'), - (1160,1094,'AoX GBR'), - (1161,1094,'AoX HUN'), - (1162,1094,'AoX ITA'), - (1163,1094,'AoX KOR'), - (1164,1094,'AoX POL'), - (1165,1094,'AoX RUS'), - (1166,1094,'AoX USA'), - (1167,1094,'AoX AFRICA'), - (1168,1094,'AoX AMERICA'), - (1169,1094,'AoX ASIA'), - (1170,1094,'AoX EUROPE'), - (1171,1071,'Legend 03'), - (1172,1071,'Legend 04'), - (1173,976,'Advanced'), - (1174,1092,'Beginner'), - (1175,1092,'Intermediate'), - (1176,1092,'Advanced'), - (1177,845,'Isteru'), - (1178,845,'Gregor'), - (1179,845,'Gregor'), - (1180,845,'Rahvan'), - (1181,845,'Rahvan'), - (1182,845,'Feandan'), - (1183,845,'Feandan'), - (1184,845,'Dalziel'), - (1185,845,'Dalziel'), - (1186,845,'Istaura'), - (1187,845,'Istaura'), - (1188,845,'Agarrus'), - (1189,845,'Agarrus'), - (1190,845,'Lorethal'), - (1191,845,'Lorethal'), - (1192,845,'Vistira'), - (1193,845,'Vistira'), - (1194,845,'Keh'), - (1195,845,'Keh'), - (1196,845,'Soranith'), - (1197,845,'Soranith'), - (1198,845,'Rubicon'), - (1199,845,'Rubicon'), - (1200,845,'Thena'), - (1201,845,'Thena'), - (1202,845,'Artech'), - (1203,845,'Artech'), - (1204,845,'Ethaniel'), - (1205,845,'Ethaniel'), - (1206,845,'Kale'), - (1207,845,'Kale'), - (1208,845,'Calix'), - (1209,845,'Calix'), - (1210,845,'Culahn'), - (1211,845,'Culahn'), - (1212,845,'Rowain'), - (1213,845,'Rowain'), - (1214,845,'Kelis Carthok'), - (1215,845,'Kelis Carthok'), - (1223,1035,'Main'), - (1224,1035,'Asia'), - (1225,1035,'Europe'), - (1226,1035,'US'), - (1227,1035,'Main'), - (1228,1035,'Asia'), - (1229,1035,'Europe'), - (1230,1035,'US'), - (1231,1035,'Main'), - (1232,1035,'Asia'), - (1233,1035,'Europe'), - (1234,1035,'US'), - (1235,1135,'Novices'), - (1236,1135,'Veterans'), - (1237,1135,'English'), - (1238,1135,'French'), - (1239,1135,'German'), - (1240,1135,'Italian'), - (1241,1135,'Spanish'), - (1250,952,'US - Eastern'), - (1251,952,'US - Central'), - (1253,952,'US - Western'), - (1254,952,'Europe - English'), - (1255,952,'Europe - French'), - (1256,952,'Europe - Italian'), - (1257,952,'Europe - German'), - (1258,952,'Europe - Spanish'), - (1259,1042,'Conquest 2'), - (1260,1042,'Conquest 3'), - (1261,1156,'Main'), - (1262,1156,'Main'), - (1263,1156,'Main'), - (1264,1042,'Territory Control 2'), - (1265,1042,'Territory Control 3'), - (1266,1042,'King of the Hill 2'), - (1267,1042,'King of the Hill 3'), - (1269,1042,'Conquest'), - (1270,1042,'King of the Hill'), - (1271,1042,'Territory Control'), - (1272,1042,'Conquest 2'), - (1273,1042,'Conquest 3'), - (1274,1042,'Territory Control 3'), - (1275,1042,'King of the Hill 2'), - (1276,1042,'King of the Hill 3'), - (1277,1042,'Territory Control 2'), - (1278,1159,'West'), - (1279,1159,'East'), - (1282,1173,'General'), - (1283,1173,'OnlineBattle'), - (1284,1181,'General'), - (1285,1181,'OnlineBattle'), - (1287,1191,'Beginner'), - (1288,1191,'Intermediate'), - (1289,1191,'Advanced'), - (1290,948,'North America'), - (1291,948,'Europe'), - (1292,948,'Asia Pacific'), - (1301,948,'Unpatched'), - (1302,1195,'Beginner'), - (1303,1195,'Intermediate'), - (1304,1195,'Advanced'), - (1330,1212,'West'), - (1331,1212,'East'), - (1334,1190,'Generak'), - (1335,1190,'OnlineBattle'), - (1336,1213,'West'), - (1337,1213,'East'), - (1354,1207,'Room 1'), - (1355,1207,'Room 2'), - (1356,1207,'Room 3'), - (1357,1207,'Room 4'), - (1358,1207,'Room 5'), - (1359,1207,'Room 6'), - (1360,1207,'Room 7'), - (1361,1207,'Room 8'), - (1362,1207,'Room 9'), - (1363,1207,'Room 10'), - (1369,1,'TestGroupRoom'), - (1370,1224,'North America'), - (1371,1224,'Europe'), - (1372,1224,'Asia Pacific'), - (1381,1231,'English'), - (1382,1231,'French'), - (1383,1231,'German'), - (1384,1231,'Italian'), - (1385,1231,'Spanish'), - (1386,1231,'Eastern US'), - (1387,1231,'Central US'), - (1388,1231,'Western US'), - (1390,1196,'Exhibition Single 00'), - (1391,1196,'Exhibition Single 01'), - (1392,1196,'Exhibition Single 02'), - (1393,1196,'Exhibition Single 03'), - (1394,1196,'Exhibition Single 04'), - (1395,1196,'Exhibition Single 05'), - (1396,1196,'Exhibition Single 06'), - (1397,1196,'Exhibition Single 07'), - (1398,1196,'Exhibition Single 08'), - (1399,1196,'Exhibition Single 09'), - (1410,1196,'Exhibition Tag 00'), - (1411,1196,'Exhibition Tag 01'), - (1412,1196,'Exhibition Tag 02'), - (1413,1196,'Exhibition Tag 03'), - (1414,1196,'Exhibition Tag 04'), - (1415,1196,'Exhibition Tag 05'), - (1416,1196,'Exhibition Tag 06'), - (1417,1196,'Exhibition Tag 07'), - (1418,1196,'Exhibition Tag 08'), - (1419,1196,'Exhibition Tag 09'), - (1430,1196,'Exhibition Main 00'), - (1431,1196,'Exhibition Main 01'), - (1432,1196,'Exhibition Main 02'), - (1433,1196,'Exhibition Main 03'), - (1434,1196,'Exhibition Main 04'), - (1435,1196,'Exhibition Main 05'), - (1436,1196,'Exhibition Main 06'), - (1437,1196,'Exhibition Main 07'), - (1438,1196,'Exhibition Main 08'), - (1439,1196,'Exhibition Main 09'), - (1450,1196,'Exhibition Voice 00'), - (1451,1196,'Exhibition Voice 01'), - (1452,1196,'Exhibition Voice 02'), - (1453,1196,'Exhibition Voice 03'), - (1454,1196,'Exhibition Voice 04'), - (1455,1196,'Exhibition Voice 05'), - (1456,1196,'Exhibition Voice 06'), - (1457,1196,'Exhibition Voice 07'), - (1458,1196,'Exhibition Voice 08'), - (1459,1196,'Exhibition Voice 09'), - (1470,1196,'TitleMatch Single 00'), - (1471,1196,'TitleMatch Single 01'), - (1472,1196,'TitleMatch Single 02'), - (1473,1196,'TitleMatch Single 03'), - (1474,1196,'TitleMatch Single 04'), - (1475,1196,'TitleMatch Single 05'), - (1476,1196,'TitleMatch Single 06'), - (1477,1196,'TitleMatch Single 07'), - (1478,1196,'TitleMatch Single 08'), - (1479,1196,'TitleMatch Single 09'), - (1490,1196,'TitleMatch Tag 00'), - (1491,1196,'TitleMatch Tag 01'), - (1492,1196,'TitleMatch Tag 02'), - (1493,1196,'TitleMatch Tag 03'), - (1494,1196,'TitleMatch Tag 04'), - (1495,1196,'TitleMatch Tag 05'), - (1496,1196,'TitleMatch Tag 06'), - (1497,1196,'TitleMatch Tag 07'), - (1498,1196,'TitleMatch Tag 08'), - (1499,1196,'TitleMatch Tag 09'), - (1510,1196,'TitleMatch Main 00'), - (1511,1196,'TitleMatch Main 01'), - (1512,1196,'TitleMatch Main 02'), - (1513,1196,'TitleMatch Main 03'), - (1514,1196,'TitleMatch Main 04'), - (1515,1196,'TitleMatch Main 05'), - (1516,1196,'TitleMatch Main 06'), - (1517,1196,'TitleMatch Main 07'), - (1518,1196,'TitleMatch Main 08'), - (1519,1196,'TitleMatch Main 09'), - (1530,1196,'TitleMatch Voice 00'), - (1531,1196,'TitleMatch Voice 01'), - (1532,1196,'TitleMatch Voice 02'), - (1533,1196,'TitleMatch Voice 03'), - (1534,1196,'TitleMatch Voice 04'), - (1535,1196,'TitleMatch Voice 05'), - (1536,1196,'TitleMatch Voice 06'), - (1537,1196,'TitleMatch Voice 07'), - (1538,1196,'TitleMatch Voice 08'), - (1539,1196,'TitleMatch Voice 09'), - (1590,1196,'Trade 00'), - (1591,1196,'Trade 01'), - (1592,1196,'Trade 02'), - (1593,1196,'Trade 03'), - (1594,1196,'Trade 04'), - (1595,1196,'Trade 05'), - (1596,1196,'Trade 06'), - (1597,1196,'Trade 07'), - (1598,1196,'Trade 08'), - (1599,1196,'Trade 09'), - (1610,1228,'Group Room 1'), - (1611,1228,'Group Room 2'), - (1612,1228,'Group Room 3'), - (1613,1122,'Noodlers'), - (1614,1265,'West Coast'), - (1616,1265,'East Coast'), - (1620,1266,'QuickMatch'), - (1621,1266,'ChatRoom2'), - (1622,1266,'ChatRoom1'), - (1623,1266,'LobbyRoom1'), - (1624,1266,'LobbyRoom2'), - (1652,237,'First New One'), - (1653,237,'Second New One'), - (1654,237,'Third New One'), - (1655,237,'Fourth New One'), - (1656,1197,'Exhibition Single 00'), - (1657,1197,'Exhibition Single 01'), - (1658,1197,'Exhibition Single 02'), - (1659,1197,'Exhibition Single 03'), - (1660,1197,'Exhibition Single 04'), - (1661,1197,'Exhibition Single 05'), - (1662,1197,'Exhibition Single 06'), - (1663,1197,'Exhibition Single 07'), - (1664,1197,'Exhibition Single 08'), - (1665,1197,'Exhibition Single 09'), - (1666,1197,'Exhibition Tag 00'), - (1667,1197,'Exhibition Tag 01'), - (1668,1197,'Exhibition Tag 02'), - (1669,1197,'Exhibition Tag 03'), - (1670,1197,'Exhibition Tag 04'), - (1671,1197,'Exhibition Tag 05'), - (1672,1197,'Exhibition Tag 06'), - (1673,1197,'Exhibition Tag 07'), - (1674,1197,'Exhibition Tag 08'), - (1675,1197,'Exhibition Tag 09'), - (1676,1197,'Exhibition Main 00'), - (1677,1197,'Exhibition Main 01'), - (1678,1197,'Exhibition Main 02'), - (1679,1197,'Exhibition Main 03'), - (1680,1197,'Exhibition Main 04'), - (1681,1197,'Exhibition Main 05'), - (1682,1197,'Exhibition Main 06'), - (1683,1197,'Exhibition Main 07'), - (1684,1197,'Exhibition Main 08'), - (1685,1197,'Exhibition Main 09'), - (1686,1197,'Exhibition Voice 00'), - (1687,1197,'Exhibition Voice 01'), - (1688,1197,'Exhibition Voice 02'), - (1689,1197,'Exhibition Voice 03'), - (1690,1197,'Exhibition Voice 04'), - (1691,1197,'Exhibition Voice 05'), - (1692,1197,'Exhibition Voice 06'), - (1693,1197,'Exhibition Voice 07'), - (1694,1197,'Exhibition Voice 08'), - (1695,1197,'Exhibition Voice 09'), - (1696,1197,'TitleMatch Single 00'), - (1697,1197,'TitleMatch Single 01'), - (1698,1197,'TitleMatch Single 02'), - (1699,1197,'TitleMatch Single 03'), - (1700,1197,'TitleMatch Single 04'), - (1701,1197,'TitleMatch Single 05'), - (1702,1197,'TitleMatch Single 06'), - (1703,1197,'TitleMatch Single 07'), - (1704,1197,'TitleMatch Single 08'), - (1705,1197,'TitleMatch Single 09'), - (1706,1197,'TitleMatch Tag 00'), - (1707,1197,'TitleMatch Tag 01'), - (1708,1197,'TitleMatch Tag 02'), - (1709,1197,'TitleMatch Tag 03'), - (1710,1197,'TitleMatch Tag 04'), - (1711,1197,'TitleMatch Tag 05'), - (1712,1197,'TitleMatch Tag 06'), - (1713,1197,'TitleMatch Tag 07'), - (1714,1197,'TitleMatch Tag 08'), - (1715,1197,'TitleMatch Tag 09'), - (1716,1197,'TitleMatch Main 00'), - (1717,1197,'TitleMatch Main 01'), - (1718,1197,'TitleMatch Main 02'), - (1719,1197,'TitleMatch Main 03'), - (1720,1197,'TitleMatch Main 04'), - (1721,1197,'TitleMatch Main 05'), - (1722,1197,'TitleMatch Main 06'), - (1723,1197,'TitleMatch Main 07'), - (1724,1197,'TitleMatch Main 08'), - (1725,1197,'TitleMatch Main 09'), - (1726,1197,'TitleMatch Voice 00'), - (1727,1197,'TitleMatch Voice 01'), - (1728,1197,'TitleMatch Voice 02'), - (1729,1197,'TitleMatch Voice 03'), - (1730,1197,'TitleMatch Voice 04'), - (1731,1197,'TitleMatch Voice 05'), - (1732,1197,'TitleMatch Voice 06'), - (1733,1197,'TitleMatch Voice 07'), - (1734,1197,'TitleMatch Voice 08'), - (1735,1197,'TitleMatch Voice 09'), - (1736,1197,'Trade 00'), - (1737,1197,'Trade 01'), - (1738,1197,'Trade 02'), - (1739,1197,'Trade 03'), - (1740,1197,'Trade 04'), - (1741,1197,'Trade 05'), - (1742,1197,'Trade 06'), - (1743,1197,'Trade 07'), - (1744,1197,'Trade 08'), - (1745,1197,'Trade 09'), - (1746,1198,'Exhibition Single 00'), - (1747,1198,'Exhibition Single 01'), - (1748,1198,'Exhibition Single 02'), - (1749,1198,'Exhibition Single 03'), - (1750,1198,'Exhibition Single 04'), - (1751,1198,'Exhibition Tag 00'), - (1752,1198,'Exhibition Tag 01'), - (1753,1198,'Exhibition Tag 02'), - (1754,1198,'Exhibition Tag 03'), - (1755,1198,'Exhibition Tag 04'), - (1756,1198,'Exhibition Main 00'), - (1757,1198,'Exhibition Main 01'), - (1758,1198,'Exhibition Main 02'), - (1759,1198,'Exhibition Main 03'), - (1760,1198,'Exhibition Main 04'), - (1761,1198,'Exhibition Voice 00'), - (1762,1198,'Exhibition Voice 01'), - (1763,1198,'Exhibition Voice 02'), - (1764,1198,'Exhibition Voice 03'), - (1765,1198,'Exhibition Voice 04'), - (1766,1198,'TitleMatch Single 00'), - (1767,1198,'TitleMatch Single 01'), - (1768,1198,'TitleMatch Single 02'), - (1769,1198,'TitleMatch Single 03'), - (1770,1198,'TitleMatch Single 04'), - (1771,1198,'TitleMatch Tag 00'), - (1772,1198,'TitleMatch Tag 01'), - (1773,1198,'TitleMatch Tag 02'), - (1774,1198,'TitleMatch Tag 03'), - (1775,1198,'TitleMatch Tag 04'), - (1776,1198,'TitleMatch Main 00'), - (1777,1198,'TitleMatch Main 01'), - (1778,1198,'TitleMatch Main 02'), - (1779,1198,'TitleMatch Main 03'), - (1780,1198,'TitleMatch Main 04'), - (1781,1198,'TitleMatch Voice 00'), - (1782,1198,'TitleMatch Voice 01'), - (1783,1198,'TitleMatch Voice 02'), - (1784,1198,'TitleMatch Voice 03'), - (1785,1198,'TitleMatch Voice 04'), - (1786,1198,'Trade 00'), - (1787,1198,'Trade 01'), - (1788,1198,'Trade 02'), - (1789,1198,'Trade 03'), - (1790,1198,'Trade 04'), - (1793,1122,'Jammers'), - (1795,1066,'Rebellion'), - (1796,1066,'Empire'), - (1797,1066,'Versus (1vs1)'), - (1798,1066,'Team Games'), - (1799,1066,'General'), - (1800,1066,'Rebellion'), - (1801,1066,'Empire'), - (1802,1066,'Versus (1vs1)'), - (1803,1066,'Team Games'), - (1804,1066,'General'), - (1805,1066,'Rebellion'), - (1806,1066,'Empire'), - (1807,1066,'Versus (1vs1)'), - (1808,1066,'Team Games'), - (1809,1066,'General'), - (1810,1066,'Rebellion'), - (1811,1066,'Empire'), - (1812,1066,'Versus (1vs1)'), - (1813,1066,'Team Games'), - (1814,1066,'General'), - (1815,1066,'Rebellion'), - (1816,1066,'Empire'), - (1817,1066,'Versus (1vs1)'), - (1818,1066,'Team Games'), - (1819,1066,'General'), - (1820,1066,'Rebellion'), - (1821,1066,'Empire'), - (1822,1066,'Versus (1vs1)'), - (1823,1066,'Team Games'), - (1824,1066,'General'), - (1825,1066,'Rebellion'), - (1826,1066,'Empire'), - (1827,1066,'Versus (1vs1)'), - (1828,1066,'Team Games'), - (1829,1066,'General'), - (1830,1066,'Rebellion'), - (1831,1066,'Empire'), - (1837,1309,'West'), - (1838,1309,'East'), - (1839,1321,'QuickMatch'), - (1840,1321,'ChatRoom1'), - (1842,1321,'LobbyRoom1'), - (1843,1321,'LobbyRoom2'), - (1844,1321,'LobbyRoom3'), - (1845,1321,'LobbyRoom4'), - (1846,1321,'LobbyRoom5'), - (1847,1321,'LobbyRoom6'), - (1848,1321,'LobbyRoom7'), - (1849,1321,'LobbyRoom8'), - (1850,1283,'Western US'), - (1851,1283,'Central US'), - (1852,1283,'Eastern US'), - (1853,1283,'German'), - (1854,1283,'Spanish'), - (1855,1283,'English'), - (1856,1283,'Italian'), - (1857,1283,'French'), - (1858,1321,'LobbyRoom9'), - (1859,1122,'Chop Masters'), - (1860,1160,'USA'), - (1861,1160,'Europe'), - (1862,1190,'Debug'), - (1863,1354,'Larry'), - (1864,1354,'Curly'), - (1865,1354,'Moe'), - (1866,1376,'West'), - (1867,1376,'East'), - (1868,1391,'Action'), - (1869,1391,'Story'), - (1870,1391,'Story Lite'), - (1871,1391,'Role Play'), - (1872,1391,'Team'), - (1873,1391,'Melee'), - (1874,1391,'Arena'), - (1875,1391,'Social'), - (1876,1391,'Alternative'), - (1877,1391,'PW Story'), - (1878,1391,'PW Action'), - (1879,1391,'Solo'), - (1880,1391,'Tech Support'), - (1881,1122,'eJamming Test'), - (1882,1401,'Novices'), - (1883,1401,'Veterans'), - (1884,1401,'English'), - (1885,1401,'French'), - (1886,1401,'German'), - (1887,1401,'Italian'), - (1888,1401,'Spanish'), - (1889,1396,'Africa'), - (1890,1396,'America'), - (1891,1396,'Asia'), - (1892,1396,'Europe'), - (1893,1396,'Pacific'), - (1894,1396,'The Empire'), - (1895,1396,'Hordes of Chaos'), - (1896,1396,'High Elves'), - (1897,1396,'Skaven'), - (1898,1396,'Other'), - (1899,1396,'Kicked'), - (1900,1396,'Banned'), - (1901,1422,'QuickMatch'), - (1902,1422,'ChatRoom1'), - (1904,1426,'Beginner'), - (1905,1426,'Intermediate'), - (1906,1426,'Advanced'), - (1907,1411,'Room 1'), - (1908,1411,'Room 2'), - (1909,1411,'Room 3'), - (1910,1411,'Room 4'), - (1911,1411,'Room 5'), - (1912,1411,'Room 6'), - (1913,1411,'Room 7'), - (1914,1411,'Room 8'), - (1915,1411,'Room 9'), - (1916,1411,'Room 10'), - (1917,1463,'QuickMatch'), - (1918,1463,'ChatRoom1'), - (1919,1463,'LobbyRoom1'), - (1920,1463,'LobbyRoom2'), - (1921,1463,'LobbyRoom3'), - (1922,1463,'LobbyRoom4'), - (1923,1463,'LobbyRoom5'), - (1924,1463,'LobbyRoom6'), - (1925,1463,'LobbyRoom7'), - (1926,1463,'LobbyRoom8'), - (1927,1463,'LobbyRoom9'), - (1928,1398,'Africa'), - (1929,1398,'America'), - (1930,1398,'Asia'), - (1931,1398,'Europe'), - (1932,1398,'Pacific'), - (1933,1398,'The Empire'), - (1934,1398,'Hordes of Chaos'), - (1935,1398,'High Elves'), - (1936,1398,'Skaven'), - (1937,1398,'Other'), - (1938,1398,'Kicked'), - (1939,1398,'Banned'), - (1940,1479,'West'), - (1941,1479,'East'), - (1942,1481,'East'), - (1943,1481,'West'), - (1944,1463,'QuickMatch2'), - (1945,1483,'America'), - (1946,1483,'Asia'), - (1947,1483,'Europe'), - (1948,1321,'QuickMatch2'), - (1956,1514,'Newbies'), - (1957,1514,'Experienced Players'), - (1958,1514,'Strategists'), - (1959,1515,'Newbies'), - (1960,1515,'Experienced Players'), - (1961,1515,'Strategists'), - (1962,1523,'Skirmish'), - (1963,1523,'World Domination'), - (1964,1524,'Skirmish'), - (1965,1524,'World Domination'), - (1966,1577,'Rebellion'), - (1967,1577,'Empire'), - (1968,1577,'Versus (1vs1)'), - (1969,1577,'Team Games'), - (1970,1577,'General'), - (1971,1577,'Rebellion'), - (1972,1577,'Empire'), - (1973,1577,'Versus (1vs1)'), - (1974,1577,'Team Games'), - (1975,1577,'General'), - (1976,1577,'Rebellion'), - (1977,1577,'Empire'), - (1978,1577,'Versus (1vs1)'), - (1979,1577,'Team Games'), - (1980,1577,'General'), - (1981,1577,'Rebellion'), - (1982,1577,'Empire'), - (1983,1577,'Versus (1vs1)'), - (1984,1577,'Team Games'), - (1985,1577,'General'), - (1986,1577,'Rebellion'), - (1987,1577,'Empire'), - (1988,1577,'Versus (1vs1)'), - (1989,1577,'Team Games'), - (1990,1577,'General'), - (1991,1577,'Rebellion'), - (1992,1577,'Empire'), - (1993,1577,'Versus (1vs1)'), - (1994,1577,'Team Games'), - (1995,1577,'General'), - (1996,1577,'Rebellion'), - (1997,1577,'Empire'), - (1998,1577,'Versus (1vs1)'), - (1999,1577,'Team Games'), - (2000,1577,'General'), - (2001,1577,'Rebellion'), - (2002,1577,'Empire'), - (2003,1631,'Skirmish'), - (2004,1631,'World Domination'), - (2027,1714,'ChatRoom1'), - (2028,1714,'QuickMatch'), - (2029,1714,'LobbyRoom:1'), - (2030,1714,'LobbyRoom:2'), - (2031,1714,'LobbyRoom:3'), - (2032,1714,'LobbyRoom:4'), - (2033,1714,'LobbyRoom:5'), - (2034,1714,'LobbyRoom:6'), - (2035,1714,'LobbyRoom:7'), - (2036,1714,'LobbyRoom:8'), - (2037,1714,'LobbyRoom:9'), - (2038,1714,'LobbyRoom:10'), - (2039,1714,'LobbyRoom:11'), - (2040,1714,'LobbyRoom:12'), - (2041,1714,'LobbyRoom:13'), - (2042,1714,'LobbyRoom:14'), - (2043,1714,'LobbyRoom:15'), - (2044,1714,'LobbyRoom:16'), - (2045,1714,'LobbyBeginners:1'), - (2046,1714,'LobbyHardcore:1'), - (2047,1714,'LobbyClan:1'), - (2048,1714,'LobbyClan:2'), - (2049,1714,'LobbyTournaments:1'), - (2050,1714,'LobbyTournaments:2'), - (2051,1714,'LobbyBattlecast:1'), - (2052,1714,'LobbyCustomMap:1'), - (2053,1714,'LobbyCustomMap:2'), - (2054,1714,'LobbyCompStomp:1'), - (2055,1714,'LobbyGerman:1'), - (2056,1714,'LobbyGerman:2'), - (2057,1714,'LobbyKorean:1'), - (2058,1714,'LobbyFrench:1'), - (2059,1422,'LobbyRoom:1'), - (2060,1422,'LobbyRoom:2'), - (2061,1422,'LobbyRoom:3'), - (2062,1422,'LobbyRoom:4'), - (2063,1422,'LobbyRoom:5'), - (2064,1422,'LobbyRoom:6'), - (2065,1422,'LobbyRoom:7'), - (2066,1422,'LobbyRoom:8'), - (2067,1422,'LobbyRoom:9'), - (2068,1422,'LobbyRoom:10'), - (2069,1422,'LobbyRoom:11'), - (2070,1422,'LobbyRoom:12'), - (2071,1422,'LobbyRoom:13'), - (2072,1422,'LobbyRoom:14'), - (2073,1422,'LobbyRoom:15'), - (2074,1422,'LobbyRoom:16'), - (2075,1422,'LobbyBeginners:1'), - (2076,1422,'LobbyHardcore:1'), - (2077,1422,'LobbyClan:1'), - (2078,1422,'LobbyClan:2'), - (2079,1422,'LobbyTournaments:1'), - (2080,1422,'LobbyTournaments:2'), - (2081,1422,'LobbyBattlecast:1'), - (2082,1422,'LobbyCustomMap:1'), - (2083,1422,'LobbyCustomMap:2'), - (2084,1422,'LobbyCompStomp:1'), - (2085,1422,'LobbyGerman:1'), - (2086,1422,'LobbyGerman:2'), - (2087,1422,'LobbyKorean:1'), - (2088,1422,'LobbyFrench:1'), - (2089,1774,'Room 1'), - (2090,1774,'Room 2'), - (2091,1774,'Room 3'), - (2092,1774,'Room 4'), - (2093,1774,'Room 5'), - (2094,1774,'Room 6'), - (2095,1774,'Room 7'), - (2096,1774,'Room 8'), - (2097,1774,'Room 9'), - (2098,1774,'Room 10'), - (2099,1814,'ChatRoom1'), - (2100,1814,'QuickMatch'), - (2101,1814,'LobbyRoom:1'), - (2102,1814,'LobbyRoom:2'), - (2103,1814,'LobbyRoom:3'), - (2104,1814,'LobbyRoom:4'), - (2105,1814,'LobbyRoom:5'), - (2106,1814,'LobbyRoom:6'), - (2107,1814,'LobbyRoom:7'), - (2108,1814,'LobbyRoom:8'), - (2109,1814,'LobbyRoom:9'), - (2110,1814,'LobbyRoom:10'), - (2111,1814,'LobbyRoom:11'), - (2112,1814,'LobbyRoom:12'), - (2113,1814,'LobbyRoom:13'), - (2114,1814,'LobbyRoom:14'), - (2115,1814,'LobbyRoom:15'), - (2116,1814,'LobbyRoom:16'), - (2117,1814,'LobbyBeginners:1'), - (2118,1814,'LobbyHardcore:1'), - (2119,1814,'LobbyClan:1'), - (2120,1814,'LobbyClan:2'), - (2121,1814,'LobbyTournaments:1'), - (2122,1814,'LobbyTournaments:2'), - (2123,1814,'LobbyBattlecast:1'), - (2124,1814,'LobbyCustomMap:1'), - (2125,1814,'LobbyCustomMap:2'), - (2126,1814,'LobbyCompStomp:1'), - (2127,1814,'LobbyGerman:1'), - (2128,1814,'LobbyGerman:2'), - (2129,1814,'LobbyKorean:1'), - (2130,1814,'LobbyFrench:1'), - (2131,1884,'Room 1'), - (2132,1884,'Room 2'), - (2133,1884,'Room 3'), - (2134,1884,'Room 4'), - (2135,1884,'Room 5'), - (2136,1884,'Room 6'), - (2137,1884,'Room 7'), - (2138,1884,'Room 8'), - (2139,1884,'Room 9'), - (2140,1884,'Room 10'), - (2141,1923,'Africa'), - (2142,1923,'America'), - (2143,1923,'Asia'), - (2144,1923,'Europe'), - (2145,1923,'Pacific'), - (2146,1923,'The Empire'), - (2147,1923,'Hordes of Chaos'), - (2148,1923,'High Elves'), - (2149,1923,'Skaven'), - (2150,1923,'Other'), - (2151,1923,'Dark Elf'), - (2152,1923,'Orc'), - (2153,1923,'Kicked'), - (2154,1923,'Banned'), - (2155,1514,'Sparta FX'), - (2156,1979,'QuickMatch'), - (2157,1979,'LobbyRoom:1'), - (2158,1979,'ChatRoom1'), - (2159,2100,'QuickMatch'), - (2160,2100,'LobbyRoom:1'), - (2161,2100,'ChatRoom1'), - (2162,2094,'QuickMatch'), - (2163,2094,'LobbyRoom:1'), - (2164,2094,'ChatRoom1'), - (2166,2128,'LobbyRoom:1'), - (2167,2128,'LobbyRoom:2'), - (2168,2128,'LobbyRoom:3'), - (2169,2128,'LobbyRoom:4'), - (2170,2128,'LobbyRoom:5'), - (2171,2128,'LobbyKorean:1'), - (2172,2128,'LobbyFrench:1'), - (2173,2128,'LobbyGerman:2'), - (2174,2128,'LobbyGerman:1'), - (2175,2128,'LobbyBattlecast:1'), - (2176,2128,'LobbyRoom:6'), - (2177,2128,'ChatRoom1'), - (2178,2128,'LobbyRoom:8'), - (2179,2128,'LobbyRoom:11'), - (2180,2128,'LobbyRoom:7'), - (2181,2128,'LobbyRoom:9'), - (2182,2128,'LobbyRoom:12'), - (2183,2128,'LobbyRoom:10'), - (2184,2128,'LobbyClan:1'), - (2185,2128,'LobbyRoom:13'), - (2186,2128,'LobbyClan:2'), - (2187,2128,'LobbyRoom:14'), - (2188,2128,'LobbyRoom:16'), - (2189,2128,'LobbyRoom:15'), - (2190,2128,'LobbyBeginners:1'), - (2191,2128,'LobbyTournaments:1'), - (2192,2128,'LobbyCompStomp:1'), - (2193,2128,'LobbyHardcore:1'), - (2194,2128,'LobbyCustomMap:1'), - (2195,2128,'LobbyCustomMap:2'), - (2196,2128,'LobbyTournaments:2'), - (2198,2128,'ChatRoom1'), - (2200,2130,'LobbyRoom:1'), - (2201,2130,'LobbyRoom:2'), - (2202,2130,'LobbyRoom:3'), - (2203,2130,'LobbyRoom:4'), - (2204,2130,'LobbyRoom:5'), - (2205,2130,'LobbyKorean:1'), - (2206,2130,'LobbyFrench:1'), - (2207,2130,'LobbyGerman:2'), - (2208,2130,'LobbyGerman:1'), - (2209,2130,'LobbyBattlecast:1'), - (2210,2130,'LobbyRoom:6'), - (2211,2130,'ChatRoom1'), - (2212,2130,'LobbyRoom:8'), - (2213,2130,'LobbyRoom:11'), - (2214,2130,'LobbyRoom:7'), - (2215,2130,'LobbyRoom:9'), - (2216,2130,'LobbyRoom:12'), - (2217,2130,'LobbyRoom:10'), - (2218,2130,'LobbyClan:1'), - (2219,2130,'LobbyRoom:13'), - (2220,2130,'LobbyClan:2'), - (2221,2130,'LobbyRoom:14'), - (2222,2130,'LobbyRoom:16'), - (2223,2130,'LobbyRoom:15'), - (2224,2130,'LobbyBeginners:1'), - (2225,2130,'LobbyTournaments:1'), - (2226,2130,'LobbyCompStomp:1'), - (2227,2130,'LobbyHardcore:1'), - (2228,2130,'LobbyCustomMap:1'), - (2229,2130,'LobbyCustomMap:2'), - (2230,2130,'LobbyTournaments:2'), - (2232,2130,'ChatRoom1'), - (2233,2160,'QuickMatch'), - (2234,2160,'LobbyTournaments:2'), - (2235,2160,'LobbyTournaments:1'), - (2236,2160,'LobbyRoom:9'), - (2237,2160,'LobbyRoom:8'), - (2238,2160,'LobbyRoom:7'), - (2239,2160,'LobbyRoom:6'), - (2240,2160,'LobbyRoom:5'), - (2241,2160,'LobbyRoom:4'), - (2242,2160,'LobbyRoom:3'), - (2243,2160,'LobbyRoom:2'), - (2244,2160,'LobbyRoom:16'), - (2245,2160,'LobbyRoom:15'), - (2246,2160,'LobbyRoom:14'), - (2247,2160,'LobbyRoom:13'), - (2248,2160,'LobbyRoom:12'), - (2249,2160,'LobbyRoom:11'), - (2250,2160,'LobbyRoom:10'), - (2251,2160,'LobbyRoom:1'), - (2252,2160,'LobbyKorean:1'), - (2253,2160,'LobbyHardcore:1'), - (2254,2160,'LobbyGerman:2'), - (2255,2160,'LobbyGerman:1'), - (2256,2160,'LobbyFrench:1'), - (2257,2160,'LobbyCustomMap:2'), - (2258,2160,'LobbyCustomMap:1'), - (2259,2160,'LobbyCompStomp:1'), - (2260,2160,'LobbyClan:2'), - (2261,2160,'LobbyClan:1'), - (2262,2160,'LobbyBeginners:1'), - (2263,2160,'LobbyBattlecast:1'), - (2264,2160,'ChatRoom1'), - (2265,1979,'Russia:1'), - (2266,2238,'LobbyRoom:1'), - (2267,2238,'LobbyRoom:2'), - (2268,2238,'LobbyRoom:3'), - (2269,2238,'LobbyRoom:4'), - (2270,2238,'LobbyRoom:5'), - (2271,2238,'LobbyRoom:6'), - (2272,2238,'LobbyRoom:7'), - (2273,2238,'LobbyRoom:8'), - (2274,2238,'LobbyRoom:9'), - (2275,2238,'LobbyRoom:10'), - (2276,2238,'LobbyRoom:11'), - (2277,2238,'LobbyRoom:12'), - (2278,2238,'LobbyRoom:13'), - (2279,2238,'LobbyRoom:14'), - (2280,2238,'LobbyRoom:15'), - (2281,2238,'LobbyRoom:16'), - (2282,2238,'LobbyBeginners:1'), - (2283,2238,'LobbyHardcore:1'), - (2284,2238,'LobbyClan:1'), - (2285,2238,'LobbyClan:2'), - (2286,2238,'LobbyTournaments:1'), - (2287,2238,'LobbyTournaments:2'), - (2288,2238,'LobbyBattlecast:1'), - (2289,2238,'LobbyCustomMap:1'), - (2290,2238,'LobbyCustomMap:2'), - (2291,2238,'LobbyCompStomp:1'), - (2292,2238,'LobbyGerman:1'), - (2293,2238,'LobbyGerman:2'), - (2294,2238,'LobbyKorean:1'), - (2295,2238,'LobbyFrench:1'), - (2296,2238,'ChatRoom1'), - (2297,1814,'Russia:1'), - (2298,2298,'Deathmatch'), - (2299,2298,'RopeRace'), - (2300,2298,'Forts'), - (2301,2298,'Triathlon'), - (2302,2313,'Beginner'), - (2303,2313,'Intermediate'), - (2304,2313,'Expert'), - (2305,2374,'ChatRoom1'), - (2306,2374,'LobbyRoom:1'), - (2307,2374,'LobbyRoom:2'), - (2308,2374,'LobbyRoom:3'), - (2309,2374,'LobbyRoom:4'), - (2310,2374,'LobbyRoom:5'), - (2311,2374,'LobbyKorean:1'), - (2312,2374,'LobbyFrench:1'), - (2313,2374,'LobbyGerman:2'), - (2314,2374,'LobbyGerman:1'), - (2315,2374,'LobbyBattlecast:1'), - (2316,2374,'LobbyRoom:6'), - (2317,2374,'ChatRoom1'), - (2318,2374,'LobbyRoom:8'), - (2319,2374,'LobbyRoom:11'), - (2320,2374,'LobbyRoom:7'), - (2321,2374,'LobbyRoom:9'), - (2322,2374,'LobbyRoom:12'), - (2323,2374,'LobbyRoom:10'), - (2324,2374,'LobbyClan:1'), - (2325,2374,'LobbyRoom:13'), - (2326,2374,'LobbyClan:2'), - (2327,2374,'LobbyRoom:14'), - (2328,2374,'LobbyRoom:16'), - (2329,2374,'LobbyRoom:15'), - (2330,2374,'LobbyBeginners:1'), - (2331,2374,'LobbyTournaments:1'), - (2332,2374,'LobbyCompStomp:1'), - (2333,2374,'LobbyHardcore:1'), - (2334,2374,'LobbyCustomMap:1'), - (2335,2374,'LobbyCustomMap:2'), - (2336,2374,'LobbyTournaments:2'), - (2337,2130,'LobbyRussian:1'), - (2338,2130,'LobbyTaiwan:1'), - (2339,2128,'LobbyRoom:17'), - (2340,2128,'LobbyRoom:18'), - (2341,2128,'LobbyRoom:19'), - (2342,2128,'LobbyRoom:20'), - (2343,2128,'LobbyRoom:21'), - (2344,2128,'LobbyCoop:1'), - (2345,2128,'LobbyCoop:2'), - (2346,2128,'LobbyCoop:3'), - (2347,2128,'LobbyCoop:4'), - (2348,2128,'LobbyCoop:5'), - (2349,2128,'LobbyRussian:1'), - (2350,2128,'LobbyTaiwan:1'), - (2351,2298,'WarRoom'), - (2352,2298,'TacticsMode'), - (2353,2259,'room1'), - (2354,2259,'room2'), - (2355,2259,'room3'), - (2356,2259,'room4'), - (2357,2128,'LobbySpanish:1'), - (2358,2714,'room1'), - (2359,2714,'room2'), - (2360,2714,'room3'), - (2361,2714,'room4'), - (2362,2246,'ChatMonTesting'), - (2363,2712,'room1'), - (2364,2712,'room2'), - (2365,2712,'room3'), - (2366,2712,'room4'), - (2367,2705,'North America'), - (2368,2705,'Europe'), - (2369,2705,'Brazil'), - (2370,2840,'FX Sparta II'), - (2371,2706,'North America'), - (2372,2706,'Europe'), - (2373,2706,'Brazil'), - (2374,2707,'North America'), - (2375,2707,'Europe'), - (2376,2707,'Brazil'), - (2377,2032,'North America'), - (2378,2032,'Europe'), - (2379,2032,'Brazil'), - (2380,2034,'North America'), - (2381,2034,'Europe'), - (2382,2034,'Brazil'), - (2383,2035,'North America'), - (2384,2035,'Europe'), - (2385,2035,'Brazil'), - (2386,706,'Main Lobby'), - (2387,1003,'ThMods.com'), - (2388,917,'Main Lobby'), - (2389,1128,'Main Lobby'), - (2390,1307,'ThMods.com'), - (2391,1005,'ThMods.com'), - (2392,467,'Main Lobby'), - (2393,600,'Main Lobby'), - (2399,1003,'Lobby 2'); -UNLOCK TABLES; - - -LOCK TABLES `messages` WRITE; -UNLOCK TABLES; - - -LOCK TABLES `partner` WRITE; -INSERT INTO `partner` (`partnerid`, `partnername`) VALUES - (0,'RetroSpy'), - (95,'Crytek'); -UNLOCK TABLES; - - -LOCK TABLES `profiles` WRITE; -INSERT INTO `profiles` (`profileid`, `userid`, `nick`, `serverflag`, `status`, `statstring`, `location`, `firstname`, `lastname`, `publicmask`, `latitude`, `longitude`, `aim`, `picture`, `occupationid`, `incomeid`, `industryid`, `marriedid`, `childcount`, `interests1`, `ownership1`, `connectiontype`, `sex`, `zipcode`, `countrycode`, `homepage`, `birthday`, `birthmonth`, `birthyear`, `icquin`, `quietflags`, `streetaddr`, `streeaddr`, `city`, `cpubrandid`, `cpuspeed`, `memory`, `videocard1string`, `videocard1ram`, `videocard2string`, `videocard2ram`, `subscription`, `adminrights`) VALUES - (1,1,'spyguy',0,0,'I love RetroSpy','earth','spy','guy',0,0,0,'0',0,0,0,0,0,0,0,0,0,2,'00000','1','rspy.org',0,0,0,0,0,'','','',0,0,0,'',0,'',0,0,0), - (14,10,'gptest1',0,0,'I love RetroSpy','','','',0,0,0,'0',0,0,0,0,0,0,0,0,0,2,'00000','1','rspy.org',0,0,0,0,0,NULL,NULL,NULL,0,0,0,NULL,0,NULL,0,0,0), - (15,11,'gptest2',0,0,'I love RetroSpy','','','',0,0,0,'0',0,0,0,0,0,0,0,0,0,2,'00000','1','rspy.org',0,0,0,0,0,NULL,NULL,NULL,0,0,0,NULL,0,NULL,0,0,0), - (16,12,'gptest3',0,0,'I love RetroSpy','','','',0,0,0,'0',0,0,0,0,0,0,0,0,0,2,'00000','1','rspy.org',0,0,0,0,0,NULL,NULL,NULL,0,0,0,NULL,0,NULL,0,0,0), - (19,15,'mrpants',0,0,'I love RetroSpy','','','',0,0,0,'0',0,0,0,0,0,0,0,0,0,2,'00000','1','rspy.org',0,0,0,0,0,NULL,NULL,NULL,0,0,0,NULL,0,NULL,0,0,0); -UNLOCK TABLES; - - -LOCK TABLES `pstorage` WRITE; -INSERT INTO `pstorage` (`pstorageid`, `profileid`, `ptype`, `dindex`, `data`) VALUES - (1,1,1,0,''), - (2,1,3,0,''); -UNLOCK TABLES; - - -LOCK TABLES `sakestorage` WRITE; -UNLOCK TABLES; - - -LOCK TABLES `subprofiles` WRITE; -INSERT INTO `subprofiles` (`subprofileid`, `profileid`, `uniquenick`, `namespaceid`, `partnerid`, `productid`, `gamename`, `cdkeyenc`, `firewall`, `port`, `authtoken`) VALUES - (1,1,'spyguy',1,0,0,'gmtest',NULL,0,0,'example_token'), - (13,14,'',1,0,0,'gmtest',NULL,0,0,NULL), - (14,15,'',1,0,0,'gmtest',NULL,0,0,NULL), - (15,16,'',1,0,0,'gmtest',NULL,0,0,NULL), - (18,19,'',1,0,0,'gmtest',NULL,0,0,NULL); -UNLOCK TABLES; - - -LOCK TABLES `users` WRITE; -INSERT INTO `users` (`userid`, `email`, `password`, `emailverified`, `lastip`, `lastonline`, `createddate`, `banned`, `deleted`) VALUES - (1,'spyguy@gamespy.com','4a7d1ed414474e4033ac29ccb8653d9b',1,'127.0.0.1','2020-05-15 13:17:00','2019-08-11 01:07:27',0,0), - (10,'gptestc1@gptestc.com','c6d525669e64438c9aa156a0cc80cd14',1,NULL,'2021-02-10 12:04:13','2021-02-10 12:04:13',0,0), - (11,'gptestc2@gptestc.com','c6d525669e64438c9aa156a0cc80cd14',1,NULL,'2021-02-10 12:04:33','2021-02-10 12:04:33',0,0), - (12,'gptestc3@gptestc.com','c6d525669e64438c9aa156a0cc80cd14',1,NULL,'2021-02-10 12:04:40','2021-02-10 12:04:40',0,0), - (15,'dan@gamespy.com','6e7d5392358354f24f39064380cb7061',1,NULL,'2021-04-10 13:35:46','2021-04-10 13:35:46',0,0); -UNLOCK TABLES; - - - - - - -SET FOREIGN_KEY_CHECKS = @ORIG_FOREIGN_KEY_CHECKS; - -SET UNIQUE_CHECKS = @ORIG_UNIQUE_CHECKS; - -SET @ORIG_TIME_ZONE = @@TIME_ZONE; -SET TIME_ZONE = @ORIG_TIME_ZONE; - -SET SQL_MODE = @ORIG_SQL_MODE; - - - -# Export Finished: April 10, 2021 at 21:38:07 GMT+8 - diff --git a/common/UniSpyServerConfig.json b/common/UniSpyServerConfig.json deleted file mode 100644 index 75e04d2fc..000000000 --- a/common/UniSpyServerConfig.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "Database": { - "Server": "127.0.0.1", - "Port": "5432", - "Database": "unispy", - "Username": "root", - "Password": "0000", - "SSLMode": "Prefer", - "TrustServerCert": "false", - "SSLKey": "", - "SSLPassword": "", - "RootCert": "" - }, - "Redis": { - "Server": "127.0.0.1", - "Port": "6379", - "User": "", - "Password": "", - "SSL": "false", - "SSLHost": "" - }, - "Servers": [ - { - "ServerID": "00000000-0000-0000-0000-000000000000", - "ServerName": "PresenceConnectionManager", - "PublicAddress": "0.0.0.0", - "ListeningPort": "29900" - }, - { - "ServerID": "00000000-0000-0000-0000-000000000000", - "ServerName": "PresenceSearchPlayer", - "PublicAddress": "0.0.0.0", - "ListeningPort": "29901" - }, - { - "ServerID": "00000000-0000-0000-0000-000000000000", - "ServerName": "CDKey", - "PublicAddress": "0.0.0.0", - "ListeningPort": "29910" - }, - { - "ServerID": "00000000-0000-0000-0000-000000000000", - "ServerName": "ServerBrowserV1", - "PublicAddress": "0.0.0.0", - "ListeningPort": "28900" - }, - { - "ServerID": "00000000-0000-0000-0000-000000000000", - "ServerName": "ServerBrowserV2", - "PublicAddress": "0.0.0.0", - "ListeningPort": "28910" - }, - { - "ServerID": "00000000-0000-0000-0000-000000000000", - "ServerName": "QueryReport", - "PublicAddress": "0.0.0.0", - "ListeningPort": "27900" - }, - { - "ServerID": "00000000-0000-0000-0000-000000000000", - "ServerName": "NatNegotiation", - "PublicAddress": "0.0.0.0", - "ListeningPort": "27901" - }, - { - "ServerID": "00000000-0000-0000-0000-000000000000", - "ServerName": "GameStatus", - "PublicAddress": "0.0.0.0", - "ListeningPort": "29920" - }, - { - "ServerID": "00000000-0000-0000-0000-000000000000", - "ServerName": "Chat", - "PublicAddress": "0.0.0.0", - "ListeningPort": "6667" - }, - { - "ServerID": "00000000-0000-0000-0000-000000000000", - "ServerName": "WebServer", - "PublicAddress": "0.0.0.0", - "ListeningPort": "80" - }, - { - "ServerID": "00000000-0000-0000-0000-000000000000", - "ServerName": "GameTrafficRelay", - "PublicAddress": "0.0.0.0", - "ListeningPort": "10086" - } - ], - "MinimumLogLevel": "Verbose" -} \ No newline at end of file diff --git a/common/UniSpy_pg.sql b/common/UniSpy_pg.sql index 3a8add655..a91a1ab86 100644 --- a/common/UniSpy_pg.sql +++ b/common/UniSpy_pg.sql @@ -2,10 +2,8 @@ -- PostgreSQL database dump -- --- Dumped from database version 14.2 (Debian 14.2-1.pgdg110+1) --- Dumped by pg_dump version 14.1 - --- Started on 2022-03-02 20:15:24 CET +-- Dumped from database version 14.13 (Debian 14.13-1.pgdg120+1) +-- Dumped by pg_dump version 14.13 (Debian 14.13-1.pgdg120+1) SET statement_timeout = 0; SET lock_timeout = 0; @@ -19,17 +17,16 @@ SET client_min_messages = warning; SET row_security = off; -- --- TOC entry 5 (class 2615 OID 16385) --- Name: unispy; Type: SCHEMA; Schema: -; Owner: - +-- Name: unispy; Type: SCHEMA; Schema: -; Owner: unispy -- CREATE SCHEMA unispy; +ALTER SCHEMA unispy OWNER TO unispy; + -- --- TOC entry 3466 (class 0 OID 0) --- Dependencies: 5 --- Name: SCHEMA unispy; Type: COMMENT; Schema: -; Owner: - +-- Name: SCHEMA unispy; Type: COMMENT; Schema: -; Owner: unispy -- COMMENT ON SCHEMA unispy IS 'standard public schema'; @@ -40,149 +37,229 @@ SET default_tablespace = ''; SET default_table_access_method = heap; -- --- TOC entry 209 (class 1259 OID 16386) --- Name: addrequests; Type: TABLE; Schema: unispy; Owner: - +-- Name: addrequests; Type: TABLE; Schema: unispy; Owner: unispy -- CREATE TABLE unispy.addrequests ( - addrequestid integer NOT NULL, + addrequestid SERIAL PRIMARY KEY NOT NULL, profileid integer NOT NULL, - namespaceid integer NOT NULL, targetid integer NOT NULL, + namespaceid integer NOT NULL, reason character varying NOT NULL, - syncrequested character varying NOT NULL + status smallint NOT NULL ); --- --- TOC entry 3467 (class 0 OID 0) --- Dependencies: 209 --- Name: TABLE addrequests; Type: COMMENT; Schema: unispy; Owner: - --- - -COMMENT ON TABLE unispy.addrequests IS 'Friend request.'; - +ALTER TABLE unispy.addrequests OWNER TO unispy; -- --- TOC entry 210 (class 1259 OID 16391) --- Name: addrequests_addrequestid_seq; Type: SEQUENCE; Schema: unispy; Owner: - +-- Name: addrequests_addrequestid_seq; Type: SEQUENCE; Schema: unispy; Owner: unispy -- -CREATE SEQUENCE unispy.addrequests_addrequestid_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; +-- CREATE SEQUENCE unispy.addrequests_addrequestid_seq +-- AS integer +-- START WITH 1 +-- INCREMENT BY 1 +-- NO MINVALUE +-- NO MAXVALUE +-- CACHE 1; +ALTER TABLE unispy.addrequests_addrequestid_seq OWNER TO unispy; + -- --- TOC entry 3468 (class 0 OID 0) --- Dependencies: 210 --- Name: addrequests_addrequestid_seq; Type: SEQUENCE OWNED BY; Schema: unispy; Owner: - +-- Name: addrequests_addrequestid_seq; Type: SEQUENCE OWNED BY; Schema: unispy; Owner: unispy -- ALTER SEQUENCE unispy.addrequests_addrequestid_seq OWNED BY unispy.addrequests.addrequestid; -- --- TOC entry 211 (class 1259 OID 16392) --- Name: blocked; Type: TABLE; Schema: unispy; Owner: - +-- Name: blocked; Type: TABLE; Schema: unispy; Owner: unispy -- CREATE TABLE unispy.blocked ( - blockid integer NOT NULL, + blockid SERIAL PRIMARY KEY NOT NULL, profileid integer NOT NULL, namespaceid integer NOT NULL, targetid integer NOT NULL ); +ALTER TABLE unispy.blocked OWNER TO unispy; + -- --- TOC entry 3469 (class 0 OID 0) --- Dependencies: 211 --- Name: TABLE blocked; Type: COMMENT; Schema: unispy; Owner: - +-- Name: blocked_blockid_seq; Type: SEQUENCE; Schema: unispy; Owner: unispy -- -COMMENT ON TABLE unispy.blocked IS 'Block list.'; +-- CREATE SEQUENCE unispy.blocked_blockid_seq +-- AS integer +-- START WITH 1 +-- INCREMENT BY 1 +-- NO MINVALUE +-- NO MAXVALUE +-- CACHE 1; +ALTER TABLE unispy.blocked_blockid_seq OWNER TO unispy; + -- --- TOC entry 212 (class 1259 OID 16395) --- Name: blocked_blockid_seq; Type: SEQUENCE; Schema: unispy; Owner: - +-- Name: blocked_blockid_seq; Type: SEQUENCE OWNED BY; Schema: unispy; Owner: unispy -- -CREATE SEQUENCE unispy.blocked_blockid_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; +ALTER SEQUENCE unispy.blocked_blockid_seq OWNED BY unispy.blocked.blockid; -- --- TOC entry 3470 (class 0 OID 0) --- Dependencies: 212 --- Name: blocked_blockid_seq; Type: SEQUENCE OWNED BY; Schema: unispy; Owner: - +-- Name: chat_nick_caches; Type: TABLE; Schema: unispy; Owner: unispy -- -ALTER SEQUENCE unispy.blocked_blockid_seq OWNED BY unispy.blocked.blockid; +CREATE TABLE unispy.chat_user_caches ( + server_id uuid NOT NULL, + nick_name character varying PRIMARY KEY NOT NULL, + game_name character varying, + user_name character varying, + remote_ip inet NOT NULL, + remote_port INTEGER NOT NULL, + websocket_address character varying NOT NULL, + key_value jsonb, + update_time timestamp without time zone NOT NULL +); + +-- +-- Name: chat_channel_caches; Type: TABLE; Schema: unispy; Owner: unispy +-- + +CREATE TABLE unispy.chat_channel_caches ( + channel_name character varying PRIMARY KEY NOT NULL, + server_id uuid NOT NULL, + creator character varying, + game_name character varying NOT NULL, + room_name character varying NOT NULL, + topic character varying, + password character varying, + group_id integer NOT NULL, + max_num_user integer NOT NULL, + key_values jsonb, + invited_nicks jsonb, + update_time timestamp without time zone NOT NULL, + modes jsonb NOT NULL, + banned_nicks jsonb +); + + +ALTER TABLE unispy.chat_channel_caches OWNER TO unispy; + +ALTER TABLE unispy.chat_user_caches OWNER TO unispy; + -- --- TOC entry 213 (class 1259 OID 16396) --- Name: friends; Type: TABLE; Schema: unispy; Owner: - +-- Name: chat_user_caches; Type: TABLE; Schema: unispy; Owner: unispy +-- + +CREATE TABLE unispy.chat_channel_user_caches ( + id SERIAL PRIMARY KEY NOT NULL, + nick_name character varying NOT NULL, + user_name character varying NOT NULL, + channel_name character varying NOT NULL, + server_id uuid NOT NULL, + update_time timestamp without time zone NOT NULL, + is_voiceable boolean NOT NULL, + is_channel_operator boolean NOT NULL, + is_channel_creator boolean NOT NULL, + remote_ip inet NOT NULL, + remote_port integer NOT NULL, + key_values jsonb +); + + +ALTER TABLE unispy.chat_channel_user_caches OWNER TO unispy; + +-- +-- Name: friends; Type: TABLE; Schema: unispy; Owner: unispy -- CREATE TABLE unispy.friends ( - friendid integer NOT NULL, + friendid SERIAL PRIMARY KEY NOT NULL, profileid integer NOT NULL, - namespaceid integer NOT NULL, - targetid integer NOT NULL + targetid integer NOT NULL, + namespaceid integer NOT NULL ); +ALTER TABLE unispy.friends OWNER TO unispy; + -- --- TOC entry 3471 (class 0 OID 0) --- Dependencies: 213 --- Name: TABLE friends; Type: COMMENT; Schema: unispy; Owner: - +-- Name: friends_friendid_seq; Type: SEQUENCE; Schema: unispy; Owner: unispy -- -COMMENT ON TABLE unispy.friends IS 'Friend list.'; +-- CREATE SEQUENCE unispy.friends_friendid_seq +-- AS integer +-- START WITH 1 +-- INCREMENT BY 1 +-- NO MINVALUE +-- NO MAXVALUE +-- CACHE 1; +ALTER TABLE unispy.friends_friendid_seq OWNER TO unispy; + -- --- TOC entry 214 (class 1259 OID 16399) --- Name: friends_friendid_seq; Type: SEQUENCE; Schema: unispy; Owner: - +-- Name: friends_friendid_seq; Type: SEQUENCE OWNED BY; Schema: unispy; Owner: unispy -- -CREATE SEQUENCE unispy.friends_friendid_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; +ALTER SEQUENCE unispy.friends_friendid_seq OWNED BY unispy.friends.friendid; -- --- TOC entry 3472 (class 0 OID 0) --- Dependencies: 214 --- Name: friends_friendid_seq; Type: SEQUENCE OWNED BY; Schema: unispy; Owner: - +-- Name: game_server_caches; Type: TABLE; Schema: unispy; Owner: unispy -- -ALTER SEQUENCE unispy.friends_friendid_seq OWNED BY unispy.friends.friendid; +CREATE TABLE unispy.game_server_caches ( + id SERIAL PRIMARY KEY NOT NULL, + instant_key character varying(10), + server_id uuid NOT NULL, + host_ip_address inet NOT NULL, + game_name character varying NOT NULL, + query_report_port integer NOT NULL, + update_time timestamp without time zone NOT NULL, + status smallint not NULL, + data jsonb NOT NULL, + avaliable boolean +); + + +ALTER TABLE unispy.game_server_caches OWNER TO unispy; + +-- +-- Name: game_server_caches_instant_key_seq; Type: SEQUENCE; Schema: unispy; Owner: unispy +-- + +-- CREATE SEQUENCE unispy.game_server_caches_instant_key_seq +-- AS integer +-- START WITH 1 +-- INCREMENT BY 1 +-- NO MINVALUE +-- NO MAXVALUE +-- CACHE 1; + + +-- ALTER TABLE unispy.game_server_caches_instant_key_seq OWNER TO unispy; + +-- +-- Name: game_server_caches_instant_key_seq; Type: SEQUENCE OWNED BY; Schema: unispy; Owner: unispy +-- + +-- ALTER SEQUENCE unispy.game_server_caches_instant_key_seq OWNED BY unispy.game_server_caches.instant_key; -- --- TOC entry 215 (class 1259 OID 16400) --- Name: games; Type: TABLE; Schema: unispy; Owner: - +-- Name: games; Type: TABLE; Schema: unispy; Owner: unispy -- CREATE TABLE unispy.games ( - gameid integer NOT NULL, + gameid integer PRIMARY KEY NOT NULL , gamename character varying NOT NULL, secretkey character varying, description character varying(4095) NOT NULL, @@ -190,337 +267,368 @@ CREATE TABLE unispy.games ( ); +ALTER TABLE unispy.games OWNER TO unispy; + -- --- TOC entry 3473 (class 0 OID 0) --- Dependencies: 215 --- Name: TABLE games; Type: COMMENT; Schema: unispy; Owner: - +-- Name: TABLE games; Type: COMMENT; Schema: unispy; Owner: unispy -- COMMENT ON TABLE unispy.games IS 'Game list.'; -- --- TOC entry 216 (class 1259 OID 16405) --- Name: grouplist; Type: TABLE; Schema: unispy; Owner: - +-- Name: grouplist; Type: TABLE; Schema: unispy; Owner: unispy -- CREATE TABLE unispy.grouplist ( - groupid integer NOT NULL, + groupid integer NOT NULL UNIQUE, gameid integer NOT NULL, roomname text NOT NULL ); +ALTER TABLE unispy.grouplist OWNER TO unispy; + -- --- TOC entry 3474 (class 0 OID 0) --- Dependencies: 216 --- Name: TABLE grouplist; Type: COMMENT; Schema: unispy; Owner: - +-- Name: TABLE grouplist; Type: COMMENT; Schema: unispy; Owner: unispy -- COMMENT ON TABLE unispy.grouplist IS 'Old games use grouplist to create their game rooms.'; -- --- TOC entry 217 (class 1259 OID 16410) --- Name: messages; Type: TABLE; Schema: unispy; Owner: - +-- Name: init_packet_caches; Type: TABLE; Schema: unispy; Owner: unispy +-- + +CREATE TABLE unispy.init_packet_caches ( + id SERIAL PRIMARY KEY NOT NULL, + cookie bigint NOT NULL, + server_id uuid NOT NULL, + version integer NOT NULL, + port_type smallint NOT NULL, + client_index smallint NOT NULL, + game_name character varying NOT NULL, + use_game_port boolean NOT NULL, + public_ip character varying NOT NULL, + public_port integer NOT NULL, + private_ip character varying NOT NULL, + private_port integer NOT NULL, + update_time timestamp without time zone NOT NULL +); + + +ALTER TABLE unispy.init_packet_caches OWNER TO unispy; + +-- +-- Name: init_packet_caches_cookie_seq; Type: SEQUENCE; Schema: unispy; Owner: unispy +-- + +-- CREATE SEQUENCE unispy.init_packet_caches_cookie_seq +-- AS integer +-- START WITH 1 +-- INCREMENT BY 1 +-- NO MINVALUE +-- NO MAXVALUE +-- CACHE 1; + + +-- ALTER TABLE unispy.init_packet_caches_cookie_seq OWNER TO unispy; + +-- +-- Name: init_packet_caches_cookie_seq; Type: SEQUENCE OWNED BY; Schema: unispy; Owner: unispy +-- + +-- ALTER SEQUENCE unispy.init_packet_caches_cookie_seq OWNED BY unispy.init_packet_caches.cookie; + + +-- +-- Name: messages; Type: TABLE; Schema: unispy; Owner: unispy -- CREATE TABLE unispy.messages ( - messageid integer NOT NULL, - namespaceid integer, + id SERIAL PRIMARY KEY NOT NULL, + namespaceid integer NOT NULL, type integer, - "from" integer NOT NULL, - "to" integer NOT NULL, - date timestamp without time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, - message character varying NOT NULL + from_user integer NOT NULL, + to_user integer NOT NULL, + date timestamp without time zone NOT NULL, + message text NOT NULL ); +ALTER TABLE unispy.messages OWNER TO unispy; + +-- +-- Name: messages_id_seq; Type: SEQUENCE; Schema: unispy; Owner: unispy +-- + +-- CREATE SEQUENCE unispy.messages_id_seq +-- AS integer +-- START WITH 1 +-- INCREMENT BY 1 +-- NO MINVALUE +-- NO MAXVALUE +-- CACHE 1; + + +ALTER TABLE unispy.messages_id_seq OWNER TO unispy; + -- --- TOC entry 3475 (class 0 OID 0) --- Dependencies: 217 --- Name: TABLE messages; Type: COMMENT; Schema: unispy; Owner: - +-- Name: messages_id_seq; Type: SEQUENCE OWNED BY; Schema: unispy; Owner: unispy -- -COMMENT ON TABLE unispy.messages IS 'Friend messages.'; +ALTER SEQUENCE unispy.messages_id_seq OWNED BY unispy.messages.id; -- --- TOC entry 218 (class 1259 OID 16416) --- Name: messages_messageid_seq; Type: SEQUENCE; Schema: unispy; Owner: - +-- Name: nat_result_caches; Type: TABLE; Schema: unispy; Owner: unispy -- -CREATE SEQUENCE unispy.messages_messageid_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; +CREATE TABLE unispy.nat_result_caches ( + id SERIAL PRIMARY KEY NOT NULL, + cookie smallint NOT NULL, + public_ip inet NOT NULL, + private_ip inet NOT NULL, + is_success boolean NOT NULL, + port_mapping_scheme smallint NOT NULL, + port_type smallint NOT NULL, + nat_type smallint NOT NULL, + client_index smallint NOT NULL, + game_name character varying NOT NULL, + update_time timestamp without time zone NOT NULL +); + +ALTER TABLE unispy.nat_result_caches OWNER TO unispy; -- --- TOC entry 3476 (class 0 OID 0) --- Dependencies: 218 --- Name: messages_messageid_seq; Type: SEQUENCE OWNED BY; Schema: unispy; Owner: - +-- Name: nat_result_caches_id_seq; Type: SEQUENCE; Schema: unispy; Owner: unispy -- -ALTER SEQUENCE unispy.messages_messageid_seq OWNED BY unispy.messages.messageid; +-- CREATE SEQUENCE unispy.nat_result_caches_id_seq +-- AS integer +-- START WITH 1 +-- INCREMENT BY 1 +-- NO MINVALUE +-- NO MAXVALUE +-- CACHE 1; +ALTER TABLE unispy.nat_result_caches_id_seq OWNER TO unispy; + -- --- TOC entry 219 (class 1259 OID 16417) --- Name: partner; Type: TABLE; Schema: unispy; Owner: - +-- Name: nat_result_caches_id_seq; Type: SEQUENCE OWNED BY; Schema: unispy; Owner: unispy +-- + +ALTER SEQUENCE unispy.nat_result_caches_id_seq OWNED BY unispy.nat_result_caches.id; + + +-- +-- Name: partner; Type: TABLE; Schema: unispy; Owner: unispy -- CREATE TABLE unispy.partner ( - partnerid integer NOT NULL, + partnerid SERIAL PRIMARY KEY, partnername character varying NOT NULL ); +ALTER TABLE unispy.partner OWNER TO unispy; + -- --- TOC entry 3477 (class 0 OID 0) --- Dependencies: 219 --- Name: TABLE partner; Type: COMMENT; Schema: unispy; Owner: - +-- Name: TABLE partner; Type: COMMENT; Schema: unispy; Owner: unispy -- COMMENT ON TABLE unispy.partner IS 'Partner information, these information are used for authentication and login.'; -- --- TOC entry 220 (class 1259 OID 16422) --- Name: profiles; Type: TABLE; Schema: unispy; Owner: - +-- Name: profiles; Type: TABLE; Schema: unispy; Owner: unispy -- CREATE TABLE unispy.profiles ( - profileid integer NOT NULL, + profileid SERIAL PRIMARY KEY NOT NULL, userid integer NOT NULL, - nick character varying NOT NULL, - serverflag integer DEFAULT 0 NOT NULL, - status smallint DEFAULT 0, - statstring character varying DEFAULT 'I love UniSpy'::character varying, - location character varying, - firstname character varying, - lastname character varying, - publicmask integer DEFAULT 0, - latitude double precision DEFAULT 0, - longitude double precision DEFAULT 0, - aim character varying DEFAULT ''::character varying, - picture integer DEFAULT 0, - occupationid integer DEFAULT 0, - incomeid integer DEFAULT 0, - industryid integer DEFAULT 0, - marriedid integer DEFAULT 0, - childcount integer DEFAULT 0, - interests1 integer DEFAULT 0, - ownership1 integer DEFAULT 0, - connectiontype integer DEFAULT 0, - sex smallint DEFAULT 0, - zipcode character varying DEFAULT '00000'::character varying, - countrycode character varying DEFAULT 1, - homepage character varying DEFAULT 'unispy.org'::character varying, - birthday integer DEFAULT 0, - birthmonth integer DEFAULT 0, - birthyear integer DEFAULT 0, - icquin integer DEFAULT 0, - quietflags smallint DEFAULT 0 NOT NULL, - streetaddr text, - streeaddr text, - city text, - cpubrandid integer DEFAULT 0, - cpuspeed integer DEFAULT 0, - memory smallint DEFAULT 0, - videocard1string text, - videocard1ram smallint DEFAULT 0, - videocard2string text, - videocard2ram smallint DEFAULT 0, - subscription integer DEFAULT 0, - adminrights integer DEFAULT 0 + nick character varying NOT NULL UNIQUE, + serverflag integer NOT NULL, + status smallint not NULL, + statstring character varying, + extra_info jsonb ); +-- FOREIGN key (userid) REFERENCES unispy.users (user_id) on delete cascade --- --- TOC entry 3478 (class 0 OID 0) --- Dependencies: 220 --- Name: TABLE profiles; Type: COMMENT; Schema: unispy; Owner: - --- - -COMMENT ON TABLE unispy.profiles IS 'User profiles.'; - +ALTER TABLE unispy.profiles OWNER TO unispy; -- --- TOC entry 221 (class 1259 OID 16459) --- Name: profiles_profileid_seq; Type: SEQUENCE; Schema: unispy; Owner: - +-- Name: profiles_profileid_seq; Type: SEQUENCE; Schema: unispy; Owner: unispy -- -CREATE SEQUENCE unispy.profiles_profileid_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; +-- CREATE SEQUENCE unispy.profiles_profileid_seq +-- AS integer +-- START WITH 1 +-- INCREMENT BY 1 +-- NO MINVALUE +-- NO MAXVALUE +-- CACHE 1; +ALTER TABLE unispy.profiles_profileid_seq OWNER TO unispy; + -- --- TOC entry 3479 (class 0 OID 0) --- Dependencies: 221 --- Name: profiles_profileid_seq; Type: SEQUENCE OWNED BY; Schema: unispy; Owner: - +-- Name: profiles_profileid_seq; Type: SEQUENCE OWNED BY; Schema: unispy; Owner: unispy -- ALTER SEQUENCE unispy.profiles_profileid_seq OWNED BY unispy.profiles.profileid; -- --- TOC entry 222 (class 1259 OID 16460) --- Name: pstorage; Type: TABLE; Schema: unispy; Owner: - +-- Name: pstorage; Type: TABLE; Schema: unispy; Owner: unispy -- CREATE TABLE unispy.pstorage ( - pstorageid integer NOT NULL, + id SERIAL PRIMARY KEY NOT NULL, profileid integer NOT NULL, ptype integer NOT NULL, dindex integer NOT NULL, - data jsonb + data character varying NOT NULL, + update_time timestamp without time zone NOT NULL ); +ALTER TABLE unispy.pstorage OWNER TO unispy; + -- --- TOC entry 3480 (class 0 OID 0) --- Dependencies: 222 --- Name: TABLE pstorage; Type: COMMENT; Schema: unispy; Owner: - +-- Name: pstorage_id_seq; Type: SEQUENCE; Schema: unispy; Owner: unispy -- -COMMENT ON TABLE unispy.pstorage IS 'Old games use pstorage to store game data.'; +-- CREATE SEQUENCE unispy.pstorage_id_seq +-- AS integer +-- START WITH 1 +-- INCREMENT BY 1 +-- NO MINVALUE +-- NO MAXVALUE +-- CACHE 1; + +ALTER TABLE unispy.pstorage_id_seq OWNER TO unispy; -- --- TOC entry 223 (class 1259 OID 16465) --- Name: pstorage_pstorageid_seq; Type: SEQUENCE; Schema: unispy; Owner: - +-- Name: pstorage_id_seq; Type: SEQUENCE OWNED BY; Schema: unispy; Owner: unispy -- -CREATE SEQUENCE unispy.pstorage_pstorageid_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; +ALTER SEQUENCE unispy.pstorage_id_seq OWNED BY unispy.pstorage.id; -- --- TOC entry 3481 (class 0 OID 0) --- Dependencies: 223 --- Name: pstorage_pstorageid_seq; Type: SEQUENCE OWNED BY; Schema: unispy; Owner: - +-- Name: relay_server_caches; Type: TABLE; Schema: unispy; Owner: unispy -- -ALTER SEQUENCE unispy.pstorage_pstorageid_seq OWNED BY unispy.pstorage.pstorageid; +CREATE TABLE unispy.relay_server_caches ( + id SERIAL PRIMARY KEY NOT NULL, + server_id uuid NOT NULL, + public_ip character varying NOT NULL, + public_port integer NOT NULL, + client_count integer NOT NULL, + update_time timestamp without time zone NOT NULL +); + +ALTER TABLE unispy.relay_server_caches OWNER TO unispy; -- --- TOC entry 224 (class 1259 OID 16466) --- Name: sakestorage; Type: TABLE; Schema: unispy; Owner: - +-- Name: sakestorage; Type: TABLE; Schema: unispy; Owner: unispy -- CREATE TABLE unispy.sakestorage ( - sakestorageid integer NOT NULL, - tableid character varying NOT NULL + id SERIAL PRIMARY KEY NOT NULL, + tableid integer NOT NULL, + data jsonb ); +ALTER TABLE unispy.sakestorage OWNER TO unispy; + -- --- TOC entry 3482 (class 0 OID 0) --- Dependencies: 224 --- Name: TABLE sakestorage; Type: COMMENT; Schema: unispy; Owner: - +-- Name: TABLE sakestorage; Type: COMMENT; Schema: unispy; Owner: unispy -- COMMENT ON TABLE unispy.sakestorage IS 'Sake storage system.'; -- --- TOC entry 225 (class 1259 OID 16471) --- Name: sakestorage_sakestorageid_seq; Type: SEQUENCE; Schema: unispy; Owner: - +-- Name: sakestorage_id_seq; Type: SEQUENCE; Schema: unispy; Owner: unispy -- -CREATE SEQUENCE unispy.sakestorage_sakestorageid_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; +-- CREATE SEQUENCE unispy.sakestorage_id_seq +-- AS integer +-- START WITH 1 +-- INCREMENT BY 1 +-- NO MINVALUE +-- NO MAXVALUE +-- CACHE 1; +ALTER TABLE unispy.sakestorage_id_seq OWNER TO unispy; + -- --- TOC entry 3483 (class 0 OID 0) --- Dependencies: 225 --- Name: sakestorage_sakestorageid_seq; Type: SEQUENCE OWNED BY; Schema: unispy; Owner: - +-- Name: sakestorage_id_seq; Type: SEQUENCE OWNED BY; Schema: unispy; Owner: unispy -- -ALTER SEQUENCE unispy.sakestorage_sakestorageid_seq OWNED BY unispy.sakestorage.sakestorageid; +ALTER SEQUENCE unispy.sakestorage_id_seq OWNED BY unispy.sakestorage.id; -- --- TOC entry 226 (class 1259 OID 16472) --- Name: subprofiles; Type: TABLE; Schema: unispy; Owner: - +-- Name: subprofiles; Type: TABLE; Schema: unispy; Owner: unispy -- CREATE TABLE unispy.subprofiles ( - subprofileid integer NOT NULL, + subprofileid SERIAL PRIMARY KEY NOT NULL, profileid integer NOT NULL, uniquenick character varying, - namespaceid integer DEFAULT 0 NOT NULL, - partnerid integer DEFAULT 0 NOT NULL, + namespaceid integer NOT NULL, + partnerid integer NOT NULL, productid integer, gamename text, cdkeyenc character varying, - firewall smallint DEFAULT 0, - port integer DEFAULT 0, - authtoken character varying + firewall smallint, + port integer, + authtoken character varying, + session_key character varying ); --- --- TOC entry 3484 (class 0 OID 0) --- Dependencies: 226 --- Name: TABLE subprofiles; Type: COMMENT; Schema: unispy; Owner: - --- - -COMMENT ON TABLE unispy.subprofiles IS 'User subprofiles.'; - +ALTER TABLE unispy.subprofiles OWNER TO unispy; -- --- TOC entry 227 (class 1259 OID 16481) --- Name: subprofiles_subprofileid_seq; Type: SEQUENCE; Schema: unispy; Owner: - +-- Name: subprofiles_subprofileid_seq; Type: SEQUENCE; Schema: unispy; Owner: unispy -- -CREATE SEQUENCE unispy.subprofiles_subprofileid_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; +-- CREATE SEQUENCE unispy.subprofiles_subprofileid_seq +-- AS integer +-- START WITH 1 +-- INCREMENT BY 1 +-- NO MINVALUE +-- NO MAXVALUE +-- CACHE 1; +ALTER TABLE unispy.subprofiles_subprofileid_seq OWNER TO unispy; + -- --- TOC entry 3485 (class 0 OID 0) --- Dependencies: 227 --- Name: subprofiles_subprofileid_seq; Type: SEQUENCE OWNED BY; Schema: unispy; Owner: - +-- Name: subprofiles_subprofileid_seq; Type: SEQUENCE OWNED BY; Schema: unispy; Owner: unispy -- ALTER SEQUENCE unispy.subprofiles_subprofileid_seq OWNED BY unispy.subprofiles.subprofileid; -- --- TOC entry 228 (class 1259 OID 16482) --- Name: users; Type: TABLE; Schema: unispy; Owner: - +-- Name: users; Type: TABLE; Schema: unispy; Owner: unispy -- CREATE TABLE unispy.users ( - userid integer NOT NULL, - email character varying NOT NULL, + userid serial primary key, + email character varying NOT NULL UNIQUE, password character varying NOT NULL, emailverified boolean DEFAULT true NOT NULL, lastip inet, @@ -531,124 +639,131 @@ CREATE TABLE unispy.users ( ); +ALTER TABLE unispy.users OWNER TO unispy; + -- --- TOC entry 3486 (class 0 OID 0) --- Dependencies: 228 --- Name: TABLE users; Type: COMMENT; Schema: unispy; Owner: - +-- Name: TABLE users; Type: COMMENT; Schema: unispy; Owner: unispy -- COMMENT ON TABLE unispy.users IS 'User account information.'; -- --- TOC entry 229 (class 1259 OID 16492) --- Name: users_userid_seq; Type: SEQUENCE; Schema: unispy; Owner: - +-- Name: users_userid_seq; Type: SEQUENCE; Schema: unispy; Owner: unispy -- -CREATE SEQUENCE unispy.users_userid_seq - AS integer - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; +-- CREATE SEQUENCE unispy.users_userid_seq +-- AS integer +-- START WITH 1 +-- INCREMENT BY 1 +-- NO MINVALUE +-- NO MAXVALUE +-- CACHE 1; + +ALTER TABLE unispy.users_userid_seq OWNER TO unispy; -- --- TOC entry 3487 (class 0 OID 0) --- Dependencies: 229 --- Name: users_userid_seq; Type: SEQUENCE OWNED BY; Schema: unispy; Owner: - +-- Name: users_userid_seq; Type: SEQUENCE OWNED BY; Schema: unispy; Owner: unispy -- ALTER SEQUENCE unispy.users_userid_seq OWNED BY unispy.users.userid; -- --- TOC entry 3219 (class 2604 OID 16493) --- Name: addrequests addrequestid; Type: DEFAULT; Schema: unispy; Owner: - +-- Name: addrequests addrequestid; Type: DEFAULT; Schema: unispy; Owner: unispy -- ALTER TABLE ONLY unispy.addrequests ALTER COLUMN addrequestid SET DEFAULT nextval('unispy.addrequests_addrequestid_seq'::regclass); -- --- TOC entry 3220 (class 2604 OID 16494) --- Name: blocked blockid; Type: DEFAULT; Schema: unispy; Owner: - +-- Name: blocked blockid; Type: DEFAULT; Schema: unispy; Owner: unispy -- ALTER TABLE ONLY unispy.blocked ALTER COLUMN blockid SET DEFAULT nextval('unispy.blocked_blockid_seq'::regclass); -- --- TOC entry 3221 (class 2604 OID 16495) --- Name: friends friendid; Type: DEFAULT; Schema: unispy; Owner: - +-- Name: friends friendid; Type: DEFAULT; Schema: unispy; Owner: unispy -- -ALTER TABLE ONLY unispy.friends ALTER COLUMN friendid SET DEFAULT nextval('unispy.friends_friendid_seq'::regclass); +-- ALTER TABLE ONLY unispy.friends ALTER COLUMN friendid SET DEFAULT nextval('unispy.friends_friendid_seq'::regclass); -- --- TOC entry 3223 (class 2604 OID 16496) --- Name: messages messageid; Type: DEFAULT; Schema: unispy; Owner: - +-- Name: game_server_caches instant_key; Type: DEFAULT; Schema: unispy; Owner: unispy -- -ALTER TABLE ONLY unispy.messages ALTER COLUMN messageid SET DEFAULT nextval('unispy.messages_messageid_seq'::regclass); +-- ALTER TABLE ONLY unispy.game_server_caches ALTER COLUMN instant_key SET DEFAULT nextval('unispy.game_server_caches_instant_key_seq'::regclass); -- --- TOC entry 3256 (class 2604 OID 16497) --- Name: profiles profileid; Type: DEFAULT; Schema: unispy; Owner: - +-- Name: init_packet_caches cookie; Type: DEFAULT; Schema: unispy; Owner: unispy +-- + +-- ALTER TABLE ONLY unispy.init_packet_caches ALTER COLUMN cookie SET DEFAULT nextval('unispy.init_packet_caches_cookie_seq'::regclass); + + +-- +-- Name: messages id; Type: DEFAULT; Schema: unispy; Owner: unispy +-- + +ALTER TABLE ONLY unispy.messages ALTER COLUMN id SET DEFAULT nextval('unispy.messages_id_seq'::regclass); + + +-- +-- Name: nat_result_caches id; Type: DEFAULT; Schema: unispy; Owner: unispy +-- + +ALTER TABLE ONLY unispy.nat_result_caches ALTER COLUMN id SET DEFAULT nextval('unispy.nat_result_caches_id_seq'::regclass); + + +-- +-- Name: profiles profileid; Type: DEFAULT; Schema: unispy; Owner: unispy -- ALTER TABLE ONLY unispy.profiles ALTER COLUMN profileid SET DEFAULT nextval('unispy.profiles_profileid_seq'::regclass); -- --- TOC entry 3257 (class 2604 OID 16498) --- Name: pstorage pstorageid; Type: DEFAULT; Schema: unispy; Owner: - +-- Name: pstorage id; Type: DEFAULT; Schema: unispy; Owner: unispy -- -ALTER TABLE ONLY unispy.pstorage ALTER COLUMN pstorageid SET DEFAULT nextval('unispy.pstorage_pstorageid_seq'::regclass); +ALTER TABLE ONLY unispy.pstorage ALTER COLUMN id SET DEFAULT nextval('unispy.pstorage_id_seq'::regclass); -- --- TOC entry 3258 (class 2604 OID 16499) --- Name: sakestorage sakestorageid; Type: DEFAULT; Schema: unispy; Owner: - +-- Name: sakestorage id; Type: DEFAULT; Schema: unispy; Owner: unispy -- -ALTER TABLE ONLY unispy.sakestorage ALTER COLUMN sakestorageid SET DEFAULT nextval('unispy.sakestorage_sakestorageid_seq'::regclass); +ALTER TABLE ONLY unispy.sakestorage ALTER COLUMN id SET DEFAULT nextval('unispy.sakestorage_id_seq'::regclass); -- --- TOC entry 3263 (class 2604 OID 16500) --- Name: subprofiles subprofileid; Type: DEFAULT; Schema: unispy; Owner: - +-- Name: subprofiles subprofileid; Type: DEFAULT; Schema: unispy; Owner: unispy -- ALTER TABLE ONLY unispy.subprofiles ALTER COLUMN subprofileid SET DEFAULT nextval('unispy.subprofiles_subprofileid_seq'::regclass); -- --- TOC entry 3269 (class 2604 OID 16501) --- Name: users userid; Type: DEFAULT; Schema: unispy; Owner: - +-- Name: users userid; Type: DEFAULT; Schema: unispy; Owner: unispy -- ALTER TABLE ONLY unispy.users ALTER COLUMN userid SET DEFAULT nextval('unispy.users_userid_seq'::regclass); -- --- TOC entry 3440 (class 0 OID 16386) --- Dependencies: 209 --- Data for Name: addrequests; Type: TABLE DATA; Schema: unispy; Owner: - +-- Data for Name: addrequests; Type: TABLE DATA; Schema: unispy; Owner: unispy -- -COPY unispy.addrequests (addrequestid, profileid, namespaceid, targetid, reason, syncrequested) FROM stdin; +COPY unispy.addrequests (addrequestid, profileid, targetid, namespaceid, reason, status) FROM stdin; \. -- --- TOC entry 3442 (class 0 OID 16392) --- Dependencies: 211 --- Data for Name: blocked; Type: TABLE DATA; Schema: unispy; Owner: - +-- Data for Name: blocked; Type: TABLE DATA; Schema: unispy; Owner: unispy -- COPY unispy.blocked (blockid, profileid, namespaceid, targetid) FROM stdin; @@ -656,19 +771,47 @@ COPY unispy.blocked (blockid, profileid, namespaceid, targetid) FROM stdin; -- --- TOC entry 3444 (class 0 OID 16396) --- Dependencies: 213 --- Data for Name: friends; Type: TABLE DATA; Schema: unispy; Owner: - +-- Data for Name: chat_channel_caches; Type: TABLE DATA; Schema: unispy; Owner: unispy +-- + +COPY unispy.chat_channel_caches (channel_name, server_id, game_name, room_name, topic, password, group_id, max_num_user, key_values, invited_nicks, update_time) FROM stdin; +\. + + +-- +-- Data for Name: chat_nick_caches; Type: TABLE DATA; Schema: unispy; Owner: unispy +-- + +COPY unispy.chat_user_caches (server_id, nick_name, game_name, user_name, remote_ip, remote_port,websocket_address, key_value, update_time) FROM stdin; +\. + + +-- +-- Data for Name: chat_user_caches; Type: TABLE DATA; Schema: unispy; Owner: unispy +-- + +COPY unispy.chat_channel_user_caches (nick_name, channel_name, server_id, user_name, update_time, is_voiceable, is_channel_operator, is_channel_creator, remote_ip, remote_port, key_values) FROM stdin; +\. + + +-- +-- Data for Name: friends; Type: TABLE DATA; Schema: unispy; Owner: unispy +-- + +COPY unispy.friends (friendid, profileid, targetid, namespaceid) FROM stdin; +\. + + +-- +-- Data for Name: game_server_caches; Type: TABLE DATA; Schema: unispy; Owner: unispy -- -COPY unispy.friends (friendid, profileid, namespaceid, targetid) FROM stdin; +COPY unispy.game_server_caches (instant_key, server_id, host_ip_address, game_name, query_report_port, update_time, status, data, avaliable) FROM stdin; \. -- --- TOC entry 3446 (class 0 OID 16400) --- Dependencies: 215 --- Data for Name: games; Type: TABLE DATA; Schema: unispy; Owner: - +-- Data for Name: games; Type: TABLE DATA; Schema: unispy; Owner: unispy -- COPY unispy.games (gameid, gamename, secretkey, description, disabled) FROM stdin; @@ -1671,6 +1814,7 @@ COPY unispy.games (gameid, gamename, secretkey, description, disabled) FROM stdi 1313 marvlegpc eAMh9M Marvel Legends (PC) f 1315 marvlegpcd \N Marvel Legends Demo (PC) f 1318 hustleps2am \N Hustle: Detroit Streets Automatch (PS2) f +2832 bädmasterid \N bädmasterid f 1317 hustleps2 ni9hdV Hustle: Detroit Streets (PS2) f 1342 ffurtdriftps2am \N The Fast and the Furious: Tokyo Drift Automatch (PS2) f 1320 koshien2ds UKdPFf PowerPro Pocket Koshien 2 (DS) f @@ -2271,6 +2415,7 @@ COPY unispy.games (gameid, gamename, secretkey, description, disabled) FROM stdi 2018 cvania08ds SwO9Jn Castlevania 2008 (DS) f 2019 nplusds qX9Muy N+ (DS) f 2020 gauntletds wUq7fL Gauntlet (DS) f +2935 DeathtoSpies LOhgNO Death to Spies f 2021 finertiaps3 3vEcPe Fatal Inertia (PS3) f 2029 tpfolEUpcd \N Turning Point: Fall of Liberty Demo (EU) (PC) f 2023 topspin3usds 8R4LgD Top Spin 3 (US) (DS) f @@ -2961,7 +3106,6 @@ COPY unispy.games (gameid, gamename, secretkey, description, disabled) FROM stdi 2817 maxpayne3x360am \N Max Payne 3 Automatch (360) f 2816 maxpayne3x360 28xd4T Max Payne 3 (360) f 2818 maxpayne3x360d \N Max Payne 3 Demo (360) f -2832 bädmasterid \N bädmasterid f 2819 wordjongeuds 3rwTkL Wordjong EU (DS) f 2820 sengo3wii Esqv7G Sengokumuso 3 f 2821 bewarewii iTHrhz Beware (WiiWare) f @@ -3062,7 +3206,6 @@ COPY unispy.games (gameid, gamename, secretkey, description, disabled) FROM stdi 2937 svsr11x360devam \N Smackdown vs Raw 2011 DEV Automatch (x360) f 2932 girlskoreads QiFGmi Girls_Korea (DS) f 2934 protocolwii Hd4g3T Protocol (WiiWare) f -2935 DeathtoSpies LOhgNO Death to Spies f 2936 svsr11x360dev h5DZhP Smackdown vs Raw 2011 DEV (x360) f 2939 svsr11ps3devam \N Smackdown vs Raw 2011 DEV Automatch (PS3) f 2938 svsr11ps3dev gSTArg Smackdown vs Raw 2011 DEV (PS3) f @@ -3475,9 +3618,7 @@ COPY unispy.games (gameid, gamename, secretkey, description, disabled) FROM stdi -- --- TOC entry 3447 (class 0 OID 16405) --- Dependencies: 216 --- Data for Name: grouplist; Type: TABLE DATA; Schema: unispy; Owner: - +-- Data for Name: grouplist; Type: TABLE DATA; Schema: unispy; Owner: unispy -- COPY unispy.grouplist (groupid, gameid, roomname) FROM stdin; @@ -5176,311 +5317,180 @@ COPY unispy.grouplist (groupid, gameid, roomname) FROM stdin; -- --- TOC entry 3448 (class 0 OID 16410) --- Dependencies: 217 --- Data for Name: messages; Type: TABLE DATA; Schema: unispy; Owner: - +-- Data for Name: init_packet_caches; Type: TABLE DATA; Schema: unispy; Owner: unispy -- -COPY unispy.messages (messageid, namespaceid, type, "from", "to", date, message) FROM stdin; +COPY unispy.init_packet_caches (cookie, server_id, version, port_type, client_index, game_name, use_game_port, public_ip, public_port, private_ip, private_port, update_time) FROM stdin; \. -- --- TOC entry 3450 (class 0 OID 16417) --- Dependencies: 219 --- Data for Name: partner; Type: TABLE DATA; Schema: unispy; Owner: - +-- Data for Name: messages; Type: TABLE DATA; Schema: unispy; Owner: unispy -- -COPY unispy.partner (partnerid, partnername) FROM stdin; -0 UniSpy -95 Crytek +COPY unispy.messages (id, namespaceid, type, from_user, to_user, date, message) FROM stdin; \. -- --- TOC entry 3451 (class 0 OID 16422) --- Dependencies: 220 --- Data for Name: profiles; Type: TABLE DATA; Schema: unispy; Owner: - +-- Data for Name: nat_result_caches; Type: TABLE DATA; Schema: unispy; Owner: unispy -- -COPY unispy.profiles (profileid, userid, nick, serverflag, status, statstring, location, firstname, lastname, publicmask, latitude, longitude, aim, picture, occupationid, incomeid, industryid, marriedid, childcount, interests1, ownership1, connectiontype, sex, zipcode, countrycode, homepage, birthday, birthmonth, birthyear, icquin, quietflags, streetaddr, streeaddr, city, cpubrandid, cpuspeed, memory, videocard1string, videocard1ram, videocard2string, videocard2ram, subscription, adminrights) FROM stdin; -1 1 spyguy 0 0 I love UniSpy earth spy guy 0 0 0 0 0 0 0 0 0 0 0 0 0 00000 1 unispy.org 0 0 0 0 0 \N \N \N 0 0 0 \N 0 \N 0 0 0 -2 2 uniguy 0 0 I love UniSpy earth uni guy 0 0 0 0 0 0 0 0 0 0 0 0 0 00000 1 unispy.org 0 0 0 0 0 \N \N \N 0 0 0 \N 0 \N 0 0 0 -3 3 gptest1 0 0 I love UniSpy \N \N \N 0 0 0 0 0 0 0 0 0 0 0 0 0 00000 1 unispy.org 0 0 0 0 0 \N \N \N 0 0 0 \N 0 \N 0 0 0 -4 4 gptest2 0 0 I love UniSpy \N \N \N 0 0 0 0 0 0 0 0 0 0 0 0 0 00000 1 unispy.org 0 0 0 0 0 \N \N \N 0 0 0 \N 0 \N 0 0 0 -5 5 gptest3 0 0 I love UniSpy \N \N \N 0 0 0 0 0 0 0 0 0 0 0 0 0 00000 1 unispy.org 0 0 0 0 0 \N \N \N 0 0 0 \N 0 \N 0 0 0 +COPY unispy.nat_result_caches (id, public_ip, private_ip, is_success, port_mapping_scheme, port_type, client_index, game_name, update_time) FROM stdin; \. -- --- TOC entry 3453 (class 0 OID 16460) --- Dependencies: 222 --- Data for Name: pstorage; Type: TABLE DATA; Schema: unispy; Owner: - +-- Data for Name: partner; Type: TABLE DATA; Schema: unispy; Owner: unispy -- -COPY unispy.pstorage (pstorageid, profileid, ptype, dindex, data) FROM stdin; +COPY unispy.partner (partnerid, partnername) FROM stdin; +0 UniSpy +95 Crytek \. -- --- TOC entry 3455 (class 0 OID 16466) --- Dependencies: 224 --- Data for Name: sakestorage; Type: TABLE DATA; Schema: unispy; Owner: - +-- Data for Name: profiles; Type: TABLE DATA; Schema: unispy; Owner: unispy -- -COPY unispy.sakestorage (sakestorageid, tableid) FROM stdin; +COPY unispy.profiles (profileid, userid, nick, serverflag, status, statstring, extra_info) FROM stdin; +1 1 spyguy 0 0 I love UniSpy {} \. -- --- TOC entry 3457 (class 0 OID 16472) --- Dependencies: 226 --- Data for Name: subprofiles; Type: TABLE DATA; Schema: unispy; Owner: - +-- Data for Name: pstorage; Type: TABLE DATA; Schema: unispy; Owner: unispy -- -COPY unispy.subprofiles (subprofileid, profileid, uniquenick, namespaceid, partnerid, productid, gamename, cdkeyenc, firewall, port, authtoken) FROM stdin; -1 1 spyguy 1 0 0 gmtest \N 0 0 example_token -2 2 uniguy 1 0 0 gmtest \N 0 0 \N -3 3 gptest1 1 0 0 gmtest \N 0 0 \N -4 4 gptest2 1 0 0 gmtest \N 0 0 \N -5 5 gptest3 1 0 0 gmtest \N 0 0 \N +COPY unispy.pstorage (id, profileid, ptype, dindex, data) FROM stdin; \. -- --- TOC entry 3459 (class 0 OID 16482) --- Dependencies: 228 --- Data for Name: users; Type: TABLE DATA; Schema: unispy; Owner: - +-- Data for Name: relay_server_caches; Type: TABLE DATA; Schema: unispy; Owner: unispy -- -COPY unispy.users (userid, email, password, emailverified, lastip, lastonline, createddate, banned, deleted) FROM stdin; -1 spyguy@gamespy.com 4a7d1ed414474e4033ac29ccb8653d9b t \N 2022-01-19 20:01:49.828006 2022-01-19 20:01:49.828006 f f -2 uni@unispy.org 4a7d1ed414474e4033ac29ccb8653d9b t \N 2022-01-19 20:02:57.595514 2022-01-19 20:02:57.595514 f f -3 gptestc1@gptestc.com c6d525669e64438c9aa156a0cc80cd14 t \N 2022-01-19 20:03:44.754069 2022-01-19 20:03:44.754069 f f -4 gptestc2@gptestc.com c6d525669e64438c9aa156a0cc80cd14 t \N 2022-01-19 20:03:44.761986 2022-01-19 20:03:44.761986 f f -5 gptestc3@gptestc.com c6d525669e64438c9aa156a0cc80cd14 t \N 2022-01-19 20:03:44.764527 2022-01-19 20:03:44.764527 f f +COPY unispy.relay_server_caches (id, public_ip, public_port, client_count, update_time) FROM stdin; \. -- --- TOC entry 3488 (class 0 OID 0) --- Dependencies: 210 --- Name: addrequests_addrequestid_seq; Type: SEQUENCE SET; Schema: unispy; Owner: - --- - -SELECT pg_catalog.setval('unispy.addrequests_addrequestid_seq', 1, false); - - --- --- TOC entry 3489 (class 0 OID 0) --- Dependencies: 212 --- Name: blocked_blockid_seq; Type: SEQUENCE SET; Schema: unispy; Owner: - +-- Data for Name: sakestorage; Type: TABLE DATA; Schema: unispy; Owner: unispy -- -SELECT pg_catalog.setval('unispy.blocked_blockid_seq', 1, false); - - --- --- TOC entry 3490 (class 0 OID 0) --- Dependencies: 214 --- Name: friends_friendid_seq; Type: SEQUENCE SET; Schema: unispy; Owner: - --- - -SELECT pg_catalog.setval('unispy.friends_friendid_seq', 1, false); - - --- --- TOC entry 3491 (class 0 OID 0) --- Dependencies: 218 --- Name: messages_messageid_seq; Type: SEQUENCE SET; Schema: unispy; Owner: - --- - -SELECT pg_catalog.setval('unispy.messages_messageid_seq', 1, false); - - --- --- TOC entry 3492 (class 0 OID 0) --- Dependencies: 221 --- Name: profiles_profileid_seq; Type: SEQUENCE SET; Schema: unispy; Owner: - --- - -SELECT pg_catalog.setval('unispy.profiles_profileid_seq', 5, true); - - --- --- TOC entry 3493 (class 0 OID 0) --- Dependencies: 223 --- Name: pstorage_pstorageid_seq; Type: SEQUENCE SET; Schema: unispy; Owner: - --- - -SELECT pg_catalog.setval('unispy.pstorage_pstorageid_seq', 1, true); - - --- --- TOC entry 3494 (class 0 OID 0) --- Dependencies: 225 --- Name: sakestorage_sakestorageid_seq; Type: SEQUENCE SET; Schema: unispy; Owner: - --- - -SELECT pg_catalog.setval('unispy.sakestorage_sakestorageid_seq', 1, false); - - --- --- TOC entry 3495 (class 0 OID 0) --- Dependencies: 227 --- Name: subprofiles_subprofileid_seq; Type: SEQUENCE SET; Schema: unispy; Owner: - --- - -SELECT pg_catalog.setval('unispy.subprofiles_subprofileid_seq', 5, true); - - --- --- TOC entry 3496 (class 0 OID 0) --- Dependencies: 229 --- Name: users_userid_seq; Type: SEQUENCE SET; Schema: unispy; Owner: - --- - -SELECT pg_catalog.setval('unispy.users_userid_seq', 5, true); - - --- --- TOC entry 3271 (class 2606 OID 16503) --- Name: addrequests addrequests_pk; Type: CONSTRAINT; Schema: unispy; Owner: - --- - -ALTER TABLE ONLY unispy.addrequests - ADD CONSTRAINT addrequests_pk PRIMARY KEY (addrequestid); +COPY unispy.sakestorage (id, tableid, data) FROM stdin; +\. -- --- TOC entry 3273 (class 2606 OID 16505) --- Name: blocked blocked_pk; Type: CONSTRAINT; Schema: unispy; Owner: - +-- Data for Name: subprofiles; Type: TABLE DATA; Schema: unispy; Owner: unispy -- -ALTER TABLE ONLY unispy.blocked - ADD CONSTRAINT blocked_pk PRIMARY KEY (blockid); +COPY unispy.subprofiles (subprofileid, profileid, uniquenick, namespaceid, partnerid, productid, gamename, cdkeyenc, firewall, port, authtoken, session_key) FROM stdin; +1 1 spyguy 0 1 1 gmtests 00000a308fd86a7eb92cbc8322b03a36 0 8080 example_auth 1111 +\. -- --- TOC entry 3275 (class 2606 OID 16507) --- Name: friends friends_pk; Type: CONSTRAINT; Schema: unispy; Owner: - +-- Data for Name: users; Type: TABLE DATA; Schema: unispy; Owner: unispy -- -ALTER TABLE ONLY unispy.friends - ADD CONSTRAINT friends_pk PRIMARY KEY (friendid); +COPY unispy.users (userid, email, password, emailverified, lastip, lastonline, createddate, banned, deleted) FROM stdin; +1 spyguy@gamespy.com 4a7d1ed414474e4033ac29ccb8653d9b t \N 2022-01-19 20:01:49.828006 2022-01-19 20:01:49.828006 f f +2 uni@unispy.org 4a7d1ed414474e4033ac29ccb8653d9b t \N 2022-01-19 20:02:57.595514 2022-01-19 20:02:57.595514 f f +3 gptestc1@gptestc.com c6d525669e64438c9aa156a0cc80cd14 t \N 2022-01-19 20:03:44.754069 2022-01-19 20:03:44.754069 f f +4 gptestc2@gptestc.com c6d525669e64438c9aa156a0cc80cd14 t \N 2022-01-19 20:03:44.761986 2022-01-19 20:03:44.761986 f f +5 gptestc3@gptestc.com c6d525669e64438c9aa156a0cc80cd14 t \N 2022-01-19 20:03:44.764527 2022-01-19 20:03:44.764527 f f +\. -- --- TOC entry 3277 (class 2606 OID 16509) --- Name: games games_pk; Type: CONSTRAINT; Schema: unispy; Owner: - +-- Name: addrequests_addrequestid_seq; Type: SEQUENCE SET; Schema: unispy; Owner: unispy -- -ALTER TABLE ONLY unispy.games - ADD CONSTRAINT games_pk PRIMARY KEY (gameid); +SELECT pg_catalog.setval('unispy.addrequests_addrequestid_seq', 1, false); -- --- TOC entry 3279 (class 2606 OID 16511) --- Name: grouplist grouplist_pk; Type: CONSTRAINT; Schema: unispy; Owner: - +-- Name: blocked_blockid_seq; Type: SEQUENCE SET; Schema: unispy; Owner: unispy -- -ALTER TABLE ONLY unispy.grouplist - ADD CONSTRAINT grouplist_pk PRIMARY KEY (groupid); +SELECT pg_catalog.setval('unispy.blocked_blockid_seq', 1, false); -- --- TOC entry 3281 (class 2606 OID 16513) --- Name: messages messages_pk; Type: CONSTRAINT; Schema: unispy; Owner: - +-- Name: friends_friendid_seq; Type: SEQUENCE SET; Schema: unispy; Owner: unispy -- -ALTER TABLE ONLY unispy.messages - ADD CONSTRAINT messages_pk PRIMARY KEY (messageid); +SELECT pg_catalog.setval('unispy.friends_friendid_seq', 1, false); -- --- TOC entry 3283 (class 2606 OID 16515) --- Name: partner partner_pk; Type: CONSTRAINT; Schema: unispy; Owner: - +-- Name: game_server_caches_instant_key_seq; Type: SEQUENCE SET; Schema: unispy; Owner: unispy -- -ALTER TABLE ONLY unispy.partner - ADD CONSTRAINT partner_pk PRIMARY KEY (partnerid); +-- SELECT pg_catalog.setval('unispy.game_server_caches_instant_key_seq', 1, false); -- --- TOC entry 3285 (class 2606 OID 16517) --- Name: profiles profiles_pk; Type: CONSTRAINT; Schema: unispy; Owner: - +-- Name: init_packet_caches_cookie_seq; Type: SEQUENCE SET; Schema: unispy; Owner: unispy -- -ALTER TABLE ONLY unispy.profiles - ADD CONSTRAINT profiles_pk PRIMARY KEY (profileid); +-- SELECT pg_catalog.setval('unispy.init_packet_caches_cookie_seq', 1, false); -- --- TOC entry 3287 (class 2606 OID 16519) --- Name: pstorage pstorage_pk; Type: CONSTRAINT; Schema: unispy; Owner: - +-- Name: messages_id_seq; Type: SEQUENCE SET; Schema: unispy; Owner: unispy -- -ALTER TABLE ONLY unispy.pstorage - ADD CONSTRAINT pstorage_pk PRIMARY KEY (pstorageid); +SELECT pg_catalog.setval('unispy.messages_id_seq', 1, false); -- --- TOC entry 3289 (class 2606 OID 16521) --- Name: sakestorage sakestorage_pk; Type: CONSTRAINT; Schema: unispy; Owner: - +-- Name: nat_result_caches_id_seq; Type: SEQUENCE SET; Schema: unispy; Owner: unispy -- -ALTER TABLE ONLY unispy.sakestorage - ADD CONSTRAINT sakestorage_pk PRIMARY KEY (sakestorageid); +SELECT pg_catalog.setval('unispy.nat_result_caches_id_seq', 1, false); -- --- TOC entry 3291 (class 2606 OID 16523) --- Name: subprofiles subprofiles_pk; Type: CONSTRAINT; Schema: unispy; Owner: - +-- Name: profiles_profileid_seq; Type: SEQUENCE SET; Schema: unispy; Owner: unispy -- -ALTER TABLE ONLY unispy.subprofiles - ADD CONSTRAINT subprofiles_pk PRIMARY KEY (subprofileid); +SELECT pg_catalog.setval('unispy.profiles_profileid_seq', 2, true); -- --- TOC entry 3293 (class 2606 OID 16525) --- Name: users users_pk; Type: CONSTRAINT; Schema: unispy; Owner: - +-- Name: pstorage_id_seq; Type: SEQUENCE SET; Schema: unispy; Owner: unispy -- -ALTER TABLE ONLY unispy.users - ADD CONSTRAINT users_pk PRIMARY KEY (userid); +SELECT pg_catalog.setval('unispy.pstorage_id_seq', 1, false); -- --- TOC entry 3294 (class 2606 OID 16526) --- Name: addrequests addrequests_fk; Type: FK CONSTRAINT; Schema: unispy; Owner: - +-- Name: sakestorage_id_seq; Type: SEQUENCE SET; Schema: unispy; Owner: unispy -- -ALTER TABLE ONLY unispy.addrequests - ADD CONSTRAINT addrequests_fk FOREIGN KEY (profileid) REFERENCES unispy.profiles(profileid); +SELECT pg_catalog.setval('unispy.sakestorage_id_seq', 1, false); -- --- TOC entry 3295 (class 2606 OID 16531) --- Name: blocked blocked_fk; Type: FK CONSTRAINT; Schema: unispy; Owner: - +-- Name: subprofiles_subprofileid_seq; Type: SEQUENCE SET; Schema: unispy; Owner: unispy -- -ALTER TABLE ONLY unispy.blocked - ADD CONSTRAINT blocked_fk FOREIGN KEY (profileid) REFERENCES unispy.profiles(profileid); +SELECT pg_catalog.setval('unispy.subprofiles_subprofileid_seq', 1, false); -- --- TOC entry 3296 (class 2606 OID 16536) --- Name: friends friends_fk; Type: FK CONSTRAINT; Schema: unispy; Owner: - +-- Name: users_userid_seq; Type: SEQUENCE SET; Schema: unispy; Owner: unispy -- -ALTER TABLE ONLY unispy.friends - ADD CONSTRAINT friends_fk FOREIGN KEY (profileid) REFERENCES unispy.profiles(profileid); +SELECT pg_catalog.setval('unispy.users_userid_seq', 5, true); -- --- TOC entry 3297 (class 2606 OID 16541) --- Name: grouplist grouplist_fk; Type: FK CONSTRAINT; Schema: unispy; Owner: - +-- Name: grouplist grouplist_fk; Type: FK CONSTRAINT; Schema: unispy; Owner: unispy -- ALTER TABLE ONLY unispy.grouplist @@ -5488,34 +5498,20 @@ ALTER TABLE ONLY unispy.grouplist -- --- TOC entry 3298 (class 2606 OID 16546) --- Name: profiles profiles_fk; Type: FK CONSTRAINT; Schema: unispy; Owner: - +-- Name: profiles profiles_userid_fkey; Type: FK CONSTRAINT; Schema: unispy; Owner: unispy -- ALTER TABLE ONLY unispy.profiles - ADD CONSTRAINT profiles_fk FOREIGN KEY (userid) REFERENCES unispy.users(userid); - - --- --- TOC entry 3299 (class 2606 OID 16551) --- Name: pstorage pstorage_fk; Type: FK CONSTRAINT; Schema: unispy; Owner: - --- - -ALTER TABLE ONLY unispy.pstorage - ADD CONSTRAINT pstorage_fk FOREIGN KEY (profileid) REFERENCES unispy.profiles(profileid); + ADD CONSTRAINT profiles_userid_fkey FOREIGN KEY (userid) REFERENCES unispy.users(userid); -- --- TOC entry 3300 (class 2606 OID 16556) --- Name: subprofiles subprofiles_fk; Type: FK CONSTRAINT; Schema: unispy; Owner: - +-- Name: chat_user_caches chat_user_caches_channel_name_fkey; Type: FK CONSTRAINT; Schema: unispy; Owner: unispy -- +ALTER TABLE ONLY unispy.chat_channel_user_caches + ADD CONSTRAINT chat_channel_user_caches_channel_name_fkey FOREIGN KEY(channel_name) REFERENCES unispy.chat_channel_caches(channel_name); -ALTER TABLE ONLY unispy.subprofiles - ADD CONSTRAINT subprofiles_fk FOREIGN KEY (profileid) REFERENCES unispy.profiles(profileid); - +ALTER TABLE ONLY unispy.chat_channel_user_caches + ADD CONSTRAINT chat_channel_user_caches_nick_name_fkey FOREIGN KEY(nick_name) REFERENCES unispy.chat_user_caches(nick_name); --- Completed on 2022-03-02 20:15:24 CET - --- --- PostgreSQL database dump complete --- +-- PostgreSQL database dump complete \ No newline at end of file diff --git a/common/config.json b/common/config.json new file mode 100644 index 000000000..4d11cefdd --- /dev/null +++ b/common/config.json @@ -0,0 +1,112 @@ +{ + "backend": { + "url": "http://unispy_backends:8080", + "token_secret_key": "I love UniSpy", + "token_algorithm": "HS256", + "token_expire_time": 30, + "is_check_public_ip": false + }, + "logging": { + "path": "~/Downloads/unispy_server/log/", + "min_log_level": "debug" + }, + "postgresql": { + "server": "unispy_postgresql", + "port": 5432, + "database": "unispy", + "username": "unispy", + "password": "123456", + "ssl_mode": "allow", + "trust_server_cert": "false", + "ssl_key": "", + "ssl_password": "", + "root_cert": "" + }, + "mongodb": { + "server": "127.0.0.1", + "port": 5432, + "username": "unispy", + "password": "123456", + "database": null + }, + "redis": { + "server": "unispy_redis", + "port": 6379, + "user": "", + "password": "123456", + "ssl": "false", + "ssl_host": "" + }, + "servers": { + "PresenceConnectionManager": { + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "server_name": "PresenceConnectionManager", + "listening_address": "0.0.0.0", + "listening_port": 29900 + }, + "PresenceSearchPlayer": { + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "server_name": "PresenceSearchPlayer", + "listening_address": "0.0.0.0", + "listening_port": 29901 + }, + "CDKey": { + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "server_name": "CDKey", + "listening_address": "0.0.0.0", + "listening_port": 29910 + }, + "ServerBrowserV1": { + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "server_name": "ServerBrowserV1", + "listening_address": "0.0.0.0", + "listening_port": 28900 + }, + "ServerBrowserV2": { + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "server_name": "ServerBrowserV2", + "listening_address": "0.0.0.0", + "listening_port": 28910 + }, + "QueryReport": { + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "server_name": "QueryReport", + "listening_address": "0.0.0.0", + "listening_port": 27900 + }, + "NatNegotiation": { + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "server_name": "NatNegotiation", + "listening_address": "0.0.0.0", + "listening_port": 27901 + }, + "GameStatus": { + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "server_name": "GameStatus", + "listening_address": "0.0.0.0", + "listening_port": 29920 + }, + "Chat": { + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "server_name": "Chat", + "listening_address": "0.0.0.0", + "listening_port": 6667 + }, + "WebServices": { + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "server_name": "WebServices", + "listening_address": "0.0.0.0", + "listening_port": 80 + }, + "GameTrafficRelay": { + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "server_name": "GameTrafficRelay", + "listening_address": "0.0.0.0", + "listening_port": 10086 + } + }, + "unittest": { + "is_raise_except": false, + "is_collect_request": false + } +} \ No newline at end of file diff --git a/common/docker-compose.build.yml b/common/docker-compose.build.yml deleted file mode 100644 index 571e96503..000000000 --- a/common/docker-compose.build.yml +++ /dev/null @@ -1,104 +0,0 @@ -# Use this docker-compose file to build RetroSpy for test purposes. - -version: '3.7' -services: - # cdkey: - # build: - # context: ../ - # dockerfile: ./src/Servers/CDKey/src/Dockerfile - # image: gameprogressive/cdkey - # ports: - # - "29910:29910/udp" - # stdin_open: true - # tty: true - - chat: - build: - context: ../ - dockerfile: ./src/Servers/Chat/src/Dockerfile - image: gameprogressive/chat - ports: - - "6667:6667" - stdin_open: true - tty: true - - gs: - build: - context: ../ - dockerfile: ./src/Servers/GameStatus/src/Dockerfile - image: gameprogressive/gs - ports: - - "29920:29920" - stdin_open: true - tty: true - - gtr: - build: - context: ../ - dockerfile: ./src/Servers/GameTrafficRelay/src/Dockerfile - image: gameprogressive/gtr - ports: - - "10086:10086/udp" - stdin_open: true - tty: true - - nn: - build: - context: ../ - dockerfile: ./src/Servers/NatNegotiation/src/Dockerfile - image: gameprogressive/nn - ports: - - "27901:27901/udp" - stdin_open: true - tty: true - - pcm: - build: - context: ../ - dockerfile: ./src/Servers/PresenceConnectionManager/src/Dockerfile - image: gameprogressive/pcm - ports: - - "29900:29900" - stdin_open: true - tty: true - - psp: - build: - context: ../ - dockerfile: ./src/Servers/PresenceSearchPlayer/src/Dockerfile - image: gameprogressive/psp - ports: - - "29901:29901" - stdin_open: true - tty: true - - qr: - build: - context: ../ - dockerfile: ./src/Servers/QueryReport/src/Dockerfile - image: gameprogressive/qr - ports: - - "27900:27900/udp" - stdin_open: true - tty: true - - sb: - build: - context: ../ - dockerfile: ./src/Servers/ServerBrowser/src/Dockerfile - image: gameprogressive/sb - ports: - - "28910:28910" - - "28900:28900" - stdin_open: true - tty: true - - ws: - build: - context: ../ - dockerfile: ./src/Servers/WebServer/src/Dockerfile - image: gameprogressive/ws - ports: - - "80:80" - stdin_open: true - tty: true diff --git a/common/pg_certs/root/root.crt b/common/pg_certs/root/root.crt new file mode 100644 index 000000000..d8dcf6b84 --- /dev/null +++ b/common/pg_certs/root/root.crt @@ -0,0 +1,77 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 36:d7:c5:3a:fe:85:75:9d:1e:ed:e2:c3:70:34:af:ed:22:57:cf:2d + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN = unispy.net + Validity + Not Before: Oct 24 02:51:56 2024 GMT + Not After : Oct 22 02:51:56 2034 GMT + Subject: CN = unispy.net + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:c6:25:5d:9a:ba:2f:a4:b7:5f:95:cd:d1:b3:51: + 36:69:69:42:05:2b:f2:32:e0:d1:b1:73:38:dc:df: + 54:49:bd:a2:34:e3:9b:5e:1b:bc:7b:54:87:28:9f: + e6:02:93:4d:62:bf:7b:01:f4:75:ea:6c:cc:50:f9: + 03:70:79:37:61:b6:06:1f:a7:23:e5:60:d5:7a:3b: + 87:5d:9c:f3:e1:9a:5e:4b:49:9c:05:70:4c:9c:b2: + f2:af:22:7d:34:da:53:a6:5e:21:73:1a:87:67:4f: + 2c:c7:65:eb:05:44:b6:97:fe:54:7d:16:61:cb:44: + d2:2f:03:6e:a6:3f:3c:19:92:75:8b:80:b0:61:10: + d5:ab:99:16:0e:cf:5d:66:f8:e5:e3:b2:08:78:03: + af:86:c0:07:3d:b0:d2:33:a2:45:6c:96:18:4a:e7: + e5:bd:ac:23:ea:7c:55:f9:15:9d:62:35:19:02:d1: + b1:c3:0b:f5:2b:f8:06:a7:53:10:42:75:c6:44:57: + ad:b9:3b:37:f1:01:f6:16:81:bb:cc:24:62:8d:da: + 53:d3:8d:9e:42:ec:33:b3:4b:29:88:b1:e4:31:03: + f5:10:51:7e:54:a0:11:92:2e:d2:b6:6b:09:8e:aa: + 17:05:b5:61:0b:93:a0:25:99:39:5a:df:31:4e:60: + f7:6b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + B9:42:89:52:5A:0B:41:68:D2:8B:B7:DD:D4:EB:B0:31:A8:01:1D:81 + X509v3 Authority Key Identifier: + B9:42:89:52:5A:0B:41:68:D2:8B:B7:DD:D4:EB:B0:31:A8:01:1D:81 + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 8e:73:42:21:f4:3c:67:98:31:b3:39:1a:0e:42:5d:fb:0f:ef: + 7d:d6:d9:86:63:29:4d:d9:ce:f6:54:49:af:4e:42:c7:f7:5e: + f4:28:39:9d:19:fc:8c:fc:61:e1:37:bf:10:29:81:aa:c4:3a: + 4a:a5:bd:92:c5:f6:51:6f:ca:4e:12:a9:ce:cd:77:75:ae:72: + a3:72:f4:19:f4:58:3a:65:6f:eb:55:a1:f2:05:04:a8:5c:6a: + 2b:d0:7e:94:a9:3b:f8:a6:68:f2:67:05:e9:79:64:6a:c2:c2: + 31:00:e3:af:95:34:6c:f9:99:88:0b:62:1a:c8:c3:31:f9:73: + 46:9b:20:6a:14:3f:ef:70:07:72:7e:4e:4e:e6:46:16:d1:f5: + 52:6b:0a:7e:7d:ed:fb:f1:31:3b:be:a9:77:06:a0:eb:e1:8a: + cb:fa:67:ef:df:2c:ef:9e:89:d8:5b:46:40:90:ab:3a:9a:69: + 5b:3d:45:8a:63:a0:6d:3b:46:69:b1:9a:60:0a:83:5a:02:53: + e3:b6:90:ec:79:90:1b:a4:13:e8:5f:b6:e2:45:fb:4b:28:a6: + 01:86:ff:a2:2e:37:cb:a0:8c:3c:8d:1b:ff:a6:0a:c7:06:01: + 8a:20:77:9b:dd:e8:bb:72:e5:d3:9c:e6:bc:92:ca:2c:19:f3: + 31:bd:1b:e7 +-----BEGIN CERTIFICATE----- +MIIDCzCCAfOgAwIBAgIUNtfFOv6FdZ0e7eLDcDSv7SJXzy0wDQYJKoZIhvcNAQEL +BQAwFTETMBEGA1UEAwwKdW5pc3B5Lm5ldDAeFw0yNDEwMjQwMjUxNTZaFw0zNDEw +MjIwMjUxNTZaMBUxEzARBgNVBAMMCnVuaXNweS5uZXQwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDGJV2aui+kt1+VzdGzUTZpaUIFK/Iy4NGxczjc31RJ +vaI045teG7x7VIcon+YCk01iv3sB9HXqbMxQ+QNweTdhtgYfpyPlYNV6O4ddnPPh +ml5LSZwFcEycsvKvIn002lOmXiFzGodnTyzHZesFRLaX/lR9FmHLRNIvA26mPzwZ +knWLgLBhENWrmRYOz11m+OXjsgh4A6+GwAc9sNIzokVslhhK5+W9rCPqfFX5FZ1i +NRkC0bHDC/Ur+AanUxBCdcZEV625OzfxAfYWgbvMJGKN2lPTjZ5C7DOzSymIseQx +A/UQUX5UoBGSLtK2awmOqhcFtWELk6AlmTla3zFOYPdrAgMBAAGjUzBRMB0GA1Ud +DgQWBBS5QolSWgtBaNKLt93U67AxqAEdgTAfBgNVHSMEGDAWgBS5QolSWgtBaNKL +t93U67AxqAEdgTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCO +c0Ih9DxnmDGzORoOQl37D+991tmGYylN2c72VEmvTkLH9170KDmdGfyM/GHhN78Q +KYGqxDpKpb2SxfZRb8pOEqnOzXd1rnKjcvQZ9Fg6ZW/rVaHyBQSoXGor0H6UqTv4 +pmjyZwXpeWRqwsIxAOOvlTRs+ZmIC2IayMMx+XNGmyBqFD/vcAdyfk5O5kYW0fVS +awp+fe378TE7vql3BqDr4YrL+mfv3yzvnonYW0ZAkKs6mmlbPUWKY6BtO0ZpsZpg +CoNaAlPjtpDseZAbpBPoX7biRftLKKYBhv+iLjfLoIw8jRv/pgrHBgGKIHeb3ei7 +cuXTnOa8ksosGfMxvRvn +-----END CERTIFICATE----- diff --git a/common/pg_certs/root/root.csr b/common/pg_certs/root/root.csr new file mode 100644 index 000000000..8e246683d --- /dev/null +++ b/common/pg_certs/root/root.csr @@ -0,0 +1,62 @@ +Certificate Request: + Data: + Version: 1 (0x0) + Subject: CN = unispy.net + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:c6:25:5d:9a:ba:2f:a4:b7:5f:95:cd:d1:b3:51: + 36:69:69:42:05:2b:f2:32:e0:d1:b1:73:38:dc:df: + 54:49:bd:a2:34:e3:9b:5e:1b:bc:7b:54:87:28:9f: + e6:02:93:4d:62:bf:7b:01:f4:75:ea:6c:cc:50:f9: + 03:70:79:37:61:b6:06:1f:a7:23:e5:60:d5:7a:3b: + 87:5d:9c:f3:e1:9a:5e:4b:49:9c:05:70:4c:9c:b2: + f2:af:22:7d:34:da:53:a6:5e:21:73:1a:87:67:4f: + 2c:c7:65:eb:05:44:b6:97:fe:54:7d:16:61:cb:44: + d2:2f:03:6e:a6:3f:3c:19:92:75:8b:80:b0:61:10: + d5:ab:99:16:0e:cf:5d:66:f8:e5:e3:b2:08:78:03: + af:86:c0:07:3d:b0:d2:33:a2:45:6c:96:18:4a:e7: + e5:bd:ac:23:ea:7c:55:f9:15:9d:62:35:19:02:d1: + b1:c3:0b:f5:2b:f8:06:a7:53:10:42:75:c6:44:57: + ad:b9:3b:37:f1:01:f6:16:81:bb:cc:24:62:8d:da: + 53:d3:8d:9e:42:ec:33:b3:4b:29:88:b1:e4:31:03: + f5:10:51:7e:54:a0:11:92:2e:d2:b6:6b:09:8e:aa: + 17:05:b5:61:0b:93:a0:25:99:39:5a:df:31:4e:60: + f7:6b + Exponent: 65537 (0x10001) + Attributes: + (none) + Requested Extensions: + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 1c:c4:9d:64:4e:ad:a8:a5:cd:c2:cf:1f:59:ec:3e:37:3c:0b: + 56:00:4e:1d:d1:71:cd:ba:76:cc:88:28:5c:15:2c:01:71:ca: + d6:b2:93:38:9e:67:ff:da:a9:cd:86:b1:be:0c:02:f9:1b:d3: + 7a:19:82:37:f6:32:1b:7b:55:1f:67:91:f1:04:d0:13:41:b5: + c8:62:c3:10:1b:45:ee:6f:3b:bf:58:5d:c0:f7:a6:c7:c9:01: + e5:8e:6b:e6:d3:40:08:51:ee:c3:07:42:bb:c6:cf:5c:74:23: + 3b:f9:e1:89:2f:a6:bb:ab:74:b8:e2:fe:76:5f:bf:b8:0d:58: + 7c:c2:76:2e:97:60:25:d3:c9:a9:1e:be:fc:2c:e9:6d:36:4c: + b3:2f:15:c1:2d:f0:6b:f4:aa:49:ea:3d:ef:0e:50:74:5f:e2: + a0:bf:a6:a0:a0:ad:0a:75:0b:c3:9b:4c:a8:d8:a2:d9:d7:ef: + 2e:2b:27:37:80:a6:da:4b:1c:8e:a4:fa:79:81:66:cd:29:58: + dc:e5:3a:67:b6:d5:3c:e0:f8:0b:10:4c:71:c0:93:95:9a:f2: + 60:4e:8d:e7:2d:8b:2e:81:a8:96:9c:fd:a9:46:44:87:eb:52: + 68:3f:d7:b8:74:6a:57:50:c2:57:0e:2a:48:78:6a:2e:6b:da: + 4e:40:db:34 +-----BEGIN CERTIFICATE REQUEST----- +MIICWjCCAUICAQAwFTETMBEGA1UEAwwKdW5pc3B5Lm5ldDCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAMYlXZq6L6S3X5XN0bNRNmlpQgUr8jLg0bFzONzf +VEm9ojTjm14bvHtUhyif5gKTTWK/ewH0depszFD5A3B5N2G2Bh+nI+Vg1Xo7h12c +8+GaXktJnAVwTJyy8q8ifTTaU6ZeIXMah2dPLMdl6wVEtpf+VH0WYctE0i8DbqY/ +PBmSdYuAsGEQ1auZFg7PXWb45eOyCHgDr4bABz2w0jOiRWyWGErn5b2sI+p8VfkV +nWI1GQLRscML9Sv4BqdTEEJ1xkRXrbk7N/EB9haBu8wkYo3aU9ONnkLsM7NLKYix +5DED9RBRflSgEZIu0rZrCY6qFwW1YQuToCWZOVrfMU5g92sCAwEAAaAAMA0GCSqG +SIb3DQEBCwUAA4IBAQAcxJ1kTq2opc3Czx9Z7D43PAtWAE4d0XHNunbMiChcFSwB +ccrWspM4nmf/2qnNhrG+DAL5G9N6GYI39jIbe1UfZ5HxBNATQbXIYsMQG0Xubzu/ +WF3A96bHyQHljmvm00AIUe7DB0K7xs9cdCM7+eGJL6a7q3S44v52X7+4DVh8wnYu +l2Al08mpHr78LOltNkyzLxXBLfBr9KpJ6j3vDlB0X+Kgv6agoK0KdQvDm0yo2KLZ +1+8uKyc3gKbaSxyOpPp5gWbNKVjc5TpnttU84PgLEExxwJOVmvJgTo3nLYsugaiW +nP2pRkSH61JoP9e4dGpXUMJXDipIeGoua9pOQNs0 +-----END CERTIFICATE REQUEST----- diff --git a/common/pg_certs/root/root.key b/common/pg_certs/root/root.key new file mode 100644 index 000000000..fd4b499e6 --- /dev/null +++ b/common/pg_certs/root/root.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDGJV2aui+kt1+V +zdGzUTZpaUIFK/Iy4NGxczjc31RJvaI045teG7x7VIcon+YCk01iv3sB9HXqbMxQ ++QNweTdhtgYfpyPlYNV6O4ddnPPhml5LSZwFcEycsvKvIn002lOmXiFzGodnTyzH +ZesFRLaX/lR9FmHLRNIvA26mPzwZknWLgLBhENWrmRYOz11m+OXjsgh4A6+GwAc9 +sNIzokVslhhK5+W9rCPqfFX5FZ1iNRkC0bHDC/Ur+AanUxBCdcZEV625OzfxAfYW +gbvMJGKN2lPTjZ5C7DOzSymIseQxA/UQUX5UoBGSLtK2awmOqhcFtWELk6AlmTla +3zFOYPdrAgMBAAECggEAH2LZ0eF+HHxDcso4Vkwd71KR95m/cpmz/YS/1BS4GDom +kHQhLyX7lBmOkzvIxk2o62RjSqr7Zpe3QXhAODerMxoPHEJwaCwPhJ4bUhPDec/m +8cwGH8JrEEM0N9Ohu5Z9u5Obfs0L96xN7oPRV3NL7QWHQo0iDn2nQXUsuL65eV83 +Tgv0eK8GlVoESGgnE9/w5U2gHMEvrKD3Zxax5i8HknSSLKS235iNnhlX1anNC34H +PQfWxCqapzRv+FB7t+AtlZx8RU/ky4Q6HkzeuXAZQ1qEk7+tblnt5B3DpHTf3l7w +EDQSvCKeKDj6ryiu+/TWwfzJFGuFVarkv8yllUFHUQKBgQDj+Qd0zytpLHkGzTpF +53iYpLyOclNd3FXTuV1L7XQB1mwKmXvL807j9tonF4repBKiLWR64SzY81sRcNAr +8SZF/C7AFtTuDJYjB81LLdUcVC7Hmen0hjQxa0OiVGck9yOlfZCcd3Ww9NFp1ycL +MnbIRWI8J8T9Qh843hMxLPpdCQKBgQDegZlze+lWlrwxn1SkYeh/bIS+WM/MwB/4 ++L7rx40W49EDhxVCM4fO91VkZN4nZPXvIDhF/8A3FMEuAxVGgbJnG9fln+3xbNeZ +fKqAS3rIXzVtDDuwsNLVX6NQZ0CagCnJyXJqDvI+N6Mgg9cdPnCL6dbthanZVYzV +Cxo9F+9B0wKBgB95SiY+U+f5U9w0iU8NXgD0/XNNJWVX/iF0/gR1jAaU6+WquwS1 +WrbuZb/v6CRE0q3BRpYQcHijYHdP8+2dJYOUBYBPpqYW5sN/WECA22NF3A+CmGJC +BQKtpHDM5lCcLjey1jxD4ePEaQULx0Asf2m26pETjIbKkjTvtAaeBxLBAoGBAJmS +V4gmgPFbjj6tmqzuSpsQGjqKb7oA7NBZVuTDUTT4Pj2yEVEk4dpOSWjGWbJU8418 +7noZv+AEeiS4yglk4O5bgFKjZIYaOmBcdA2iivcbB3PhWp1kHdBZdw26hhNc2/rD +CC39bOLWYcfCV0l+3A0lc0ty0r0HV/F+/TgneeIzAoGBANpri83xFrYQzS6fjm9U +SB/4mTzdRRVqh44UEYKciSnMhD8I8XYKV7vV3Ix9L+yYGxTOUDfskDLrQ1t66oqV +o7mmG5MFkSoTdMB1v6hZXVYhSQ5J5Q9QNdSppU8NLxXiaFScJdhZpF2wcINkbxPm +j9TqJ4zJ7H+FP0RP9Kn+zK23 +-----END PRIVATE KEY----- diff --git a/common/pg_certs/root/root.srl b/common/pg_certs/root/root.srl new file mode 100644 index 000000000..12500797a --- /dev/null +++ b/common/pg_certs/root/root.srl @@ -0,0 +1 @@ +45BD6FD72E54134CD40A3B242DC3A69B964E17BF diff --git a/common/pg_certs/root/server.csr b/common/pg_certs/root/server.csr new file mode 100644 index 000000000..bf42c3a2b --- /dev/null +++ b/common/pg_certs/root/server.csr @@ -0,0 +1,62 @@ +Certificate Request: + Data: + Version: 1 (0x0) + Subject: CN = dbhost.yourdomain.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:9c:da:6e:a6:3d:77:67:6d:b8:88:d5:2e:d9:2d: + 21:ca:9b:e4:3d:f9:a7:ba:c6:60:12:85:0c:66:64: + 2b:ac:10:a4:2a:69:a7:78:0e:0f:d8:c7:b8:83:ed: + 5d:2e:9b:30:0f:27:1e:ca:b1:0c:34:4f:e3:25:57: + 7a:5c:38:ee:ba:5a:1c:f7:d3:c7:92:df:ef:9f:26: + 2c:01:50:bf:63:df:7d:e6:0e:d7:08:49:33:de:aa: + 2d:42:3b:8f:81:c2:87:14:6c:5a:cf:c3:b6:06:59: + 3a:f6:f0:ec:ff:2b:ec:7c:e1:9b:c3:d6:5d:50:34: + 55:37:c6:77:be:88:15:0a:a9:43:0d:8c:b4:b9:9f: + 8f:8a:03:70:b7:a6:82:cb:cd:ba:ae:cd:11:b7:f2: + e1:56:16:8c:67:f9:73:c1:0d:b3:50:1f:76:3a:f9: + 91:50:bb:4c:ed:67:56:d6:c0:3f:1f:24:a3:98:20: + 55:14:6b:1c:89:f7:fe:97:04:ca:fb:50:54:1f:47: + 5a:31:4b:2d:48:86:ab:cc:c3:ca:38:b0:1f:72:8a: + 60:40:bc:e8:31:39:f4:a3:20:c4:4c:93:7c:ef:10: + 16:37:4d:9e:10:60:28:f2:89:55:bf:3d:04:cf:8d: + 58:45:3f:d5:4a:06:be:fc:5a:74:db:8d:8f:ca:98: + 3b:c1 + Exponent: 65537 (0x10001) + Attributes: + (none) + Requested Extensions: + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 7d:54:f9:9a:3c:79:64:e3:5b:9a:93:3a:36:d8:72:4d:fb:cd: + d2:a6:19:e6:d9:e0:d0:de:39:b1:a9:eb:f4:a0:eb:88:b7:0a: + 5b:c8:09:25:4a:6b:26:05:8f:3f:aa:da:75:a8:02:b5:09:ec: + e8:b9:ec:2e:55:b8:61:12:ae:5b:e9:41:68:08:cd:22:e6:e2: + d9:e9:cc:6e:df:c3:5e:2f:20:7a:39:b1:24:3a:f5:9a:9d:d1: + 39:2a:f4:c1:16:e9:64:84:1f:cd:4a:ac:91:82:e8:69:00:0b: + 2f:49:2d:15:4c:85:0f:a3:68:d1:98:aa:90:23:db:84:7a:98: + f5:fb:03:c1:d1:ae:ef:e3:67:54:f0:91:ce:29:ac:ae:dd:3f: + ac:74:59:0e:69:69:97:08:24:1b:27:77:23:b8:97:28:53:69: + ab:50:cf:ae:00:06:1e:6b:8f:62:ce:bb:9d:49:0f:c2:65:0a: + a6:5c:05:ac:b4:de:7c:72:55:9e:aa:01:0c:ff:14:46:c0:d6: + 44:eb:43:b8:25:d8:a5:e7:8b:49:c3:dd:d0:66:58:be:92:06: + 9a:dd:44:6f:c9:01:b9:5d:1e:09:fa:ad:e7:ab:8a:67:d5:21: + 00:d7:a8:c7:f1:1b:a2:f5:6a:64:c7:64:23:f2:df:f8:e0:9e: + ba:46:40:0a +-----BEGIN CERTIFICATE REQUEST----- +MIICZTCCAU0CAQAwIDEeMBwGA1UEAwwVZGJob3N0LnlvdXJkb21haW4uY29tMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnNpupj13Z224iNUu2S0hypvk +PfmnusZgEoUMZmQrrBCkKmmneA4P2Me4g+1dLpswDyceyrEMNE/jJVd6XDjuuloc +99PHkt/vnyYsAVC/Y9995g7XCEkz3qotQjuPgcKHFGxaz8O2Blk69vDs/yvsfOGb +w9ZdUDRVN8Z3vogVCqlDDYy0uZ+PigNwt6aCy826rs0Rt/LhVhaMZ/lzwQ2zUB92 +OvmRULtM7WdW1sA/HySjmCBVFGsciff+lwTK+1BUH0daMUstSIarzMPKOLAfcopg +QLzoMTn0oyDETJN87xAWN02eEGAo8olVvz0Ez41YRT/VSga+/Fp0242Pypg7wQID +AQABoAAwDQYJKoZIhvcNAQELBQADggEBAH1U+Zo8eWTjW5qTOjbYck37zdKmGebZ +4NDeObGp6/Sg64i3ClvICSVKayYFjz+q2nWoArUJ7Oi57C5VuGESrlvpQWgIzSLm +4tnpzG7fw14vIHo5sSQ69Zqd0Tkq9MEW6WSEH81KrJGC6GkACy9JLRVMhQ+jaNGY +qpAj24R6mPX7A8HRru/jZ1Twkc4prK7dP6x0WQ5paZcIJBsndyO4lyhTaatQz64A +Bh5rj2LOu51JD8JlCqZcBay03nxyVZ6qAQz/FEbA1kTrQ7gl2KXni0nD3dBmWL6S +BprdRG/JAbldHgn6reerimfVIQDXqMfxG6L1amTHZCPy3/jgnrpGQAo= +-----END CERTIFICATE REQUEST----- diff --git a/common/pg_certs/server.crt b/common/pg_certs/server.crt new file mode 100644 index 000000000..47d047a90 --- /dev/null +++ b/common/pg_certs/server.crt @@ -0,0 +1,68 @@ +Certificate: + Data: + Version: 1 (0x0) + Serial Number: + 45:bd:6f:d7:2e:54:13:4c:d4:0a:3b:24:2d:c3:a6:9b:96:4e:17:bf + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN = unispy.net + Validity + Not Before: Oct 24 02:52:10 2024 GMT + Not After : Oct 24 02:52:10 2025 GMT + Subject: CN = dbhost.yourdomain.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:9c:da:6e:a6:3d:77:67:6d:b8:88:d5:2e:d9:2d: + 21:ca:9b:e4:3d:f9:a7:ba:c6:60:12:85:0c:66:64: + 2b:ac:10:a4:2a:69:a7:78:0e:0f:d8:c7:b8:83:ed: + 5d:2e:9b:30:0f:27:1e:ca:b1:0c:34:4f:e3:25:57: + 7a:5c:38:ee:ba:5a:1c:f7:d3:c7:92:df:ef:9f:26: + 2c:01:50:bf:63:df:7d:e6:0e:d7:08:49:33:de:aa: + 2d:42:3b:8f:81:c2:87:14:6c:5a:cf:c3:b6:06:59: + 3a:f6:f0:ec:ff:2b:ec:7c:e1:9b:c3:d6:5d:50:34: + 55:37:c6:77:be:88:15:0a:a9:43:0d:8c:b4:b9:9f: + 8f:8a:03:70:b7:a6:82:cb:cd:ba:ae:cd:11:b7:f2: + e1:56:16:8c:67:f9:73:c1:0d:b3:50:1f:76:3a:f9: + 91:50:bb:4c:ed:67:56:d6:c0:3f:1f:24:a3:98:20: + 55:14:6b:1c:89:f7:fe:97:04:ca:fb:50:54:1f:47: + 5a:31:4b:2d:48:86:ab:cc:c3:ca:38:b0:1f:72:8a: + 60:40:bc:e8:31:39:f4:a3:20:c4:4c:93:7c:ef:10: + 16:37:4d:9e:10:60:28:f2:89:55:bf:3d:04:cf:8d: + 58:45:3f:d5:4a:06:be:fc:5a:74:db:8d:8f:ca:98: + 3b:c1 + Exponent: 65537 (0x10001) + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 4c:40:14:e7:6d:0e:2a:0e:9f:3e:a9:9a:ad:b1:3e:8a:dd:7a: + a4:fb:4a:11:0d:3d:8f:9f:a8:be:eb:41:1d:64:2d:d2:77:11: + 3c:1c:9f:f6:39:99:6a:08:5c:62:7e:9e:40:92:58:d9:0a:14: + 1b:fe:16:dc:48:93:2c:ab:3b:49:c6:5a:f5:01:16:ad:46:92: + a8:63:4a:21:b9:23:f5:f2:ad:4f:41:09:8c:6b:a5:4d:c9:ab: + 8e:8f:4d:dd:b4:fd:f0:5e:6c:a6:d4:0b:ad:5b:86:58:e2:48: + 72:65:ab:0b:a2:de:f4:f5:da:a5:66:16:fb:71:f0:41:90:e6: + 90:4a:73:c0:31:f2:1f:90:ab:7d:b0:e6:f0:15:76:a0:69:17: + 4a:04:cc:3d:8c:a6:dd:11:b8:e0:09:c5:5a:f8:39:d6:bf:d1: + bb:39:e5:43:04:93:fb:ed:c6:4d:16:22:eb:69:ff:ea:e5:66: + 42:9c:ce:a1:b2:84:37:d8:55:c6:ca:51:93:59:06:b3:11:23: + 5d:f1:66:5d:7e:9b:2b:f2:4d:b3:2f:37:66:5c:4a:24:14:ec: + 29:78:97:f9:7e:0f:38:20:23:f7:e2:3c:49:e4:f7:76:a8:ea: + 5b:73:03:32:f4:cc:99:dd:3f:74:0e:13:05:11:60:71:31:5a: + ef:88:22:46 +-----BEGIN CERTIFICATE----- +MIICvDCCAaQCFEW9b9cuVBNM1Ao7JC3DppuWThe/MA0GCSqGSIb3DQEBCwUAMBUx +EzARBgNVBAMMCnVuaXNweS5uZXQwHhcNMjQxMDI0MDI1MjEwWhcNMjUxMDI0MDI1 +MjEwWjAgMR4wHAYDVQQDDBVkYmhvc3QueW91cmRvbWFpbi5jb20wggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCc2m6mPXdnbbiI1S7ZLSHKm+Q9+ae6xmAS +hQxmZCusEKQqaad4Dg/Yx7iD7V0umzAPJx7KsQw0T+MlV3pcOO66Whz308eS3++f +JiwBUL9j333mDtcISTPeqi1CO4+BwocUbFrPw7YGWTr28Oz/K+x84ZvD1l1QNFU3 +xne+iBUKqUMNjLS5n4+KA3C3poLLzbquzRG38uFWFoxn+XPBDbNQH3Y6+ZFQu0zt +Z1bWwD8fJKOYIFUUaxyJ9/6XBMr7UFQfR1oxSy1IhqvMw8o4sB9yimBAvOgxOfSj +IMRMk3zvEBY3TZ4QYCjyiVW/PQTPjVhFP9VKBr78WnTbjY/KmDvBAgMBAAEwDQYJ +KoZIhvcNAQELBQADggEBAExAFOdtDioOnz6pmq2xPordeqT7ShENPY+fqL7rQR1k +LdJ3ETwcn/Y5mWoIXGJ+nkCSWNkKFBv+FtxIkyyrO0nGWvUBFq1GkqhjSiG5I/Xy +rU9BCYxrpU3Jq46PTd20/fBebKbUC61bhljiSHJlqwui3vT12qVmFvtx8EGQ5pBK +c8Ax8h+Qq32w5vAVdqBpF0oEzD2Mpt0RuOAJxVr4Oda/0bs55UMEk/vtxk0WIutp +/+rlZkKczqGyhDfYVcbKUZNZBrMRI13xZl1+myvyTbMvN2ZcSiQU7Cl4l/l+Dzgg +I/fiPEnk93ao6ltzAzL0zJndP3QOEwURYHExWu+IIkY= +-----END CERTIFICATE----- diff --git a/common/pg_certs/server.key b/common/pg_certs/server.key new file mode 100644 index 000000000..0960f0e1e --- /dev/null +++ b/common/pg_certs/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCc2m6mPXdnbbiI +1S7ZLSHKm+Q9+ae6xmAShQxmZCusEKQqaad4Dg/Yx7iD7V0umzAPJx7KsQw0T+Ml +V3pcOO66Whz308eS3++fJiwBUL9j333mDtcISTPeqi1CO4+BwocUbFrPw7YGWTr2 +8Oz/K+x84ZvD1l1QNFU3xne+iBUKqUMNjLS5n4+KA3C3poLLzbquzRG38uFWFoxn ++XPBDbNQH3Y6+ZFQu0ztZ1bWwD8fJKOYIFUUaxyJ9/6XBMr7UFQfR1oxSy1IhqvM +w8o4sB9yimBAvOgxOfSjIMRMk3zvEBY3TZ4QYCjyiVW/PQTPjVhFP9VKBr78WnTb +jY/KmDvBAgMBAAECggEADdazQ7lBVUefy/nEEP7rf+7WWbXyu5a4P/YLYKbGmB8d +Ps00zHGwKfv//mrFKYEhYbrdu3wYo65nL+KajfOrc1dTPjXKAj4969SQNhr/0dHU +b6VgSS+9MvBgfxsWZ5hINu/y6Kj/oKqDemlJ/Z7sVd3JUoNRlwuQ97Nr2exzb83Z +ByArsrrYGhApckgJ5lO5KUoEWX0ciVb3t4rQftNYSGrJUl+AKkpNrsCzhzprfJ9Y +q79/lJZ9ZBspYemF9goRtFcQ0ZuYgg05fEKNIbjm5SrNhmT0GDCFbQXcus4+aNT/ +YvTtwE9O4NJ8pfEsm6BFHpmfubu8xCbX33nYSFhE+QKBgQDWYjou0HL+7KJoqzhw +23UZCvIoH7cBqtjd5+PcpiSAEuLtPT9UJ67ZoEN4zzC8gA3KenoOVkzY9teT/CYZ +3wGzJFLLYLroQ+4pFvDNreNeT72RzlF7MYu51f7n0EEv7OrKZ/KdnxtmBqj0HH6p +ZbSkdknKz+wN/MgEMoYmpuepyQKBgQC7TTxtSaEllHwcPudGNIX4CRHNEKreU4RA +o3ggcvlmV6YKnSlwFzaF+Lgzox2J2OyswoDSgIHfBfpCCQjE6NY6/48XLuTW8JWh +kIyOaJuBS3UQDYfEdNpnpjgMU+ZwW62aC3opZCe8nK/JOWw1lCrJirZh0INM+1xy +RfG+WR7+OQKBgC+rxf5U8c1H91FJCZLm6eH4siJD8yDWycSGZP/Snfkwue9BGEzx +SgswfPBnOhIgc3CbzXpUrF/ue793aU2Fbk5UfGinCMjPGi1e4YsK6K03FBNRCoNX +YBehwz3u7B/pEciSVru//oqwXm9xyqSGbiXH+96yX2440I1GYthDcu4pAoGARrPy +IoMPzKLPcs4f+XVsOOQbjyBCj+hQ3SGYAA/Gq2ZcrFcFRGXO1CW+SufBB78WIGTP +wiZ2X9zeyjykzcfizqSXvDWcdrKcmT96f2tngBge2W9yF6vQoh2xvJ2TOEizMJoy +hBtlkKJJDRmbCmKjAC9Xh3bxiYa9L/nNNoBn3akCgYBrcFhAfzxR8uYOCD7p1blK +xz/Q72K8wTA6IHvpwFh89oby0hRTiuulOtyHs08dC2OU2sEzJvYEyK665Q8k6ttC +CVgt1nC9s/UTt7piZ1cURQhnmbw1T5wzBXyTArRXoXj7CphDY/9QxaFdSFp5pFUP +2BMWzhRZm/Q9S7oKz9TOjw== +-----END PRIVATE KEY----- diff --git a/docker-compose-unispy-env.yml b/docker-compose-unispy-env.yml new file mode 100644 index 000000000..efcb689a3 --- /dev/null +++ b/docker-compose-unispy-env.yml @@ -0,0 +1,31 @@ +services: + redis: + image: redis + container_name: unispy_redis + restart: always + ports: + - "6379:6379" + command: redis-server --requirepass 123456 + networks: + - unispy + + postgresql: + image: postgres:14 + container_name: unispy_postgresql + ports: + - "5432:5432" + restart: always + environment: + POSTGRES_USER: unispy + POSTGRES_PASSWORD: 123456 + POSTGRES_DB: unispy + volumes: + - ./common/UniSpy_pg.sql:/docker-entrypoint-initdb.d/init.sql + networks: + - unispy + +networks: + unispy: + external: true + name: unispy + driver: bridge \ No newline at end of file diff --git a/docker-compose-unispy-server.yml b/docker-compose-unispy-server.yml new file mode 100644 index 000000000..e6dc686ef --- /dev/null +++ b/docker-compose-unispy-server.yml @@ -0,0 +1,205 @@ +services: + backends: + container_name: unispy_backends + image: unispy-python + restart: always + working_dir: /unispy-server/src + environment: + - PYTHONPATH=/unispy-server/src:${PYTHONPATH:-} + - UNISPY_CONFIG=/unispy-server/common/config.json + volumes: + - ./:/unispy-server/ + - ./log:/root/Downloads/unispy-server/log/ + ports: + - "8080:8080" + command: uvicorn --host 0.0.0.0 --port 8080 backends.routers.home:app + healthcheck: + test: curl --silent --show-error http://localhost:8080 >/dev/null 2>&1 || exit 1 + interval: 30s + timeout: 3s + retries: 3 + start_period: 2s + networks: + - unispy + chat: + image: unispy-python + container_name: unispy-chat + restart: always + environment: + - PYTHONPATH=/unispy-server/src:${PYTHONPATH:-} + - UNISPY_CONFIG=/unispy-server/common/config.json + - PYTHONUNBUFFERED=1 + volumes: + - ./:/unispy-server/ + ports: + - "6667:6667" + command: python -u src/frontends/gamespy/protocols/chat/applications/server_launcher.py + depends_on: + backends: + condition: service_healthy + networks: + - unispy + + gs: + image: unispy-python + container_name: unispy-gs + restart: always + environment: + - PYTHONPATH=/unispy-server/src:${PYTHONPATH:-} + - UNISPY_CONFIG=/unispy-server/common/config.json + - PYTHONUNBUFFERED=1 + volumes: + - ./:/unispy-server/ + ports: + - "29920:29920" + command: python -u src/frontends/gamespy/protocols/game_status/applications/server_launcher.py + depends_on: + backends: + condition: service_healthy + networks: + - unispy + + + + pcm: + image: unispy-python + container_name: unispy-pcm + restart: always + environment: + - PYTHONPATH=/unispy-server/src:${PYTHONPATH:-} + - UNISPY_CONFIG=/unispy-server/common/config.json + - PYTHONUNBUFFERED=1 + volumes: + - ./:/unispy-server/ + ports: + - "29900:29900" + command: python -u src/frontends/gamespy/protocols/presence_connection_manager/applications/server_launcher.py + depends_on: + backends: + condition: service_healthy + networks: + - unispy + psp: + image: unispy-python + container_name: unispy-psp + restart: always + environment: + - PYTHONPATH=/unispy-server/src:${PYTHONPATH:-} + - UNISPY_CONFIG=/unispy-server/common/config.json + - PYTHONUNBUFFERED=1 + volumes: + - ./:/unispy-server/ + ports: + - "29901:29901" + command: python -u src/frontends/gamespy/protocols/presence_search_player/applications/server_launcher.py + depends_on: + backends: + condition: service_healthy + networks: + - unispy + + qr: + image: unispy-python + container_name: unispy-qr + restart: always + environment: + - PYTHONPATH=/unispy-server/src:${PYTHONPATH:-} + - UNISPY_CONFIG=/unispy-server/common/config.json + - PYTHONUNBUFFERED=1 + volumes: + - ./:/unispy-server/ + ports: + - "27900:27900" + command: python -u src/frontends/gamespy/protocols/query_report/applications/server_launcher.py + depends_on: + backends: + condition: service_healthy + networks: + - unispy + + sb: + image: unispy-python + container_name: unispy-sb + restart: always + environment: + - PYTHONPATH=/unispy-server/src:${PYTHONPATH:-} + - UNISPY_CONFIG=/unispy-server/common/config.json + - PYTHONUNBUFFERED=1 + volumes: + - ./:/unispy-server/ + ports: + - "28910:28910" + - "28900:28900" + command: python -u src/frontends/gamespy/protocols/query_report/applications/server_launcher.py + depends_on: + backends: + condition: service_healthy + networks: + - unispy + + + natneg: + image: unispy-python + container_name: unispy-natneg + restart: always + environment: + - PYTHONPATH=/unispy-server/src:${PYTHONPATH:-} + - UNISPY_CONFIG=/unispy-server/common/config.json + - PYTHONUNBUFFERED=1 + volumes: + - ./:/unispy-server/ + ports: + - "27901:27901" + command: python -u src/frontends/gamespy/protocols/natneg/applications/server_launcher.py + depends_on: + backends: + condition: service_healthy + networks: + - unispy + + web: + image: unispy-python + container_name: unispy-web + restart: always + environment: + - PYTHONPATH=/unispy-server/src:${PYTHONPATH:-} + - UNISPY_CONFIG=/unispy-server/common/config.json + - PYTHONUNBUFFERED=1 + volumes: + - ./:/unispy-server/ + ports: + - "80:80" + command: python -u src/frontends/gamespy/protocols/web_services/applications/server_launcher.py + depends_on: + backends: + condition: service_healthy + networks: + - unispy + + # gtr: + # image: unispy-python + # container_name: unispy-gtr + # restart: always + # environment: + # - PYTHONPATH=/unispy-server/src:${PYTHONPATH:-} + # - UNISPY_CONFIG=/unispy-server/common/config.json + # - PYTHONUNBUFFERED=1 + # volumes: + # - ./:/unispy-server/ + # ports: + # - "10086:10086" + # command: python -u src/frontends/gamespy/protocols/game_traffic_relay/applications/server_launcher.py + # depends_on: + # backends: + # condition: service_healthy + # networks: + # - unispy + + + + +networks: + unispy: + external: true + name: unispy + driver: bridge \ No newline at end of file diff --git a/src/.devcontainer/devcontainer.json b/src/.devcontainer/devcontainer.json new file mode 100644 index 000000000..42e5ae6ff --- /dev/null +++ b/src/.devcontainer/devcontainer.json @@ -0,0 +1,44 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/python +{ + "name": "Python 3", + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "runArgs": [ + "--network=unispy", + "--name=unispy_server_dev", + "--add-host=unispy_backends:127.0.0.1" + ], + "image": "mcr.microsoft.com/devcontainers/python:1-3.12-bullseye", + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + // Use 'forwardPorts' to make a list of ports inside the container available locally. + "forwardPorts": [ + 29910, + 6667, + 29920, + 10086, + 27901, + 29900, + 29901, + 27900, + 28910, + 28900, + 80 + ], + // Use 'postCreateCommand' to run commands after the container is created. + "postCreateCommand": "pip3 install --user -r requirements.txt", + "customizations": { + "vscode": { + "extensions": [ + "ms-python.vscode-pylance@2024.8.2", + "ms-python.python@2024.14.1", + "ms-python.debugpy@2024.8.0", + "ms-python.autopep8@2025.2.0" + ] + } + } + // Configure tool-specific properties. + // "customizations": {}, + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} \ No newline at end of file diff --git a/src/.vscode/launch.json b/src/.vscode/launch.json new file mode 100644 index 000000000..1a94cc25d --- /dev/null +++ b/src/.vscode/launch.json @@ -0,0 +1,180 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python Debugger: Current File", + "type": "debugpy", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal", + "env": { + "PYTHONPATH": "${workspaceFolder}", + }, + "justMyCode": true + }, + { + "name": "backends", + "type": "debugpy", + "request": "launch", + "module": "uvicorn", + "args": [ + "backends.routers.home:app", // Replace with your module name if different + "--host", + "127.0.0.1", + "--port", + "8080", + "--reload", // Optional: enables auto-reload on code changes + "--reload-dir", + "${workspaceFolder}/backends" + ], + "console": "integratedTerminal", + "env": { + "PYTHONPATH": "${workspaceFolder}", + }, + "justMyCode": true + }, + { + "name": "frontends", + "type": "debugpy", + "request": "launch", + "program": "frontends/app.py", + "console": "integratedTerminal", + "args": [ + "--debug" + ], + "env": { + "PYTHONPATH": "${workspaceFolder}", + }, + "justMyCode": true + }, + { + "name": "pcm", + "type": "debugpy", + "request": "launch", + "program": "frontends/gamespy/protocols/presence_connection_manager/applications/server_launcher.py", + "console": "integratedTerminal", + "args": [ + "--debug" + ], + "env": { + "PYTHONPATH": "${workspaceFolder}", + }, + "justMyCode": true + }, + { + "name": "psp", + "type": "debugpy", + "request": "launch", + "program": "frontends/gamespy/protocols/presence_search_player/applications/server_launcher.py", + "console": "integratedTerminal", + "args": [ + "--debug" + ], + "env": { + "PYTHONPATH": "${workspaceFolder}", + }, + "justMyCode": true + }, + { + "name": "chat", + "type": "debugpy", + "request": "launch", + "program": "frontends/gamespy/protocols/chat/applications/server_launcher.py", + "args": [ + "--debug" + ], + "console": "integratedTerminal", + "env": { + "PYTHONPATH": "${workspaceFolder}", + }, + "justMyCode": true + }, + { + "name": "gs", + "type": "debugpy", + "request": "launch", + "program": "frontends/gamespy/protocols/game_status/applications/server_launcher.py", + "console": "integratedTerminal", + "args": [ + "--debug" + ], + "env": { + "PYTHONPATH": "${workspaceFolder}", + }, + "justMyCode": true + }, + { + "name": "gtr", + "type": "debugpy", + "request": "launch", + "program": "frontends/gamespy/protocols/game_traffic_relay/applications/server_launcher.py", + "console": "integratedTerminal", + "args": [ + "--debug" + ], + "env": { + "PYTHONPATH": "${workspaceFolder}", + }, + "justMyCode": true + }, + { + "name": "natneg", + "type": "debugpy", + "request": "launch", + "program": "frontends/gamespy/protocols/natneg/applications/server_launcher.py", + "console": "integratedTerminal", + "args": [ + "--debug" + ], + "env": { + "PYTHONPATH": "${workspaceFolder}", + }, + "justMyCode": true + }, + { + "name": "qr", + "type": "debugpy", + "request": "launch", + "program": "frontends/gamespy/protocols/query_report/applications/server_launcher.py", + "console": "integratedTerminal", + "args": [ + "--debug" + ], + "env": { + "PYTHONPATH": "${workspaceFolder}", + }, + "justMyCode": true + }, + { + "name": "sb", + "type": "debugpy", + "request": "launch", + "program": "frontends/gamespy/protocols/server_browser/applications/server_launcher.py", + "console": "integratedTerminal", + "args": [ + "--debug" + ], + "env": { + "PYTHONPATH": "${workspaceFolder}", + }, + "justMyCode": true + }, + { + "name": "web", + "type": "debugpy", + "request": "launch", + "program": "frontends/gamespy/protocols/web_services/applications/server_launcher.py", + "console": "integratedTerminal", + "args": [ + "--debug" + ], + "env": { + "PYTHONPATH": "${workspaceFolder}", + }, + "justMyCode": true + }, + ], +} \ No newline at end of file diff --git a/src/.vscode/settings.json b/src/.vscode/settings.json new file mode 100644 index 000000000..cbe3eecc2 --- /dev/null +++ b/src/.vscode/settings.json @@ -0,0 +1,14 @@ +{ + "python.analysis.typeCheckingMode": "basic", + "workbench.iconTheme": "material-icon-theme", + "python.testing.unittestArgs": [ + "-v", + "-s", + ".", + "-p", + "*test*.py" + ], + "python.testing.pytestEnabled": false, + "python.testing.unittestEnabled": true, + "python.analysis.enablePytestSupport": false, +} \ No newline at end of file diff --git a/src/Contribute.md b/src/Contribute.md new file mode 100644 index 000000000..fff0a246d --- /dev/null +++ b/src/Contribute.md @@ -0,0 +1,18 @@ +```python + +class BaseClass: + """ + We use class static member only to type hint the class instance member + Do not initialize the class static member + """ + _property1:type1 + _property2:type2 + + + def __init__(self): + # if the property do not have default value it must be initialized as None + self._property1 = None + # In the base class we have to check whether the _property has been initialized, if not we init it + if self._property1 is not None: + self._property2 = value2 +``` \ No newline at end of file diff --git a/src/Libraries/Core/src/Abstraction/BaseClass/ClientBase.cs b/src/Libraries/Core/src/Abstraction/BaseClass/ClientBase.cs deleted file mode 100644 index 80ca10bfe..000000000 --- a/src/Libraries/Core/src/Abstraction/BaseClass/ClientBase.cs +++ /dev/null @@ -1,182 +0,0 @@ -using System; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Encryption; -using UniSpy.Server.Core.Logging; -using UniSpy.Server.Core.Extension; -using System.Threading.Tasks; - -namespace UniSpy.Server.Core.Abstraction.BaseClass -{ - public abstract class ClientBase : IClient, ITestClient, IDisposable - { - public IServer Server { get; private set; } - public IConnection Connection { get; private set; } - public ICryptography Crypto { get; set; } - public ClientInfoBase Info { get; protected set; } - /// - /// The timer to count and invoke some event - /// - protected EasyTimer _timer { get; set; } - /// - /// Is logging the raw byte[] requests - /// - public bool IsLogRaw { get; protected set; } - public ClientBase(IConnection connection, IServer server) - { - Connection = connection; - Server = server; - EventBinding(); - ClientManagerBase.AddClient(this); - } - protected virtual void EventBinding() - { - switch (Connection.ConnectionType) - { - case NetworkConnectionType.Tcp: - ((ITcpConnection)Connection).OnReceive += OnReceived; - ((ITcpConnection)Connection).OnConnect += OnConnected; - ((ITcpConnection)Connection).OnDisconnect += OnDisconnected; - break; - case NetworkConnectionType.Udp: - ((IUdpConnection)Connection).OnReceive += OnReceived; - _timer = new EasyTimer(TimeSpan.FromHours(1), TimeSpan.FromMinutes(1), CheckExpiredClient); - break; - case NetworkConnectionType.Http: - ((IHttpConnection)Connection).OnReceive += OnReceived; - ((IHttpConnection)Connection).OnConnect += OnConnected; - ((IHttpConnection)Connection).OnDisconnect += OnDisconnected; - break; - case NetworkConnectionType.Test: - this.LogVerbose("Using unit-test mock connection."); - break; - default: - throw new Exception("Unsupported connection type."); - } - } - /// - /// Only work for tcp - /// - protected virtual void OnConnected() => ClientManagerBase.AddClient(this); - - /// - /// Only work for tcp - /// - protected virtual void OnDisconnected() => Dispose(); - - protected abstract ISwitcher CreateSwitcher(object buffer); - /// - /// Invoked when received message from game client - /// - /// Byte[], string, Http - protected virtual void OnReceived(object buffer) - { - switch (Connection.ConnectionType) - { - case NetworkConnectionType.Tcp: - goto default; - case NetworkConnectionType.Udp: - _timer.RefreshLastActiveTime(); - goto default; - case NetworkConnectionType.Http: - var tempBuffer = ((IHttpRequest)buffer).Body; - this.LogNetworkReceiving(tempBuffer); - break; - default: - buffer = DecryptMessage((byte[])buffer); - this.LogNetworkReceiving((byte[])buffer); - break; - } - // we let child class to create swicher for us - var switcher = CreateSwitcher(buffer); - if (System.Diagnostics.Debugger.IsAttached) - { - switcher.Handle(); - } - else - { - Task.Run(() => switcher.Handle()); - } - } - protected virtual byte[] DecryptMessage(byte[] buffer) - { - if (Crypto is not null) - { - return Crypto.Decrypt(buffer); - } - else - { - return buffer; - } - } - /// - /// Check if the udp client is expired, - /// this method will only be invoked by UdpServer - /// - protected void CheckExpiredClient() - { - // we calculate the interval between last packe and current time - if (_timer.IsExpired) - { - Dispose(); - } - } - - public void Dispose() - { - this.LogDebug("client disposed."); - switch (Connection.ConnectionType) - { - case NetworkConnectionType.Tcp: - ((ITcpConnection)Connection).OnReceive -= OnReceived; - ((ITcpConnection)Connection).OnConnect -= OnConnected; - ((ITcpConnection)Connection).OnDisconnect -= OnDisconnected; - ClientManagerBase.RemoveClient(this); - break; - case NetworkConnectionType.Udp: - ((IUdpConnection)Connection).OnReceive -= OnReceived; - _timer.Dispose(); - ClientManagerBase.RemoveClient(this); - break; - case NetworkConnectionType.Http: - ((IHttpConnection)Connection).OnReceive -= OnReceived; - break; - } - } - /// - /// Sending IResponse to client(ciphertext or plaintext) - /// - /// - public void Send(IResponse response) - { - byte[] buffer = null; - response.Build(); - if (response.SendingBuffer.GetType() == typeof(string)) - { - buffer = UniSpyEncoding.GetBytes((string)response.SendingBuffer); - } - else - { - buffer = (byte[])response.SendingBuffer; - } - this.LogNetworkSending(buffer); - //Encrypt the response if Crypto is not null - if (Crypto is not null) - { - buffer = Crypto.Encrypt(buffer); - } - Connection.Send(buffer); - } - /// - /// Received function for unit-test - /// - /// Raw byte array - void ITestClient.TestReceived(byte[] buffer) - { - if (Crypto is not null) - { - Crypto = null; - } - OnReceived(buffer); - } - } -} diff --git a/src/Libraries/Core/src/Abstraction/BaseClass/ClientInfoBase.cs b/src/Libraries/Core/src/Abstraction/BaseClass/ClientInfoBase.cs deleted file mode 100644 index b2349b10e..000000000 --- a/src/Libraries/Core/src/Abstraction/BaseClass/ClientInfoBase.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace UniSpy.Server.Core.Abstraction.BaseClass -{ - public abstract class ClientInfoBase - { - public ClientInfoBase() - { - } - } -} \ No newline at end of file diff --git a/src/Libraries/Core/src/Abstraction/BaseClass/ClientManagerBase.cs b/src/Libraries/Core/src/Abstraction/BaseClass/ClientManagerBase.cs deleted file mode 100644 index bf21e097d..000000000 --- a/src/Libraries/Core/src/Abstraction/BaseClass/ClientManagerBase.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.Collections.Concurrent; -using System.Net; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.Core.Abstraction.BaseClass -{ - /// - /// This class provide global access to client pool, - /// if you need search client in specific server, - /// please inherit this class and create static method. - /// - public abstract class ClientManagerBase - { - public static readonly ConcurrentDictionary ClientPool = new ConcurrentDictionary(); - public static void AddClient(IClient client) - { - ClientPool.TryAdd(client.Connection.RemoteIPEndPoint, client); - } - public static IClient RemoveClient(IClient client) - { - return RemoveClient(client.Connection.RemoteIPEndPoint); - } - public static IClient RemoveClient(IPEndPoint endPoint) - { - ClientPool.TryRemove(endPoint, out var client); - return client; - } - public static IClient GetClient(IPEndPoint endPoint) - { - if (ClientPool.TryGetValue(endPoint, out var client)) - { - return client; - } - else - { - return null; - } - } - } -} \ No newline at end of file diff --git a/src/Libraries/Core/src/Abstraction/BaseClass/CmdHandlerBase.cs b/src/Libraries/Core/src/Abstraction/BaseClass/CmdHandlerBase.cs deleted file mode 100755 index a26e10bd7..000000000 --- a/src/Libraries/Core/src/Abstraction/BaseClass/CmdHandlerBase.cs +++ /dev/null @@ -1,86 +0,0 @@ -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Logging; - -namespace UniSpy.Server.Core.Abstraction.BaseClass -{ - public abstract class CmdHandlerBase : IHandler, ITestHandler - { - protected IClient _client { get; } - protected IRequest _request { get; } - protected ResultBase _result { get; set; } - protected IResponse _response { get; set; } - - RequestBase ITestHandler.Request => (RequestBase)_request; - ResultBase ITestHandler.Result => (ResultBase)_result; - ResponseBase ITestHandler.Response => (ResponseBase)_response; - - public CmdHandlerBase(IClient client, IRequest request) - { - _client = client; - _request = request; - } - public virtual void Handle() - { - try - { - // we first log this class - LogCurrentClass(); - // then we handle it - RequestCheck(); - DataOperation(); - ResponseConstruct(); - if (_response is null) - { - return; - } - Response(); - } - catch (UniSpy.Exception ex) - { - HandleException(ex); - } - } - protected virtual void RequestCheck() - { - // if there is gamespy raw request we convert it to unispy request - if (_request.RawRequest is not null) - { - _request.Parse(); - } - } - protected virtual void DataOperation() { } - protected virtual void ResponseConstruct() { } - /// - /// The response process - /// - protected virtual void Response() - { - _client.Send(_response); - } - - protected virtual void HandleException(System.Exception ex) - { - // we only log exception message when this message is UniSpy.Exception - if (ex is UniSpy.Exception) - { - _client.LogError(ex.Message); - } - else - { - _client.LogError(ex.ToString()); - } - } - - private void LogCurrentClass() - { - if (_client is null) - { - LogWriter.LogCurrentClass(this); - } - else - { - _client.LogCurrentClass(this); - } - } - } -} diff --git a/src/Libraries/Core/src/Abstraction/BaseClass/CmdSwitcherBase.cs b/src/Libraries/Core/src/Abstraction/BaseClass/CmdSwitcherBase.cs deleted file mode 100755 index 2b4b88104..000000000 --- a/src/Libraries/Core/src/Abstraction/BaseClass/CmdSwitcherBase.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Logging; - -namespace UniSpy.Server.Core.Abstraction.BaseClass -{ - public abstract class CmdSwitcherBase : ISwitcher - { - protected IClient _client; - protected object _rawRequest { get; private set; } - protected List> _requests { get; private set; } - protected List _handlers { get; private set; } - - public CmdSwitcherBase(IClient client, object rawRequest) - { - _client = client; - _rawRequest = rawRequest; - _handlers = new List(); - _requests = new List>(); - } - - public virtual void Handle() - { - try - { - //First we process the message split it to raw requests. - ProcessRawRequest(); - // Then we process the raw requests to UniSpy requests. - if (_requests.Count == 0) - { - return; - } - // Then we create UniSpy handlers by UniSpy requests. - foreach (var rawRequest in _requests) - { - var handler = CreateCmdHandlers(rawRequest.Key, rawRequest.Value); - if (handler is null) - { - _client.LogWarn("Request ignored."); - continue; - } - _handlers.Add(handler); - } - if (_handlers.Count == 0) - { - return; - } - - // TODO changes foreach to parallel foreach - foreach (var handler in _handlers) - { - handler.Handle(); - } - } - catch (UniSpy.Exception e) - { - _client.LogError(e.Message); - } - } - /// - /// Split the raw requests into single raw request - /// get the request type and create dictionary of (request type, request) - /// - /// request type, single request - protected abstract void ProcessRawRequest(); - /// - /// Call this in size - /// - /// - /// - protected abstract IHandler CreateCmdHandlers(object name, object rawRequest); - } -} diff --git a/src/Libraries/Core/src/Abstraction/BaseClass/EncParamBase.cs b/src/Libraries/Core/src/Abstraction/BaseClass/EncParamBase.cs deleted file mode 100644 index ce7f39b06..000000000 --- a/src/Libraries/Core/src/Abstraction/BaseClass/EncParamBase.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace UniSpy.Server.Core.Abstraction.BaseClass -{ - /// - /// The base class of encryption parameters - /// IEncryption can use the parameter to encrypt message - /// - public abstract record EncParamBase { } -} \ No newline at end of file diff --git a/src/Libraries/Core/src/Abstraction/BaseClass/RedisChannel.cs b/src/Libraries/Core/src/Abstraction/BaseClass/RedisChannel.cs deleted file mode 100755 index 33e92a26b..000000000 --- a/src/Libraries/Core/src/Abstraction/BaseClass/RedisChannel.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; -using Newtonsoft.Json; -using StackExchange.Redis; -using UniSpy.Server.Core.Config; - -namespace UniSpy.Server.Core.Abstraction.BaseClass -{ - - public abstract class RedisChannelBase : IDisposable - { - public delegate void OnReceivedMessageEventHandler(T message); - public event OnReceivedMessageEventHandler OnReceived; - protected string _redisChannelName; - /// - /// Get all subscriber in Redis - /// - protected ISubscriber _subscriber = ConfigManager.Config.Redis.RedisConnection.GetSubscriber(); - public bool IsStarted { get; private set; } - public RedisChannelBase(string redisChannelName) - { - _redisChannelName = redisChannelName; - OnReceived += ReceivedMessage; - } - - /// - /// Run StartSubscribe manually - /// Some server only require publish message - /// so they do not need to run this function - /// - public void Subscribe() - { - if (IsStarted == false) - { - _subscriber.Subscribe(_redisChannelName, (channel, message) - => - { - T msg = DeserializeMessage(message); - OnReceived(msg); - }); - IsStarted = true; - } - } - - public virtual void ReceivedMessage(T message) - { - - } - - public virtual void PublishMessage(T message) - { - if (message is null) - { - return; - } - string jsonStr = SerializeMessage(message); - _subscriber.Publish(_redisChannelName, jsonStr); - } - - protected virtual string SerializeMessage(T message) => JsonConvert.SerializeObject(message); - - protected virtual T DeserializeMessage(string message) => JsonConvert.DeserializeObject(message); - public void Unsubscribe() - { - _subscriber.Unsubscribe(_redisChannelName); - OnReceived -= ReceivedMessage; - } - public void Dispose() => Unsubscribe(); - } -} diff --git a/src/Libraries/Core/src/Abstraction/BaseClass/RedisClient.cs b/src/Libraries/Core/src/Abstraction/BaseClass/RedisClient.cs deleted file mode 100644 index 46dc8caff..000000000 --- a/src/Libraries/Core/src/Abstraction/BaseClass/RedisClient.cs +++ /dev/null @@ -1,12 +0,0 @@ -using StackExchange.Redis; -using UniSpy.Server.Core.Config; - -namespace UniSpy.Server.Core.Abstraction.BaseClass -{ - public class RedisClient : LinqToRedis.RedisClient where TValue : RedisKeyValueObject - { - public RedisClient() : base(ConfigManager.Config.Redis.RedisConnection) - { - } - } -} \ No newline at end of file diff --git a/src/Libraries/Core/src/Abstraction/BaseClass/RedisKeyValueObject.cs b/src/Libraries/Core/src/Abstraction/BaseClass/RedisKeyValueObject.cs deleted file mode 100644 index ccf61d73e..000000000 --- a/src/Libraries/Core/src/Abstraction/BaseClass/RedisKeyValueObject.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using UniSpy.Server.Core.Extension.Redis; - -namespace UniSpy.Server.Core.Abstraction.BaseClass -{ - public record RedisKeyValueObject : LinqToRedis.RedisKeyValueObject - { - public RedisKeyValueObject() - { - } - - public RedisKeyValueObject(RedisDbNumber db, TimeSpan? expireTime = null) : base((int)db, expireTime) - { - } - } -} \ No newline at end of file diff --git a/src/Libraries/Core/src/Abstraction/BaseClass/RequestBase.cs b/src/Libraries/Core/src/Abstraction/BaseClass/RequestBase.cs deleted file mode 100755 index 21db0c3ff..000000000 --- a/src/Libraries/Core/src/Abstraction/BaseClass/RequestBase.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Xml.Serialization; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.Core.Abstraction.BaseClass -{ - public abstract class RequestBase : IRequest - { - [XmlIgnoreAttribute] - public object CommandName { get; protected set; } - [XmlIgnoreAttribute] - public object RawRequest { get; protected set; } - public RequestBase() { } - public RequestBase(object rawRequest) - { - RawRequest = rawRequest; - } - - public abstract void Parse(); - } -} diff --git a/src/Libraries/Core/src/Abstraction/BaseClass/ResponseBase.cs b/src/Libraries/Core/src/Abstraction/BaseClass/ResponseBase.cs deleted file mode 100755 index f86195035..000000000 --- a/src/Libraries/Core/src/Abstraction/BaseClass/ResponseBase.cs +++ /dev/null @@ -1,37 +0,0 @@ -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.Core.Abstraction.BaseClass -{ - public abstract class ResponseBase : IResponse - { - /// - /// Represents the plaintext response data - /// - public object SendingBuffer { get; protected set; } - - /* - /// - /// Create new inhereted type of this property to make access easier without type convertion every time - /// - public ResultBase Result => _result; - /// - /// Create new inhereted type of this property to make access easier without type convertion every time - /// - public RequestBase Request => _request; - */ - - protected ResultBase _result { get; } - protected RequestBase _request { get; } - protected IClient _client { get; } - public ResponseBase(RequestBase request, ResultBase result) - { - _request = request; - _result = result; - } - - /// - /// Build response message - /// - public abstract void Build(); - } -} diff --git a/src/Libraries/Core/src/Abstraction/BaseClass/ResultBase.cs b/src/Libraries/Core/src/Abstraction/BaseClass/ResultBase.cs deleted file mode 100755 index c014f07a0..000000000 --- a/src/Libraries/Core/src/Abstraction/BaseClass/ResultBase.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace UniSpy.Server.Core.Abstraction.BaseClass -{ - public abstract class ResultBase - { - public ResultBase() - { - } - } -} diff --git a/src/Libraries/Core/src/Abstraction/BaseClass/ServerBase.cs b/src/Libraries/Core/src/Abstraction/BaseClass/ServerBase.cs deleted file mode 100644 index 961f51dfb..000000000 --- a/src/Libraries/Core/src/Abstraction/BaseClass/ServerBase.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.Linq; -using System.Net; -using Newtonsoft.Json; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Config; - -namespace UniSpy.Server.Core.Abstraction.BaseClass -{ - /// - /// Represent UniSpy server instance abstraction - /// - public abstract class ServerBase : IServer - { - public Guid Id { get; private set; } - public IPEndPoint ListeningIPEndPoint { get; private set; } - public IPEndPoint PublicIPEndPoint { get; private set; } - [JsonIgnore] - public IConnectionManager ConnectionManager; - protected UniSpyServerConfig _cfg; - public string Name { get; } = _name; - /// - /// This name is for reading from child class, indicating the server name - /// - protected static string _name; - - public ServerBase() - { - SetServerInfo(); - ConnectionManager = CreateConnectionManager(ListeningIPEndPoint); - ConnectionManager.OnInitialization += HandleConnectionInitialization; - } - /// - /// This constructor is for unittests - /// - public ServerBase(IConnectionManager manager) - { - SetServerInfo(); - ConnectionManager = manager; - } - public void SetServerInfo() - { - _cfg = ConfigManager.Config.Servers.Where(s => s.ServerName == _name).First(); - Id = _cfg.ServerID; - ListeningIPEndPoint = _cfg.ListeningIPEndPoint; - PublicIPEndPoint = _cfg.PublicIPEndPoint; - } - protected abstract IConnectionManager CreateConnectionManager(IPEndPoint endPoint); - private IClient HandleConnectionInitialization(IConnection connection) - { - var client = ClientManagerBase.GetClient(connection.RemoteIPEndPoint); - if (client is null) - { - client = CreateClient(connection); - ClientManagerBase.AddClient(client); - } - return client; - } - protected abstract IClient CreateClient(IConnection connection); - - public virtual void Start() => ConnectionManager.Start(); - } -} \ No newline at end of file diff --git a/src/Libraries/Core/src/Abstraction/BaseClass/ServerLauncherBase.cs b/src/Libraries/Core/src/Abstraction/BaseClass/ServerLauncherBase.cs deleted file mode 100755 index a2fad800c..000000000 --- a/src/Libraries/Core/src/Abstraction/BaseClass/ServerLauncherBase.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using ConsoleTables; -using Figgle; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Config; -using UniSpy.Server.Core.Database.DatabaseModel; -using System.Collections.Generic; - -namespace UniSpy.Server.Core.Abstraction.BaseClass.Factory -{ - /// - /// Each server launcher only launch an instance of IServer - /// - public abstract class ServerLauncherBase - { - /// - /// UniSpy server version - /// - public static readonly string Version = "0.8.1"; - - public static List ServerInstances { get; protected set; } = new List(); - public ServerLauncherBase() - { - } - public virtual void Start() - { - ShowUniSpyLogo(); - ConnectMySql(); - ConnectRedis(); - LaunchServer(); - } - protected abstract List LaunchNetworkService(); - protected virtual void LaunchServer() - { - ServerInstances = LaunchNetworkService(); - if (ServerInstances.Count == 0) - { - throw new Exception("Server created failed"); - } - var table = new ConsoleTable("Server Name", "Listening Address", "Listening Port"); - Console.Title = $"UniSpyServer {Version} - {ServerInstances[0].Name}"; - - foreach (var server in ServerInstances) - { - server.Start(); - table.AddRow(server.Name, server.ListeningIPEndPoint.Address, server.ListeningIPEndPoint.Port); - } - table.Write(ConsoleTables.Format.Alternative); - Console.WriteLine("Server successfully started!"); - } - - protected void ConnectRedis() - { - var redisConfig = ConfigManager.Config.Redis; - try - { - var r = StackExchange.Redis.ConnectionMultiplexer.Connect(redisConfig.ConnectionString); - r.Dispose(); - } - catch (System.Exception e) - { - throw new Exception("Can not connect to Redis", e); - } - Console.WriteLine($"Successfully connected to Redis at {redisConfig.Server}:{redisConfig.Port}"); - } - protected void ConnectMySql() - { - //Determine which database is used and establish the database connection. - var dbConfig = ConfigManager.Config.Database; - if (!new UniSpyContext().Database.CanConnect()) - { - throw new Exception($"Can not connect to {dbConfig.Type}!"); - } - - Console.WriteLine($"Successfully connected to {dbConfig.Type} at {dbConfig.Server}:{dbConfig.Port}"); - } - protected static void ShowUniSpyLogo() - { - Console.WriteLine(""); - Console.WriteLine(FiggleFonts.Small.Render("UniSpy.Server")); - Console.WriteLine(@"Version: " + Version); - } - } -} diff --git a/src/Libraries/Core/src/Abstraction/Interface/IClient.cs b/src/Libraries/Core/src/Abstraction/Interface/IClient.cs deleted file mode 100644 index 10f1f7500..000000000 --- a/src/Libraries/Core/src/Abstraction/Interface/IClient.cs +++ /dev/null @@ -1,23 +0,0 @@ -using UniSpy.Server.Core.Abstraction.BaseClass; - -namespace UniSpy.Server.Core.Abstraction.Interface -{ - public interface ITestClient - { - public void TestReceived(byte[] buffer); - } - public interface IClient - { - /// - /// whether log raw request and response message bytes - /// - /// - bool IsLogRaw { get; } - IConnection Connection { get; } - IServer Server { get; } - ICryptography Crypto { get; } - // we store client info here - ClientInfoBase Info { get; } - public void Send(IResponse response); - } -} \ No newline at end of file diff --git a/src/Libraries/Core/src/Abstraction/Interface/IConnection.cs b/src/Libraries/Core/src/Abstraction/Interface/IConnection.cs deleted file mode 100644 index 58170bc98..000000000 --- a/src/Libraries/Core/src/Abstraction/Interface/IConnection.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.Net; -using UniSpy.Server.Core.Events; - -namespace UniSpy.Server.Core.Abstraction.Interface -{ - - public enum NetworkConnectionType - { - Tcp, - Udp, - Http, - Https, - Test, - } - /// - /// Represent a remote connection, tcp, udp, http etc. - /// - public interface IConnection - { - event OnReceivedEventHandler OnReceive; - IConnectionManager Manager { get; } - IPEndPoint RemoteIPEndPoint { get; } - void Send(string response); - void Send(byte[] response); - NetworkConnectionType ConnectionType { get; } - } - /// - /// Represent a udp connection - /// - public interface IUdpConnection : IConnection - { - // public TimeSpan ConnectionExistedTime { get; } - void Send(IPEndPoint endPoint, byte[] response); - void Send(IPEndPoint endPoint, string response); - } - /// - /// Represent a tcp connection - /// - public interface ITcpConnection : IConnection - { - event OnConnectedEventHandler OnConnect; - event OnDisconnectedEventHandler OnDisconnect; - void Disconnect(); - } - public interface IHttpConnection : ITcpConnection - { - } - - public interface IConnectionManager - { - event OnConnectingEventHandler OnInitialization; - void Start(); - } -} diff --git a/src/Libraries/Core/src/Abstraction/Interface/IEncryption.cs b/src/Libraries/Core/src/Abstraction/Interface/IEncryption.cs deleted file mode 100644 index cac6ad841..000000000 --- a/src/Libraries/Core/src/Abstraction/Interface/IEncryption.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace UniSpy.Server.Core.Abstraction.Interface -{ - public interface ICryptography - { - byte[] Encrypt(byte[] data); - byte[] Decrypt(byte[] data); - } -} \ No newline at end of file diff --git a/src/Libraries/Core/src/Abstraction/Interface/IHandler.cs b/src/Libraries/Core/src/Abstraction/Interface/IHandler.cs deleted file mode 100755 index 25f519164..000000000 --- a/src/Libraries/Core/src/Abstraction/Interface/IHandler.cs +++ /dev/null @@ -1,15 +0,0 @@ -using UniSpy.Server.Core.Abstraction.BaseClass; - -namespace UniSpy.Server.Core.Abstraction.Interface -{ - public interface IHandler - { - void Handle(); - } - public interface ITestHandler - { - RequestBase Request { get; } - ResultBase Result { get; } - ResponseBase Response { get; } - } -} diff --git a/src/Libraries/Core/src/Abstraction/Interface/IHttpRequest.cs b/src/Libraries/Core/src/Abstraction/Interface/IHttpRequest.cs deleted file mode 100644 index 8c1db0864..000000000 --- a/src/Libraries/Core/src/Abstraction/Interface/IHttpRequest.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace UniSpy.Server.Core.Abstraction.Interface -{ - public interface IHttpRequest - { - byte[] BodyBytes { get; } - string Body { get; } - long Cookies { get; } - long Headers { get; } - string Protocol { get; } - string Url { get; } - string Method { get; } - bool KeepAlive { get; } - } -} \ No newline at end of file diff --git a/src/Libraries/Core/src/Abstraction/Interface/ILogger.cs b/src/Libraries/Core/src/Abstraction/Interface/ILogger.cs deleted file mode 100644 index c5c68bec9..000000000 --- a/src/Libraries/Core/src/Abstraction/Interface/ILogger.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Net; - -namespace UniSpy.Server.Core.Abstraction.Interface -{ - public interface ILogger - { - public void LogInfo(string message); - public void LogVerbose(string message); - public void LogDebug(string message); - public void LogWarn(string messsage); - public void LogError(string message); - public void LogNetworkReceiving(byte[] message); - public void LogNetworkReceiving(string message); - public void LogNetworkSending(byte[] message); - public void LogNetworkSending(string message); - public void LogNetworkForwarding(IPEndPoint receiver, byte[] message); - public void LogNetworkForwarding(IPEndPoint receiver, string message); - public void LogNetworkMultiCast(byte[] message); - public void LogNetworkMultiCast(string message); - } -} \ No newline at end of file diff --git a/src/Libraries/Core/src/Abstraction/Interface/IRedisChannelEvent.cs b/src/Libraries/Core/src/Abstraction/Interface/IRedisChannelEvent.cs deleted file mode 100755 index 437c788a1..000000000 --- a/src/Libraries/Core/src/Abstraction/Interface/IRedisChannelEvent.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace UniSpy.Server.Core.Abstraction.Interface -{ - public interface IRedisChannelEvent - { - void StartSubscribe(); - void ReceivedMessage(); - void PublishMessage(); - } -} diff --git a/src/Libraries/Core/src/Abstraction/Interface/IRequest.cs b/src/Libraries/Core/src/Abstraction/Interface/IRequest.cs deleted file mode 100755 index 13928fb93..000000000 --- a/src/Libraries/Core/src/Abstraction/Interface/IRequest.cs +++ /dev/null @@ -1,10 +0,0 @@ - -namespace UniSpy.Server.Core.Abstraction.Interface -{ - public interface IRequest - { - object CommandName { get; } - object RawRequest { get; } - void Parse(); - } -} diff --git a/src/Libraries/Core/src/Abstraction/Interface/IResponse.cs b/src/Libraries/Core/src/Abstraction/Interface/IResponse.cs deleted file mode 100644 index fb3ef883d..000000000 --- a/src/Libraries/Core/src/Abstraction/Interface/IResponse.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace UniSpy.Server.Core.Abstraction.Interface -{ - public interface IResponse - { - object SendingBuffer { get; } - void Build(); - } -} diff --git a/src/Libraries/Core/src/Abstraction/Interface/IServer.cs b/src/Libraries/Core/src/Abstraction/Interface/IServer.cs deleted file mode 100755 index af1c094ea..000000000 --- a/src/Libraries/Core/src/Abstraction/Interface/IServer.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Net; -using StackExchange.Redis; - -namespace UniSpy.Server.Core.Abstraction.Interface -{ - /// - /// Represents unispy server instance - /// - public interface IServer - { - static IConnectionMultiplexer RedisConnection { get; } - Guid Id { get; } - string Name { get; } - IPEndPoint ListeningIPEndPoint { get; } - IPEndPoint PublicIPEndPoint { get; } - // UniSpyServerConfig ServerConfig { get; } - void Start(); - } -} diff --git a/src/Libraries/Core/src/Abstraction/Interface/ISwicher.cs b/src/Libraries/Core/src/Abstraction/Interface/ISwicher.cs deleted file mode 100644 index 739bc5ab1..000000000 --- a/src/Libraries/Core/src/Abstraction/Interface/ISwicher.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace UniSpy.Server.Core.Abstraction.Interface -{ - public interface ISwitcher - { - void Handle(); - } -} \ No newline at end of file diff --git a/src/Libraries/Core/src/Config/ConfigManager.cs b/src/Libraries/Core/src/Config/ConfigManager.cs deleted file mode 100755 index e6368aac1..000000000 --- a/src/Libraries/Core/src/Config/ConfigManager.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Newtonsoft.Json; -using System.IO; - -namespace UniSpy.Server.Core.Config -{ - public class ConfigManager - { - public static bool IsConfigFileExist => File.Exists(ConfigPath); - public static UniSpyConfig Config = LoadConfigFile(); - public const string ConfigPath = @"UniSpyServerConfig.json"; - private static UniSpyConfig LoadConfigFile() - { - if (!IsConfigFileExist) - { - throw new UniSpy.Exception("UniSpy server config file not found"); - } - using (StreamReader fstream = File.OpenText(ConfigPath)) - { - return JsonConvert.DeserializeObject(fstream.ReadToEnd()); - } - } - } -} diff --git a/src/Libraries/Core/src/Config/UniSpyConfig.cs b/src/Libraries/Core/src/Config/UniSpyConfig.cs deleted file mode 100755 index 6b384b643..000000000 --- a/src/Libraries/Core/src/Config/UniSpyConfig.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net; -using Newtonsoft.Json; -using Serilog.Events; -using StackExchange.Redis; -using UniSpy.Server.Core.Database; - -namespace UniSpy.Server.Core.Config -{ - public class UniSpyConfig - { - public UniSpyDatabaseConfig Database; - public UniSpyRedisConfig Redis; - public List Servers; - public LogEventLevel MinimumLogLevel; - } - public class UniSpyDatabaseConfig - { - public string ConnectionString => - $"Server={Server};" - + $"Port={Port};" - + $"Database={Database};" - + $"Username={Username};" - + $"Password={Password};" - + $"SSL Mode={SSLMode};" - + $"Trust Server Certificate={TrustServerCert};" - + $"SSL Certificate={SSLCert};" - + $"SSL Key={SSLKey};" - + $"SSL Password={SSLPassword};" - + $"Root Certificate={RootCert};"; - public DatabaseType Type; - public string Server; - public int Port; - public string Database; - public string Username; - public string Password; - public string SSLMode; - public bool TrustServerCert; - public string SSLCert; - public string SSLKey; - public string SSLPassword; - public string RootCert; - } - public class UniSpyRedisConfig - { - public string ConnectionString => $"{Server}:{Port},user={User},password={Password},ssl={SSL},sslHost={SSLHost}"; - public string Server; - public int Port; - public string User; - public string Password; - public bool SSL; - public string SSLHost; - [JsonIgnore] - public IConnectionMultiplexer RedisConnection => ConnectionMultiplexer.Connect(ConnectionString); - } - public class UniSpyServerConfig - { - public Guid ServerID; - public string ServerName; - public IPEndPoint ListeningIPEndPoint => new IPEndPoint(IPAddress.Any, ListeningPort); - public IPEndPoint PublicIPEndPoint => new IPEndPoint(IPAddress.Parse(PublicAddress), ListeningPort); - public string PublicAddress; - public int ListeningPort; - } -} diff --git a/src/Libraries/Core/src/Database/DatabaseModel/Addrequest.cs b/src/Libraries/Core/src/Database/DatabaseModel/Addrequest.cs deleted file mode 100644 index e7f60066c..000000000 --- a/src/Libraries/Core/src/Database/DatabaseModel/Addrequest.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace UniSpy.Server.Core.Database.DatabaseModel -{ - /// - /// Friend request. - /// - public partial class Addrequest - { - public int Addrequestid { get; set; } - public int ProfileId { get; set; } - public int Namespaceid { get; set; } - public int Targetid { get; set; } - public string Reason { get; set; } = null!; - public string Syncrequested { get; set; } = null!; - - public virtual Profile Profile { get; set; } = null!; - } -} diff --git a/src/Libraries/Core/src/Database/DatabaseModel/Blocked.cs b/src/Libraries/Core/src/Database/DatabaseModel/Blocked.cs deleted file mode 100644 index 82936e98d..000000000 --- a/src/Libraries/Core/src/Database/DatabaseModel/Blocked.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace UniSpy.Server.Core.Database.DatabaseModel -{ - /// - /// Block list. - /// - public partial class Blocked - { - public int Blockid { get; set; } - public int ProfileId { get; set; } - public int Namespaceid { get; set; } - public int Targetid { get; set; } - - public virtual Profile Profile { get; set; } = null!; - } -} diff --git a/src/Libraries/Core/src/Database/DatabaseModel/Friend.cs b/src/Libraries/Core/src/Database/DatabaseModel/Friend.cs deleted file mode 100644 index 325081a31..000000000 --- a/src/Libraries/Core/src/Database/DatabaseModel/Friend.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace UniSpy.Server.Core.Database.DatabaseModel -{ - /// - /// Friend list. - /// - public partial class Friend - { - public int Friendid { get; set; } - public int ProfileId { get; set; } - public int Namespaceid { get; set; } - public int Targetid { get; set; } - - public virtual Profile Profile { get; set; } = null!; - } -} diff --git a/src/Libraries/Core/src/Database/DatabaseModel/Game.cs b/src/Libraries/Core/src/Database/DatabaseModel/Game.cs deleted file mode 100644 index f6999dece..000000000 --- a/src/Libraries/Core/src/Database/DatabaseModel/Game.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Collections.Generic; - -namespace UniSpy.Server.Core.Database.DatabaseModel -{ - /// - /// Game list. - /// - public partial class Game - { - public Game() - { - Grouplists = new HashSet(); - } - - public int Gameid { get; set; } - public string Gamename { get; set; } = null!; - public string Secretkey { get; set; } - public string Description { get; set; } = null!; - public bool Disabled { get; set; } - - public virtual ICollection Grouplists { get; set; } - } -} diff --git a/src/Libraries/Core/src/Database/DatabaseModel/Grouplist.cs b/src/Libraries/Core/src/Database/DatabaseModel/Grouplist.cs deleted file mode 100644 index fe2568849..000000000 --- a/src/Libraries/Core/src/Database/DatabaseModel/Grouplist.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace UniSpy.Server.Core.Database.DatabaseModel -{ - /// - /// Old games use grouplist to create their game rooms. - /// - public partial class Grouplist - { - public int Groupid { get; set; } - public int Gameid { get; set; } - public string Roomname { get; set; } = null!; - - public virtual Game Game { get; set; } = null!; - } -} diff --git a/src/Libraries/Core/src/Database/DatabaseModel/Message.cs b/src/Libraries/Core/src/Database/DatabaseModel/Message.cs deleted file mode 100644 index 9053093cb..000000000 --- a/src/Libraries/Core/src/Database/DatabaseModel/Message.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; - -namespace UniSpy.Server.Core.Database.DatabaseModel -{ - /// - /// Friend messages. - /// - public partial class Message - { - public int Messageid { get; set; } - public int? Namespaceid { get; set; } - public int? Type { get; set; } - public int From { get; set; } - public int To { get; set; } - public DateTime Date { get; set; } - public string Message1 { get; set; } = null!; - } -} diff --git a/src/Libraries/Core/src/Database/DatabaseModel/Partner.cs b/src/Libraries/Core/src/Database/DatabaseModel/Partner.cs deleted file mode 100644 index 95fc3ffa1..000000000 --- a/src/Libraries/Core/src/Database/DatabaseModel/Partner.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace UniSpy.Server.Core.Database.DatabaseModel -{ - /// - /// Partner information, these information are used for authentication and login. - /// - public partial class Partner - { - public int Partnerid { get; set; } - public string Partnername { get; set; } = null!; - } -} diff --git a/src/Libraries/Core/src/Database/DatabaseModel/Profile.cs b/src/Libraries/Core/src/Database/DatabaseModel/Profile.cs deleted file mode 100644 index 3aa6a0ef3..000000000 --- a/src/Libraries/Core/src/Database/DatabaseModel/Profile.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System.Collections.Generic; - -namespace UniSpy.Server.Core.Database.DatabaseModel -{ - /// - /// User profiles. - /// - public partial class Profile - { - public Profile() - { - Addrequests = new HashSet(); - Blockeds = new HashSet(); - Friends = new HashSet(); - Pstorages = new HashSet(); - Subprofiles = new HashSet(); - } - - public int ProfileId { get; set; } - public int Userid { get; set; } - public string Nick { get; set; } = null!; - public int Serverflag { get; set; } - public short? Status { get; set; } - public string Statstring { get; set; } - public string Location { get; set; } - public string Firstname { get; set; } - public string Lastname { get; set; } - public int? Publicmask { get; set; } - public double? Latitude { get; set; } - public double? Longitude { get; set; } - public string Aim { get; set; } - public int? Picture { get; set; } - public int? Occupationid { get; set; } - public int? Incomeid { get; set; } - public int? Industryid { get; set; } - public int? Marriedid { get; set; } - public int? Childcount { get; set; } - public int? Interests1 { get; set; } - public int? Ownership1 { get; set; } - public int? Connectiontype { get; set; } - public short? Sex { get; set; } - public string Zipcode { get; set; } - public string Countrycode { get; set; } - public string Homepage { get; set; } - public int? Birthday { get; set; } - public int? Birthmonth { get; set; } - public int? Birthyear { get; set; } - public int? Icquin { get; set; } - public short Quietflags { get; set; } - public string Streetaddr { get; set; } - public string Streeaddr { get; set; } - public string City { get; set; } - public int? Cpubrandid { get; set; } - public int? Cpuspeed { get; set; } - public short? Memory { get; set; } - public string Videocard1string { get; set; } - public short? Videocard1ram { get; set; } - public string Videocard2string { get; set; } - public short? Videocard2ram { get; set; } - public int? Subscription { get; set; } - public int? Adminrights { get; set; } - - public virtual User User { get; set; } = null!; - public virtual ICollection Addrequests { get; set; } - public virtual ICollection Blockeds { get; set; } - public virtual ICollection Friends { get; set; } - public virtual ICollection Pstorages { get; set; } - public virtual ICollection Subprofiles { get; set; } - } -} diff --git a/src/Libraries/Core/src/Database/DatabaseModel/Pstorage.cs b/src/Libraries/Core/src/Database/DatabaseModel/Pstorage.cs deleted file mode 100644 index b7ea8452b..000000000 --- a/src/Libraries/Core/src/Database/DatabaseModel/Pstorage.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; - -namespace UniSpy.Server.Core.Database.DatabaseModel -{ - /// - /// Old games use pstorage to store game data. - /// - public partial class Pstorage - { - public int Pstorageid { get; set; } - public int ProfileId { get; set; } - public int Ptype { get; set; } - public int Dindex { get; set; } - [Column(TypeName = "jsonb")] - public Dictionary Data { get; set; } - // public string Data { get; set; } - public virtual Profile Profile { get; set; } = null!; - } -} diff --git a/src/Libraries/Core/src/Database/DatabaseModel/Sakestorage.cs b/src/Libraries/Core/src/Database/DatabaseModel/Sakestorage.cs deleted file mode 100644 index 85d2001f7..000000000 --- a/src/Libraries/Core/src/Database/DatabaseModel/Sakestorage.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace UniSpy.Server.Core.Database.DatabaseModel -{ - /// - /// Sake storage system. - /// - public partial class Sakestorage - { - public int Sakestorageid { get; set; } - public string Tableid { get; set; } = null!; - } -} diff --git a/src/Libraries/Core/src/Database/DatabaseModel/Subprofile.cs b/src/Libraries/Core/src/Database/DatabaseModel/Subprofile.cs deleted file mode 100644 index c84785e0d..000000000 --- a/src/Libraries/Core/src/Database/DatabaseModel/Subprofile.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace UniSpy.Server.Core.Database.DatabaseModel -{ - /// - /// User subprofiles. - /// - public partial class Subprofile - { - public int SubProfileId { get; set; } - public int ProfileId { get; set; } - public string Uniquenick { get; set; } - public int NamespaceId { get; set; } - public int PartnerId { get; set; } - public int? ProductId { get; set; } - public string Gamename { get; set; } - public string Cdkeyenc { get; set; } - public short? Firewall { get; set; } - public int? Port { get; set; } - public string Authtoken { get; set; } - - public virtual Profile Profile { get; set; } = null!; - } -} diff --git a/src/Libraries/Core/src/Database/DatabaseModel/UnispyContext.cs b/src/Libraries/Core/src/Database/DatabaseModel/UnispyContext.cs deleted file mode 100644 index 9e511e471..000000000 --- a/src/Libraries/Core/src/Database/DatabaseModel/UnispyContext.cs +++ /dev/null @@ -1,520 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using UniSpy.Server.Core.Config; - -namespace UniSpy.Server.Core.Database.DatabaseModel -{ - public partial class UniSpyContext : DbContext - { - public UniSpyContext() - { - } - - public UniSpyContext(DbContextOptions options) - : base(options) - { - } - - public virtual DbSet Addrequests { get; set; } = null!; - public virtual DbSet Blockeds { get; set; } = null!; - public virtual DbSet Friends { get; set; } = null!; - public virtual DbSet Games { get; set; } = null!; - public virtual DbSet Grouplists { get; set; } = null!; - public virtual DbSet Messages { get; set; } = null!; - public virtual DbSet Partners { get; set; } = null!; - public virtual DbSet Profiles { get; set; } = null!; - public virtual DbSet Pstorages { get; set; } = null!; - public virtual DbSet Sakestorages { get; set; } = null!; - public virtual DbSet Subprofiles { get; set; } = null!; - public virtual DbSet Users { get; set; } = null!; - - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - { - if (!optionsBuilder.IsConfigured) - { - optionsBuilder.UseNpgsql(ConfigManager.Config.Database.ConnectionString); - } - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder.Entity(entity => - { - entity.ToTable("addrequests", "unispy"); - - entity.HasComment("Friend request."); - - entity.Property(e => e.Addrequestid) - .HasColumnName("addrequestid") - .HasDefaultValueSql("nextval('addrequests_addrequestid_seq'::regclass)"); - - entity.Property(e => e.Namespaceid).HasColumnName("namespaceid"); - - entity.Property(e => e.ProfileId).HasColumnName("profileid"); - - entity.Property(e => e.Reason) - .HasColumnType("character varying") - .HasColumnName("reason"); - - entity.Property(e => e.Syncrequested) - .HasColumnType("character varying") - .HasColumnName("syncrequested"); - - entity.Property(e => e.Targetid).HasColumnName("targetid"); - - entity.HasOne(d => d.Profile) - .WithMany(p => p.Addrequests) - .HasForeignKey(d => d.ProfileId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("addrequests_fk"); - }); - - modelBuilder.Entity(entity => - { - entity.HasKey(e => e.Blockid) - .HasName("blocked_pk"); - - entity.ToTable("blocked", "unispy"); - - entity.HasComment("Block list."); - - entity.Property(e => e.Blockid) - .HasColumnName("blockid") - .HasDefaultValueSql("nextval('blocked_blockid_seq'::regclass)"); - - entity.Property(e => e.Namespaceid).HasColumnName("namespaceid"); - - entity.Property(e => e.ProfileId).HasColumnName("profileid"); - - entity.Property(e => e.Targetid).HasColumnName("targetid"); - - entity.HasOne(d => d.Profile) - .WithMany(p => p.Blockeds) - .HasForeignKey(d => d.ProfileId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("blocked_fk"); - }); - - modelBuilder.Entity(entity => - { - entity.ToTable("friends", "unispy"); - - entity.HasComment("Friend list."); - - entity.Property(e => e.Friendid) - .HasColumnName("friendid") - .HasDefaultValueSql("nextval('friends_friendid_seq'::regclass)"); - - entity.Property(e => e.Namespaceid).HasColumnName("namespaceid"); - - entity.Property(e => e.ProfileId).HasColumnName("profileid"); - - entity.Property(e => e.Targetid).HasColumnName("targetid"); - - entity.HasOne(d => d.Profile) - .WithMany(p => p.Friends) - .HasForeignKey(d => d.ProfileId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("friends_fk"); - }); - - modelBuilder.Entity(entity => - { - entity.ToTable("games", "unispy"); - - entity.HasComment("Game list."); - - entity.Property(e => e.Gameid) - .ValueGeneratedNever() - .HasColumnName("gameid"); - - entity.Property(e => e.Description) - .HasMaxLength(4095) - .HasColumnName("description"); - - entity.Property(e => e.Disabled).HasColumnName("disabled"); - - entity.Property(e => e.Gamename) - .HasColumnType("character varying") - .HasColumnName("gamename"); - - entity.Property(e => e.Secretkey) - .HasColumnType("character varying") - .HasColumnName("secretkey"); - }); - - modelBuilder.Entity(entity => - { - entity.HasKey(e => e.Groupid) - .HasName("grouplist_pk"); - - entity.ToTable("grouplist", "unispy"); - - entity.HasComment("Old games use grouplist to create their game rooms."); - - entity.Property(e => e.Groupid) - .ValueGeneratedNever() - .HasColumnName("groupid"); - - entity.Property(e => e.Gameid).HasColumnName("gameid"); - - entity.Property(e => e.Roomname).HasColumnName("roomname"); - - entity.HasOne(d => d.Game) - .WithMany(p => p.Grouplists) - .HasForeignKey(d => d.Gameid) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("grouplist_fk"); - }); - - modelBuilder.Entity(entity => - { - entity.ToTable("messages", "unispy"); - - entity.HasComment("Friend messages."); - - entity.Property(e => e.Messageid) - .HasColumnName("messageid") - .HasDefaultValueSql("nextval('messages_messageid_seq'::regclass)"); - - entity.Property(e => e.Date) - .HasColumnType("timestamp without time zone") - .HasColumnName("date") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - entity.Property(e => e.From).HasColumnName("from"); - - entity.Property(e => e.Message1) - .HasColumnType("character varying") - .HasColumnName("message"); - - entity.Property(e => e.Namespaceid).HasColumnName("namespaceid"); - - entity.Property(e => e.To).HasColumnName("to"); - - entity.Property(e => e.Type).HasColumnName("type"); - }); - - modelBuilder.Entity(entity => - { - entity.ToTable("partner", "unispy"); - - entity.HasComment("Partner information, these information are used for authentication and login."); - - entity.Property(e => e.Partnerid) - .ValueGeneratedNever() - .HasColumnName("partnerid"); - - entity.Property(e => e.Partnername) - .HasColumnType("character varying") - .HasColumnName("partnername"); - }); - - modelBuilder.Entity(entity => - { - entity.ToTable("profiles", "unispy"); - - entity.HasComment("User profiles."); - - entity.Property(e => e.ProfileId) - .HasColumnName("profileid") - .HasDefaultValueSql("nextval('profiles_profileid_seq'::regclass)"); - - entity.Property(e => e.Adminrights) - .HasColumnName("adminrights") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Aim) - .HasColumnType("character varying") - .HasColumnName("aim") - .HasDefaultValueSql("''::character varying"); - - entity.Property(e => e.Birthday) - .HasColumnName("birthday") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Birthmonth) - .HasColumnName("birthmonth") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Birthyear) - .HasColumnName("birthyear") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Childcount) - .HasColumnName("childcount") - .HasDefaultValueSql("0"); - - entity.Property(e => e.City).HasColumnName("city"); - - entity.Property(e => e.Connectiontype) - .HasColumnName("connectiontype") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Countrycode) - .HasColumnType("character varying") - .HasColumnName("countrycode") - .HasDefaultValueSql("1"); - - entity.Property(e => e.Cpubrandid) - .HasColumnName("cpubrandid") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Cpuspeed) - .HasColumnName("cpuspeed") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Firstname) - .HasColumnType("character varying") - .HasColumnName("firstname"); - - entity.Property(e => e.Homepage) - .HasColumnType("character varying") - .HasColumnName("homepage") - .HasDefaultValueSql("'unispy.org'::character varying"); - - entity.Property(e => e.Icquin) - .HasColumnName("icquin") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Incomeid) - .HasColumnName("incomeid") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Industryid) - .HasColumnName("industryid") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Interests1) - .HasColumnName("interests1") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Lastname) - .HasColumnType("character varying") - .HasColumnName("lastname"); - - entity.Property(e => e.Latitude) - .HasColumnName("latitude") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Location) - .HasColumnType("character varying") - .HasColumnName("location"); - - entity.Property(e => e.Longitude) - .HasColumnName("longitude") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Marriedid) - .HasColumnName("marriedid") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Memory) - .HasColumnName("memory") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Nick) - .HasColumnType("character varying") - .HasColumnName("nick"); - - entity.Property(e => e.Occupationid) - .HasColumnName("occupationid") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Ownership1) - .HasColumnName("ownership1") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Picture) - .HasColumnName("picture") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Publicmask) - .HasColumnName("publicmask") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Quietflags).HasColumnName("quietflags"); - - entity.Property(e => e.Serverflag).HasColumnName("serverflag"); - - entity.Property(e => e.Sex) - .HasColumnName("sex") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Statstring) - .HasColumnType("character varying") - .HasColumnName("statstring") - .HasDefaultValueSql("'I love UniSpy'::character varying"); - - entity.Property(e => e.Status) - .HasColumnName("status") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Streeaddr).HasColumnName("streeaddr"); - - entity.Property(e => e.Streetaddr).HasColumnName("streetaddr"); - - entity.Property(e => e.Subscription) - .HasColumnName("subscription") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Userid).HasColumnName("userid"); - - entity.Property(e => e.Videocard1ram) - .HasColumnName("videocard1ram") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Videocard1string).HasColumnName("videocard1string"); - - entity.Property(e => e.Videocard2ram) - .HasColumnName("videocard2ram") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Videocard2string).HasColumnName("videocard2string"); - - entity.Property(e => e.Zipcode) - .HasColumnType("character varying") - .HasColumnName("zipcode") - .HasDefaultValueSql("'00000'::character varying"); - - entity.HasOne(d => d.User) - .WithMany(p => p.Profiles) - .HasForeignKey(d => d.Userid) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("profiles_fk"); - }); - - modelBuilder.Entity(entity => - { - entity.ToTable("pstorage", "unispy"); - - entity.HasComment("Old games use pstorage to store game data."); - - entity.Property(e => e.Pstorageid) - .HasColumnName("pstorageid") - .HasDefaultValueSql("nextval('pstorage_pstorageid_seq'::regclass)"); - - entity.Property(e => e.Data) - .HasColumnType("jsonb") - .HasColumnName("data"); - - entity.Property(e => e.Dindex).HasColumnName("dindex"); - - entity.Property(e => e.ProfileId).HasColumnName("profileid"); - - entity.Property(e => e.Ptype).HasColumnName("ptype"); - - entity.HasOne(d => d.Profile) - .WithMany(p => p.Pstorages) - .HasForeignKey(d => d.ProfileId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("pstorage_fk"); - }); - - modelBuilder.Entity(entity => - { - entity.ToTable("sakestorage", "unispy"); - - entity.HasComment("Sake storage system."); - - entity.Property(e => e.Sakestorageid) - .HasColumnName("sakestorageid") - .HasDefaultValueSql("nextval('sakestorage_sakestorageid_seq'::regclass)"); - - entity.Property(e => e.Tableid) - .HasColumnType("character varying") - .HasColumnName("tableid"); - }); - - modelBuilder.Entity(entity => - { - entity.ToTable("subprofiles", "unispy"); - - entity.HasComment("User subprofiles."); - - entity.Property(e => e.SubProfileId) - .HasColumnName("subprofileid") - .HasDefaultValueSql("nextval('subprofiles_subprofileid_seq'::regclass)"); - - entity.Property(e => e.Authtoken) - .HasColumnType("character varying") - .HasColumnName("authtoken"); - - entity.Property(e => e.Cdkeyenc) - .HasColumnType("character varying") - .HasColumnName("cdkeyenc"); - - entity.Property(e => e.Firewall) - .HasColumnName("firewall") - .HasDefaultValueSql("0"); - - entity.Property(e => e.Gamename).HasColumnName("gamename"); - - entity.Property(e => e.NamespaceId).HasColumnName("namespaceid"); - - entity.Property(e => e.PartnerId).HasColumnName("partnerid"); - - entity.Property(e => e.Port) - .HasColumnName("port") - .HasDefaultValueSql("0"); - - entity.Property(e => e.ProductId).HasColumnName("productid"); - - entity.Property(e => e.ProfileId).HasColumnName("profileid"); - - entity.Property(e => e.Uniquenick) - .HasColumnType("character varying") - .HasColumnName("uniquenick"); - - entity.HasOne(d => d.Profile) - .WithMany(p => p.Subprofiles) - .HasForeignKey(d => d.ProfileId) - .OnDelete(DeleteBehavior.ClientSetNull) - .HasConstraintName("subprofiles_fk"); - }); - - modelBuilder.Entity(entity => - { - entity.ToTable("users", "unispy"); - - entity.HasComment("User account information."); - - entity.Property(e => e.UserId) - .HasColumnName("userid") - .HasDefaultValueSql("nextval('users_userid_seq'::regclass)"); - - entity.Property(e => e.Banned).HasColumnName("banned"); - - entity.Property(e => e.Createddate) - .HasColumnType("timestamp without time zone") - .HasColumnName("createddate") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - entity.Property(e => e.Deleted).HasColumnName("deleted"); - - entity.Property(e => e.Email) - .HasColumnType("character varying") - .HasColumnName("email"); - - entity.Property(e => e.Emailverified) - .IsRequired() - .HasColumnName("emailverified") - .HasDefaultValueSql("true"); - - entity.Property(e => e.LastIp).HasColumnName("lastip"); - - entity.Property(e => e.Lastonline) - .HasColumnType("timestamp without time zone") - .HasColumnName("lastonline") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - entity.Property(e => e.Password) - .HasColumnType("character varying") - .HasColumnName("password"); - }); - - OnModelCreatingPartial(modelBuilder); - } - - partial void OnModelCreatingPartial(ModelBuilder modelBuilder); - } -} diff --git a/src/Libraries/Core/src/Database/DatabaseModel/User.cs b/src/Libraries/Core/src/Database/DatabaseModel/User.cs deleted file mode 100644 index fe9bb1645..000000000 --- a/src/Libraries/Core/src/Database/DatabaseModel/User.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net; - -namespace UniSpy.Server.Core.Database.DatabaseModel -{ - /// - /// User account information. - /// - public partial class User - { - public User() - { - Profiles = new HashSet(); - } - - public int UserId { get; set; } - public string Email { get; set; } = null!; - public string Password { get; set; } = null!; - public bool? Emailverified { get; set; } - public IPAddress LastIp { get; set; } - public DateTime Lastonline { get; set; } - public DateTime Createddate { get; set; } - public bool Banned { get; set; } - public bool Deleted { get; set; } - - public virtual ICollection Profiles { get; set; } - } -} diff --git a/src/Libraries/Core/src/Database/DatabaseType.cs b/src/Libraries/Core/src/Database/DatabaseType.cs deleted file mode 100755 index e2ef1f780..000000000 --- a/src/Libraries/Core/src/Database/DatabaseType.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace UniSpy.Server.Core.Database -{ - public enum DatabaseType - { - PostgreSql - } -} diff --git a/src/Libraries/Core/src/Encryption/Crc16.cs b/src/Libraries/Core/src/Encryption/Crc16.cs deleted file mode 100755 index 7157b30cb..000000000 --- a/src/Libraries/Core/src/Encryption/Crc16.cs +++ /dev/null @@ -1,90 +0,0 @@ -namespace UniSpy.Server.Core.Encryption -{ - public enum Crc16Mode : ushort - { - Standard = 0xA001, - CCITT = 4129, - CCITTKermit = 0x8408 - } - - /// - /// Credits go to http://www.sanity-free.com/134/standard_crc_16_in_csharp.html - /// - public class Crc16 - { - /// - /// The Crc16 Table - /// - public ushort[] CrcTable { get; protected set; } - - public Crc16() - { - // Build Standard Crc16 Table - BuildCrcTable(0xA001); - } - - public Crc16(ushort polynomial) - { - BuildCrcTable(polynomial); - } - - public Crc16(Crc16Mode Mode) - { - BuildCrcTable((ushort)Mode); - } - - /// - /// Calculates the Checksum for the input string - /// - /// - /// - public ushort ComputeChecksum(string Input) - { - return ComputeChecksum(UniSpyEncoding.GetBytes(Input)); - } - - /// - /// Calculates the Checksum for the given bytes - /// - /// - /// - public ushort ComputeChecksum(byte[] bytes) - { - ushort crc = 0; - for (int i = 0; i < bytes.Length; ++i) - { - crc = (ushort)(CrcTable[(bytes[i] ^ crc) & 0xFF] ^ (crc >> 8)); - } - return crc; - } - - /// - /// Builds the Crc table programmatically with the given polynomial - /// - /// - private void BuildCrcTable(ushort polynomial) - { - ushort value; - ushort temp; - - // Build standard Crc16 Table - CrcTable = new ushort[256]; - for (ushort i = 0; i < 256; ++i) - { - value = 0; - temp = i; - for (byte j = 0; j < 8; ++j) - { - if (((value ^ temp) & 0x0001) != 0) - value = (ushort)((value >> 1) ^ polynomial); - else - value >>= 1; - - temp >>= 1; - } - - CrcTable[i] = value; - } - } - } -} diff --git a/src/Libraries/Core/src/Encryption/GSEncryption.cs b/src/Libraries/Core/src/Encryption/GSEncryption.cs deleted file mode 100644 index 9c83b08a5..000000000 --- a/src/Libraries/Core/src/Encryption/GSEncryption.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.Core.Encryption -{ - public sealed class GameSpyCTX - { - public byte Buffer1; - public byte Buffer2; - public byte[] SBox = new byte[256]; - } - /// - /// This class is used to encrypt and decrypt the data for Chat. - /// - /// Note: this is a C-sharp version of the peerchat algorithm created by aluigi. - /// Original C implementation: http://aluigi.altervista.org/papers/gs_peerchat.h - /// - public sealed class GSEncryption : ICryptography - { - public const string DigitsHex = "0123456789abcdef"; - public const string DigitsCrypt = "aFl4uOD9sfWq1vGp"; - public const string NewDigitsCrypt = "qJ1h4N9cP3lzD0Ka"; - public const uint IPXorMask = 0xc3801dc7; - public const string ClientKey = "0000000000000000"; - public const string ServerKey = "0000000000000000"; - public static byte[] Handle(GameSpyCTX ctx, byte[] data) - { - byte num1 = ctx.Buffer1; - byte num2 = ctx.Buffer2; - byte t; - int datapos = 0; - List buffer = new List(); - long size = data.Length; - - while (size-- > 0) - { - num1 = (byte)((num1 + 1) % 256); - num2 = (byte)((ctx.SBox[num1] + num2) % 256); - t = ctx.SBox[num1]; - ctx.SBox[num1] = ctx.SBox[num2]; - ctx.SBox[num2] = t; - t = (byte)((ctx.SBox[num2] + ctx.SBox[num1]) % 256); - byte temp = (byte)(data[datapos++] ^ ctx.SBox[t]); - buffer.Add(temp); - } - - ctx.Buffer1 = num1; - ctx.Buffer2 = num2; - return buffer.ToArray(); - } - - /// - /// Prepare the key - /// - /// - /// - /// - public static void Init(GameSpyCTX ctx, string challengeKey, string secretKey) - { - byte[] challengeBytes = UniSpyEncoding.GetBytes(challengeKey); - byte[] secretKeyBytes = UniSpyEncoding.GetBytes(secretKey); - - ctx.Buffer1 = 0; - ctx.Buffer2 = 0; - - int secretKeyIndex = 0; - for (int i = 0; i < challengeBytes.Length; i++, secretKeyIndex++) - { - if (secretKeyIndex >= secretKeyBytes.Length) - { - secretKeyIndex = 0; - } - - challengeBytes[i] ^= secretKeyBytes[secretKeyIndex]; - } - - byte index1 = 255; - - for (int i = 0; i < 256; i++, index1--) - { - ctx.SBox[i] = index1; - } - - index1 = 0; - - for (int i = 0, index2 = 0; i < ctx.SBox.Length; i++, index1++) - { - if (index1 >= challengeBytes.Length) - { - index1 = 0; - } - - index2 = (byte)((challengeBytes[index1] + ctx.SBox[i] + index2) % 256); - byte t = ctx.SBox[i]; - ctx.SBox[i] = ctx.SBox[index2]; - ctx.SBox[index2] = t; - } - } - - public static bool EncodeIP() - { - return false; - } - public GameSpyCTX ClientCtx { get; private set; } - public GameSpyCTX ServerCtx { get; private set; } - public GSEncryption(string gameSecretKey) - { - ClientCtx = new GameSpyCTX(); - ServerCtx = new GameSpyCTX(); - Init(ClientCtx, ClientKey, gameSecretKey); - Init(ServerCtx, ServerKey, gameSecretKey); - } - public byte[] Encrypt(byte[] data) - { - return Handle(ServerCtx, data); - } - - public byte[] Decrypt(byte[] data) - { - return Handle(ClientCtx, data); - } - } -} diff --git a/src/Libraries/Core/src/Encryption/UniSpyEncoding.cs b/src/Libraries/Core/src/Encryption/UniSpyEncoding.cs deleted file mode 100755 index b7d305227..000000000 --- a/src/Libraries/Core/src/Encryption/UniSpyEncoding.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Text; - -namespace UniSpy.Server.Core.Encryption -{ - public static class UniSpyEncoding - { - public static Func GetString => Encoding.ASCII.GetString; - public static Func GetBytes => Encoding.ASCII.GetBytes; - - } -} \ No newline at end of file diff --git a/src/Libraries/Core/src/Encryption/XorEncoding.cs b/src/Libraries/Core/src/Encryption/XorEncoding.cs deleted file mode 100755 index 92362dac1..000000000 --- a/src/Libraries/Core/src/Encryption/XorEncoding.cs +++ /dev/null @@ -1,82 +0,0 @@ -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.Core.Encryption -{ - public enum XorType : int - { - Type0, - Type1, - Type2, - Type3 - } - public class XOREncoding : ICryptography - { - public XorType EncryptionType { get; private set; } - - public XOREncoding(XorType type) - { - EncryptionType = type; - } - - public static string Encode(string plainText, XorType type) => UniSpyEncoding.GetString(Encode(UniSpyEncoding.GetBytes(plainText), type)); - - /// - /// simple xor encoding for Gstats,GPSP,GPCM - /// - /// - /// default encryption string used in GPSP,GPCM - /// used in GStats - /// used in GStats - /// - /// - public static byte[] Encode(byte[] plaintext, XorType type) - { - string seed0 = "gamespy"; - string seed1 = "GameSpy3D"; - string seed2 = "Industries"; - string seed3 = "ProjectAphex"; - - int length = plaintext.Length; - int index = 0; - byte[] temp; - switch (type) - { - case XorType.Type0: - temp = UniSpyEncoding.GetBytes(seed0); - break; - case XorType.Type1: - temp = UniSpyEncoding.GetBytes(seed1); - break; - case XorType.Type2: - temp = UniSpyEncoding.GetBytes(seed2); - break; - case XorType.Type3: - temp = UniSpyEncoding.GetBytes(seed3); - break; - default: - temp = UniSpyEncoding.GetBytes(seed0); - break; - } - - for (int i = 0; length > 0; length--) - { - if (i >= temp.Length) - i = 0; - - plaintext[index++] ^= temp[i++]; - } - - return plaintext; - } - - public byte[] Encrypt(byte[] data) - { - return Encode(data, EncryptionType); - } - - public byte[] Decrypt(byte[] data) - { - return Encode(data, EncryptionType); - } - } -} diff --git a/src/Libraries/Core/src/Exception/UniSpyException.cs b/src/Libraries/Core/src/Exception/UniSpyException.cs deleted file mode 100755 index a85cb700e..000000000 --- a/src/Libraries/Core/src/Exception/UniSpyException.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace UniSpy -{ - public class Exception : System.Exception - { - public Exception() - { - } - - public Exception(string message) : base(message) - { - } - - public Exception(string message, System.Exception innerException) : base(message, innerException) - { - } - } - -} diff --git a/src/Libraries/Core/src/Extension/DataOperationExtensions.cs b/src/Libraries/Core/src/Extension/DataOperationExtensions.cs deleted file mode 100755 index 2ff30c6bc..000000000 --- a/src/Libraries/Core/src/Extension/DataOperationExtensions.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Linq; -using UniSpy.Server.Core.Database.DatabaseModel; -namespace UniSpy.Server.Core.Extension -{ - public class DataOperationExtensions - { - public static string GetSecretKey(string gameName) - { - using (var db = new UniSpyContext()) - { - var result = from p in db.Games - where p.Gamename == gameName - select new { p.Secretkey }; - - return result.First().Secretkey; - } - } - } -} diff --git a/src/Libraries/Core/src/Extension/EasyTimer.cs b/src/Libraries/Core/src/Extension/EasyTimer.cs deleted file mode 100644 index d38e09e26..000000000 --- a/src/Libraries/Core/src/Extension/EasyTimer.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Timers; - -namespace UniSpy.Server.Core.Extension -{ - public class EasyTimer - { - public TimeSpan ExpireTime { get; private set; } - public DateTime LastActiveTime { get; private set; } - public TimeSpan IdleTime => DateTime.Now - LastActiveTime; - /// - /// The timer to count and invoke some event - /// - private Timer _timer; - public bool IsExpired => IdleTime > ExpireTime; - public EasyTimer(TimeSpan expireTimeSpan, TimeSpan intervalTimeSpan, Action invokingAction) - { - _timer = new Timer - { - Enabled = true, - Interval = intervalTimeSpan.TotalMilliseconds, - AutoReset = true - }; - ExpireTime = expireTimeSpan; - RefreshLastActiveTime(); - _timer.Elapsed += (s, e) => invokingAction(); - _timer.Start(); - } - public void RefreshLastActiveTime() => LastActiveTime = DateTime.Now; - public void Dispose() => _timer.Dispose(); - } -} \ No newline at end of file diff --git a/src/Libraries/Core/src/Extension/Redis/RedisChannelName.cs b/src/Libraries/Core/src/Extension/Redis/RedisChannelName.cs deleted file mode 100755 index 8c7764b2d..000000000 --- a/src/Libraries/Core/src/Extension/Redis/RedisChannelName.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace UniSpy.Server.Core.Extension.Redis -{ - public class RedisChannelName - { - public const string NatNegCookieChannel = "QueryReport:NatNegCookieChannel"; - public const string HeartbeatChannel = "QueryReport:HeartbeatChannel"; - public const string PresenceConnectionManagerBuddyMessageChannel = "PresenceConnectionManager:BuddyMessageChannel"; - public const string ChatChannelPrefix = "Chat:Channel"; - } -} diff --git a/src/Libraries/Core/src/Extension/Redis/RedisDbNumber.cs b/src/Libraries/Core/src/Extension/Redis/RedisDbNumber.cs deleted file mode 100755 index 0ccc239b7..000000000 --- a/src/Libraries/Core/src/Extension/Redis/RedisDbNumber.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace UniSpy.Server.Core.Extension.Redis -{ - public enum RedisDbNumber : int - { - ChatChannel = 0, - GameServerV1 = 1, - GameServerV2 = 2, - NatAddressInfo = 3, - NatFailInfo = 4, - GameTrafficRelay = 5 - } -} diff --git a/src/Libraries/Core/src/Extension/StringExtensions.cs b/src/Libraries/Core/src/Extension/StringExtensions.cs deleted file mode 100755 index 14915bdc2..000000000 --- a/src/Libraries/Core/src/Extension/StringExtensions.cs +++ /dev/null @@ -1,221 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Security.Cryptography; -using System.Text; -using UniSpy.Server.Core.Encryption; - -namespace UniSpy.Server.Core.Extension -{ - public static class StringExtensions - { - /// - /// Returns all the index's of the given string input - /// - /// - /// - public static List IndexesOf(this string str, string value) - { - if (string.IsNullOrEmpty(value)) - throw new ArgumentException("the string to find may not be empty", "value"); - List indexes = new List(); - for (int index = 0; ; index += value.Length) - { - index = str.IndexOf(value, index); - if (index == -1) - return indexes; - indexes.Add(index); - } - } - - /// - /// Removes any invalid file path characters from this string - /// - public static string MakeFileNameSafe(this string fileName) - { - return Path.GetInvalidFileNameChars().Aggregate(fileName, (current, c) => current.Replace(c.ToString(), string.Empty)); - } - - /// - /// Converts the input string into its MD5 Hex variant - /// - /// Uppercase the characters? - /// The encoding of the string. Default is UTF8 - /// - public static string GetMD5Hash(this string input, bool upperCase = false, Encoding Encoding = null) - { - using (MD5 Md5 = MD5.Create()) - { - return Md5.ComputeHash(Encoding.ASCII.GetBytes(input)).ToHex(upperCase); - } - } - /// - /// Converts the byte array to its Hex string equivlent - /// - /// Do we uppercase the hex string? - /// - public static string ToHex(this byte[] bytes, bool upperCase = true) - { - StringBuilder result = new StringBuilder(bytes.Length * 2); - for (int i = 0; i < bytes.Length; i++) - result.Append(bytes[i].ToString(upperCase ? "X2" : "x2")); - - return result.ToString(); - } - #region Undisplayable char convert - /// - /// Convert byte array to pure hex string dispite if byte is printable or non-pritable - /// - /// - /// - public static string ConvertByteToHexString(this byte[] buffer) - { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < buffer.Length; i++) - { - if (i == buffer.Length - 1) - { - sb.Append("0x" + buffer[i].ToString("X2")); - } - else - { - sb.Append("0x" + buffer[i].ToString("X2") + ","); - } - } - return sb.ToString(); - } - /// - /// Convert nonpritable to hex string, combine with printable char to create a string: - /// [0x00] [0x01] hello [0x02] - /// - /// Raw byte array - /// - public static string ConvertNonprintableBytesToHexString(this byte[] buffer) - { - StringBuilder temp = new StringBuilder(); - for (int i = 0; i < buffer.Length; i++) - { - if (buffer[i] < 0x1F || buffer[i] > 0x7E) - { - temp.Append($"[{buffer[i]:X2}]"); - } - else - { - temp.Append((char)buffer[i]); - } - } - return temp.ToString(); - } - - /// - /// Only convert printable bytes to string - /// - /// raw byte array - /// - public static string ConvertPrintableBytesToString(this byte[] buffer) - { - char delimiter = ' '; - StringBuilder temp = new StringBuilder(); - for (int i = 0; i < buffer.Length; i++) - { - if (buffer[i] < 0x1F || buffer[i] > 0x7E) - { - // if the last char in temp is not delimiter, we add delemiter - if (temp.Length != 0 && temp[temp.Length - 1] != delimiter) - { - temp.Append(delimiter); - } - } - else - { - temp.Append((char)buffer[i]); - } - } - return temp.ToString(); - } - public static string ConvertNonprintableCharToHex(this string buffer) - { - return ConvertNonprintableBytesToHexString(UniSpyEncoding.GetBytes(buffer)); - } - #endregion - - public static Dictionary ConvertKVStringToDictionary(this string kvStr) - { - Dictionary dic = new Dictionary(); - List keyValueList = - kvStr.Split("\\").ToList(); - - for (int i = 0; i < keyValueList.Count; i = i + 2) - { - if (keyValueList.Count < i + 2) // Count starts from 1, i from 0 - { - dic.TryAdd(keyValueList[i], ""); - } - else - { - dic.TryAdd(keyValueList[i], keyValueList[i + 1]); - } - } - - return dic; - } - public static string ConvertDictionaryToKVString(this Dictionary kv) - { - string buffer = @"\"; - foreach (var data in kv) - { - buffer += data.Key + @"\" + data.Value + @"\"; - } - - buffer = buffer.Substring(0, buffer.Length - 1); - - return buffer; - } - - public static List ConvertKeyStrToList(this string keyStr) - { - List data = keyStr.Split(@"\", StringSplitOptions.RemoveEmptyEntries).ToList(); - - return data; - } - - /// - /// Check the validation of response string - /// - /// return true if the string is valid - public static bool CheckResponseValidation(this string buffer) - { - return buffer?.Length > 3; - } - - public static bool CheckResponseValidation(this byte[] buffer) - { - if (buffer is null) - { - return false; - } - - if (buffer.Length < 3) - { - return false; - } - return true; - } - /// - /// Get byte array from a hexstring - /// the hexstring is like "01020304" - /// two char as a byte - /// - /// - public static byte[] FromHexStringToBytes(this string hex) - { - return Enumerable.Range(0, hex.Length) - .Where(x => x % 2 == 0) - .Select(x => Convert.ToByte(hex.Substring(x, 2), 16)) - .ToArray(); - } - - - } -} diff --git a/src/Libraries/Core/src/Logging/LogWriter.cs b/src/Libraries/Core/src/Logging/LogWriter.cs deleted file mode 100755 index eb32baef3..000000000 --- a/src/Libraries/Core/src/Logging/LogWriter.cs +++ /dev/null @@ -1,97 +0,0 @@ -using Serilog; -using Serilog.Events; -using UniSpy.Server.Core.Abstraction.BaseClass.Factory; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Config; -using UniSpy.Server.Core.Extension; - -namespace UniSpy.Server.Core.Logging -{ - /// - /// Provides an object wrapper for a file that is used to - /// store LogMessage's into. Uses a Multi-Thread safe Queueing - /// system, and provides full Asynchronous writing and flushing - /// - public static class LogWriter - { - public static readonly LoggerConfiguration LogConfig; - static LogWriter() - { - LogConfig = new LoggerConfiguration(); - if (ConfigManager.IsConfigFileExist) - { - switch (ConfigManager.Config.MinimumLogLevel) - { - case LogEventLevel.Verbose: - LogConfig.MinimumLevel.Verbose(); - break; - case LogEventLevel.Information: - LogConfig.MinimumLevel.Information(); - break; - case LogEventLevel.Debug: - LogConfig.MinimumLevel.Debug(); - break; - case LogEventLevel.Warning: - LogConfig.MinimumLevel.Warning(); - break; - case LogEventLevel.Error: - LogConfig.MinimumLevel.Error(); - break; - case LogEventLevel.Fatal: - LogConfig.MinimumLevel.Fatal(); - break; - } - } - - var path = ServerLauncherBase.ServerInstances.Count == 0 ? "" : ServerLauncherBase.ServerInstances[0].Name; - LogConfig = LogConfig - .WriteTo.Console(outputTemplate: "{Timestamp:[HH:mm:ss]} [{Level:u4}] {Message:}{NewLine}{Exception}") - .WriteTo.File( - path: $"Logs/[{path}]-.log", - outputTemplate: "{Timestamp:[yyyy-MM-dd HH:mm:ss]} [{Level:u4}] {Message:}{NewLine}{Exception}", - rollingInterval: RollingInterval.Day); - Log.Logger = LogConfig.CreateLogger(); - } - public static void LogVerbose(string message) => Log.Verbose(message); - public static void LogDebug(string message) => Log.Debug(message); - public static void LogInfo(string message) => Log.Information(message); - public static void LogWarn(string message) => Log.Warning(message); - public static void LogError(string message) => Log.Error(message); - public static void LogError(System.Exception e) => LogError(e.ToString()); - public static void LogFatal(string message) => Log.Fatal(message); - public static void LogCurrentClass(object param) => LogVerbose($"[ => ] [{param.GetType().Name}]"); - public static void LogCurrentClass(this IClient client, object param) => LogVerbose(FormatLogMessage(client, $"[ => ] [{param.GetType().Name}]")); - - public static string FormatLogMessage(this IClient client, string message) => $"[{client.Connection.RemoteIPEndPoint}] {message}"; - public static string FormatNetworkLogMessage(string type, string message) => $"[{type}] {message}"; - public static string FormatNetworkLogMessage(string type, byte[] message, bool isLogRaw) - { - if (isLogRaw) - { - // we first show printable bytes, then show all bytes - var tempLog = $"{StringExtensions.ConvertPrintableBytesToString(message)} [{StringExtensions.ConvertByteToHexString(message)}]"; - return $"[{type}] {tempLog}"; - } - else - { - var tempLog = StringExtensions.ConvertNonprintableBytesToHexString(message); - return $"[{type}] {tempLog}"; - } - } - - public static void LogVerbose(this IClient client, string message) => Log.Verbose(FormatLogMessage(client, message)); - public static void LogInfo(this IClient client, string message) => Log.Information(FormatLogMessage(client, message)); - public static void LogDebug(this IClient client, string message) => Log.Debug(FormatLogMessage(client, message)); - public static void LogWarn(this IClient client, string message) => Log.Warning(FormatLogMessage(client, message)); - public static void LogError(this IClient client, string message) => Log.Error(FormatLogMessage(client, message)); - public static void LogError(this IClient client, Exception e) => Log.Error(FormatLogMessage(client, e.Message)); - public static void LogFatal(this IClient client, string message) => Log.Fatal(FormatLogMessage(client, message)); - - public static void LogNetworkReceiving(this IClient client, string message) => LogDebug(client, FormatNetworkLogMessage("Recv", message)); - public static void LogNetworkSending(this IClient client, string message) => LogDebug(client, FormatNetworkLogMessage("Send", message)); - public static void LogNetworkReceiving(this IClient client, byte[] message) => LogDebug(client, FormatNetworkLogMessage("Recv", message, client.IsLogRaw)); - public static void LogNetworkSending(this IClient client, byte[] message) => LogDebug(client, FormatNetworkLogMessage("Send", message, client.IsLogRaw)); - public static void LogNetworkMultiCast(this IClient client, string message) => LogDebug(client, FormatNetworkLogMessage("Cast", message)); - public static void LogNetworkMultiCast(this IClient client, byte[] message) => LogDebug(client, FormatNetworkLogMessage("Cast", message, client.IsLogRaw)); - } -} diff --git a/src/Libraries/Core/src/Misc/BufferCacheBase.cs b/src/Libraries/Core/src/Misc/BufferCacheBase.cs deleted file mode 100644 index 443229d88..000000000 --- a/src/Libraries/Core/src/Misc/BufferCacheBase.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace UniSpy.Server.Core.Misc -{ - public abstract class BufferCacheBase - { - public T InCompleteBuffer { get; protected set; } - - protected BufferCacheBase() - { - } - - /// - /// Process the incoming buffer, if buffer is complete return complete buffer, other wise return null - /// - /// - public abstract bool ProcessBuffer(T buffer, out T completeBuffer); - } -} \ No newline at end of file diff --git a/src/Libraries/Core/src/Misc/GameSpyRandom.cs b/src/Libraries/Core/src/Misc/GameSpyRandom.cs deleted file mode 100755 index d397f5c2c..000000000 --- a/src/Libraries/Core/src/Misc/GameSpyRandom.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Text; - -namespace UniSpy.Server.Core.Misc -{ - public class GameSpyRandom - { - public enum StringType - { - Alpha, - AlphaNumeric, - Hex - } - /// - /// Array of characters used in generating a signiture - /// - private static char[] AlphaChars = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', - 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' - }; - - /// - /// An array of Alpha Numeric characters used in generating a random string - /// - private static char[] AlphaNumChars = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', - 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', - 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' - }; - - /// - /// Array of Hex cahracters - /// - private static char[] HexChars = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'a', 'b', 'c', 'd', 'e', 'f' - }; - - public static string GenerateRandomString(int count, StringType type) - { - Random random = new Random((int)DateTime.Now.Ticks); - - StringBuilder builder = new StringBuilder(count); - - for (int i = 0; i < count; i++) - { - switch (type) - { - case StringType.AlphaNumeric: - builder.Append(AlphaNumChars[random.Next(AlphaNumChars.Length)]); - break; - default: - builder.Append(AlphaChars[random.Next(AlphaChars.Length)]); - break; - case StringType.Hex: - builder.Append(HexChars[random.Next(HexChars.Length)]); - break; - } - } - - return builder.ToString(); - } - } -} diff --git a/src/Libraries/Core/src/Misc/GameSpyUtils.cs b/src/Libraries/Core/src/Misc/GameSpyUtils.cs deleted file mode 100755 index 054530d4d..000000000 --- a/src/Libraries/Core/src/Misc/GameSpyUtils.cs +++ /dev/null @@ -1,273 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Net; -using System.Text.RegularExpressions; -using UniSpy.Server.Core.Logging; - -namespace UniSpy.Server.Core.Misc -{ - public static class GameSpyUtils - { - /// - /// Get the string type request command name from rawrequest - /// - public static string GetRequestName(string request) - { - var frags = request.Split('\\', StringSplitOptions.RemoveEmptyEntries); - if (frags.Length < 4) - { - throw new UniSpy.Exception("Request is not valid."); - } - return frags[0]; - } - /// - /// Split command to key value array then convert it to dictionary - /// - /// a string like request - /// - public static Dictionary ConvertToKeyValue(string request) - { - string[] commandParts = request.Replace(@"\final\", "").TrimStart('\\').TrimEnd('\\').Split('\\'); - return ConvertToKeyValue(commandParts); - } - - /// - /// Converts a trimmed presence message from the client string to a keyValue pair dictionary - /// - /// The array of data from the client - /// A converted dictionary - public static Dictionary ConvertToKeyValue(string[] parts) - { - // we remove final item - parts = parts.Where(p => p != "final").ToArray(); - Dictionary dict = new Dictionary(); - try - { - for (int i = 0; i < parts.Length; i += 2) - { - if (!dict.ContainsKey(parts[i])) - { - dict.Add(parts[i].ToLower(), parts[i + 1]); - } - //Some game send uppercase key to us, so we have to deal with it - } - } - catch (IndexOutOfRangeException) { } - - return dict; - } - - - public static void PrintReceivedGPDictToLogger(Dictionary recv) - { - LogWriter.LogDebug( - $"Received request {recv.Keys.First()} with content: {string.Join(";", recv.Select(x => x.Key + "=" + x.Value).ToArray())}"); - } - - /// - /// Check the correctness of the email account format. - /// - /// email account - /// - public static bool IsEmailFormatCorrect(string email) - { - - if (string.IsNullOrWhiteSpace(email)) - return false; - - try - { - // Normalize the domain - email = Regex.Replace(email, @"(@)(.+)$", DomainMapper, - RegexOptions.None, TimeSpan.FromMilliseconds(200)); - - // Examines the domain part of the email and normalizes it. - string DomainMapper(Match match) - { - // Use IdnMapping class to convert Unicode domain names. - var idn = new IdnMapping(); - - // Pull out and process domain name (throws ArgumentException on invalid) - var domainName = idn.GetAscii(match.Groups[2].Value); - - return match.Groups[1].Value + domainName; - } - } - catch (RegexMatchTimeoutException e) - { - LogWriter.LogError(e); - return false; - } - catch (ArgumentException e) - { - LogWriter.LogError(e); - return false; - } - - try - { - return Regex.IsMatch(email, - @"^(?("")("".+?(? (!char.IsLetterOrDigit(ch) && ch != '@' && ch != '.')); - } - /// - /// Check is the format of nick or uniquenick are correct - /// - /// - /// - public static bool IsNickOrUniquenickFormatCorrect(string nick) - { - string pattern = @"^\w+$"; - Regex regex = new Regex(pattern); - return regex.IsMatch(nick); - } - - /// - /// Check if a date is correct - /// - /// - /// - /// - /// True if the date is valid, otherwise false - public static bool IsValidDate(int day, int month, int year) - { - // Check for a blank. - ///////////////////// - if ((day == 0) && (month == 0) && (year == 0)) - return false; - - // Validate the day of the month. - ///////////////////////////////// - switch (month) - { - // No month. - //////////// - case 0: - // Can't specify a day without a month. - /////////////////////////////////////// - if (day != 0) - return false; - break; - - // 31-day month. - //////////////// - case 1: - case 3: - case 5: - case 7: - case 8: - case 10: - case 12: - if (day > 31) - return false; - break; - - // 30-day month. - //////////////// - case 4: - case 6: - case 9: - case 11: - if (day > 30) - return false; - break; - - // 28/29-day month. - /////////////////// - case 2: - // Leap year? - ///////////// - if ((((year % 4) == 0) && ((year % 100) != 0)) || ((year % 400) == 0)) - { - if (day > 29) - return false; - } - else - { - if (day > 28) - return false; - } - break; - - // Invalid month. - ///////////////// - default: - return false; - } - - // Check that the date is in the valid range. - ///////////////////////////////////////////// - if (year < 1900) - return false; - if (year > 2079) - return false; - if (year == 2079) - { - if (month > 6) - return false; - if ((month == 6) && (day > 6)) - return false; - } - - return true; - } - public static bool IsNumber(string strNumber) - { - Regex objNotNumberPattern = new Regex("[^0-9.-]"); - Regex objTwoDotPattern = new Regex("[0-9]*[.][0-9]*[.][0-9]*"); - Regex objTwoMinusPattern = new Regex("[0-9]*[-][0-9]*[-][0-9]*"); - string strValidRealPattern = "^([-]|[.]|[-.]|[0-9])[0-9]*[.]*[0-9]+$"; - string strValidIntegerPattern = "^([-]|[0-9])[0-9]*$"; - Regex objNumberPattern = new Regex("(" + strValidRealPattern + ")|(" + strValidIntegerPattern + ")"); - - return !objNotNumberPattern.IsMatch(strNumber) && - !objTwoDotPattern.IsMatch(strNumber) && - !objTwoMinusPattern.IsMatch(strNumber) && - objNumberPattern.IsMatch(strNumber); - } - - /// - /// Compute the interval of time - /// - /// old time - /// milisecond - public static byte ComputeTimeInterval(DateTime old) - { - return (byte)DateTime.Now.Subtract(old).TotalMilliseconds; - } - - - /// - /// An extension method to determine if an IP address is internal, as specified in RFC1918 - /// - /// The IP address that will be tested - /// Returns true if the IP is internal, false if it is external - public static bool IsInternal(this IPAddress toTest) - { - if (IPAddress.IsLoopback(toTest)) return true; - else if (toTest.ToString() == "::1") return false; - - byte[] bytes = toTest.GetAddressBytes(); - switch (bytes[0]) - { - case 10: - return true; - case 172: - return bytes[1] < 32 && bytes[1] >= 16; - case 192: - return bytes[1] == 168; - default: - return false; - } - } - } -} diff --git a/src/Libraries/Core/src/Misc/PasswordEncoder.cs b/src/Libraries/Core/src/Misc/PasswordEncoder.cs deleted file mode 100755 index 15d4a0ea3..000000000 --- a/src/Libraries/Core/src/Misc/PasswordEncoder.cs +++ /dev/null @@ -1,126 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using UniSpy.Server.Core.Encryption; -using UniSpy.Server.Core.Extension; - -namespace UniSpy.Server.Core.Misc -{ - public class PasswordEncoder - { - /// - /// process password to string which stores in our database - /// - /// - public static string ProcessPassword(Dictionary dict) - { - string md5Password; - if (dict.ContainsKey("passwordenc")) - { - //we decoded gamespy encoded password then get md5 of it - md5Password = StringExtensions.GetMD5Hash(Decode(dict["passwordenc"])); - } - else if (dict.ContainsKey("passenc")) - { - //we decoded gamespy encoded password then get md5 of it - md5Password = StringExtensions.GetMD5Hash(Decode(dict["passenc"])); - } - else if (dict.ContainsKey("pass")) - { - md5Password = StringExtensions.GetMD5Hash(dict["pass"]); - } - else if (dict.ContainsKey("password")) - { - md5Password = StringExtensions.GetMD5Hash(dict["password"]); - } - else - { - throw new UniSpy.Exception("Can not find password field in request"); - } - return md5Password; - } - /// - /// Encodes a password to Gamespy format - /// - /// - /// - private static string Encode(string Password) - { - // Get password string as UTF8 String, Convert to Base64 - byte[] PasswordBytes = Encoding.UTF8.GetBytes(Password); - string Pass = Convert.ToBase64String(GameSpyEncodeMethod(PasswordBytes)); - - // Convert Standard Base64 to Gamespy Base 64 - StringBuilder builder = new StringBuilder(Pass); - builder.Replace('=', '_'); - builder.Replace('+', '['); - builder.Replace('/', ']'); - return builder.ToString(); - } - - /// - /// Decodes a Gamespy encoded password - /// - /// - /// - private static string Decode(string password) - { - // Convert Gamespy Base64 to Standard Base 64 - password = password.Replace('_', '=').Replace('[', '+').Replace(']', '/'); - // Decode passsword - byte[] passwordBytes = Convert.FromBase64String(password); - return UniSpyEncoding.GetString(GameSpyEncodeMethod(passwordBytes)); - } - - /// - /// Gamespy's XOR method to encrypt and decrypt a password - /// - /// - /// - private static byte[] GameSpyEncodeMethod(byte[] pass) - { - int a = 0; - int num = 0x79707367; // gamespy - for (int i = 0; i < pass.Length; ++i) - { - num = GameSpyByteShift(num); - a = num % 0xFF; - pass[i] ^= (byte)a; - } - - return pass; - } - - /// - /// Not exactly sure what this does, but i know its used to - /// reverse the encryption and decryption of a string - /// - /// - /// - private static int GameSpyByteShift(int num) - { - int c = (num >> 16) & 0xffff; - int a = num & 0xffff; - - c *= 0x41a7; - a *= 0x41a7; - a += ((c & 0x7fff) << 16); - - if (a < 0) - { - a &= 0x7fffffff; - a++; - } - - a += (c >> 15); - - if (a < 0) - { - a &= 0x7fffffff; - a++; - } - - return a; - } - } -} diff --git a/src/Libraries/Core/src/Misc/RequestChecker.cs b/src/Libraries/Core/src/Misc/RequestChecker.cs deleted file mode 100755 index 3e0f7ef51..000000000 --- a/src/Libraries/Core/src/Misc/RequestChecker.cs +++ /dev/null @@ -1,46 +0,0 @@ -namespace UniSpy.Server.Core.Misc -{ - public class RequestChecker - { - public static bool IsUniqueNickLegal(string uniquenick) - { - if (uniquenick.Length > 3 && uniquenick.Length < 15) - { - return true; - } - - return false; - } - public static bool IsNicknameLegal(string nick) - { - if (nick.Length > 2 && nick.Length < 15) - { - return true; - } - - return false; - } - public static bool IsEmailLegal(string email) - { - return true; - - } - public static bool IsNamespaceidLegal(ushort namespaceid) - { - return true; - } - public static bool IsPartneridLegal(ushort partnerid) - { - return true; - } - - public static bool IsPasswordLegal(string password) - { - if (password.Length > 4 && password.Length < 20) - { - return true; - } - return false; - } - } -} diff --git a/src/Libraries/Core/src/Misc/UniSpyJsonConverter.cs b/src/Libraries/Core/src/Misc/UniSpyJsonConverter.cs deleted file mode 100755 index 29311e812..000000000 --- a/src/Libraries/Core/src/Misc/UniSpyJsonConverter.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.Net; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace UniSpy.Server.Core.Misc -{ - - public class IPAddressConverter : JsonConverter - { - public override bool CanConvert(Type objectType) - { - return (objectType == typeof(IPAddress)); - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - writer.WriteValue(value.ToString()); - } - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - return IPAddress.Parse((string)reader.Value); - } - } - public class IPAddresConverter : JsonConverter - { - public override bool CanConvert(Type objectType) - { - return (objectType == typeof(IPAddress)); - } - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - IPAddress ep = (IPAddress)value; - JObject jo = new JObject(); - jo.Add("Address", JToken.FromObject(ep.ToString(), serializer)); - jo.WriteTo(writer); - } - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - JObject jo = JObject.Load(reader); - IPAddress address = IPAddress.Parse(jo["Address"].ToObject()); - return address; - } - } - public class IPEndPointConverter : JsonConverter - { - public override bool CanConvert(Type objectType) - { - return (objectType == typeof(IPEndPoint)); - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - IPEndPoint ep = (IPEndPoint)value; - JObject jo = new JObject(); - jo.Add("Address", JToken.FromObject(ep.Address.ToString(), serializer)); - jo.Add("Port", ep.Port); - jo.WriteTo(writer); - } - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - // if (reader.Value == null) - // { - // return null; - // } - JObject jo = JObject.Load(reader); - IPAddress address = IPAddress.Parse(jo["Address"].ToObject()); - int port = (int)jo["Port"]; - return new IPEndPoint(address, port); - } - } - -} diff --git a/src/Libraries/Core/src/Network/Http/Server/HttpConnection.cs b/src/Libraries/Core/src/Network/Http/Server/HttpConnection.cs deleted file mode 100644 index 73ff585ab..000000000 --- a/src/Libraries/Core/src/Network/Http/Server/HttpConnection.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.Net; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Events; - -namespace UniSpy.Server.Core.Network.Http.Server -{ - public class HttpConnection : NetCoreServer.HttpSession, IHttpConnection - { - public IPEndPoint RemoteIPEndPoint { get; private set; } - public NetworkConnectionType ConnectionType => NetworkConnectionType.Http; - public IConnectionManager Manager => (IConnectionManager)Server; - - public event OnConnectedEventHandler OnConnect; - public event OnDisconnectedEventHandler OnDisconnect; - public event OnReceivedEventHandler OnReceive; - public HttpConnection(HttpConnectionManager server) : base(server) - { - } - protected override void OnConnecting() - { - if (RemoteIPEndPoint is null) - { - RemoteIPEndPoint = (IPEndPoint)Socket.RemoteEndPoint; - } - base.OnConnecting(); - } - protected override void OnConnected() => OnConnect(); - protected override void OnDisconnected() => OnDisconnect(); - protected override void OnReceivedRequest(NetCoreServer.HttpRequest request) => OnReceive(new HttpRequest(request)); - void IConnection.Send(string response) - { - // Response.MakeOkResponse(); - Response.SetBegin(200); - Response.SetBody(response); - base.SendResponseAsync(); - } - - void IConnection.Send(byte[] response) - { - // Response.MakeOkResponse(); - Response.SetBegin(200); - Response.SetBody(response); - base.SendResponseAsync(); - } - - void ITcpConnection.Disconnect() => Disconnect(); - - } -} \ No newline at end of file diff --git a/src/Libraries/Core/src/Network/Http/Server/HttpConnectionManager.cs b/src/Libraries/Core/src/Network/Http/Server/HttpConnectionManager.cs deleted file mode 100644 index bf82505a4..000000000 --- a/src/Libraries/Core/src/Network/Http/Server/HttpConnectionManager.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Net; -using NetCoreServer; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Events; - -namespace UniSpy.Server.Core.Network.Http.Server -{ - public class HttpConnectionManager : NetCoreServer.HttpServer, IConnectionManager - { - public event OnConnectingEventHandler OnInitialization; - public HttpConnectionManager(IPEndPoint endpoint) : base(endpoint) - { - } - - protected override NetCoreServer.TcpSession CreateSession() => new UniSpy.Server.Core.Network.Http.Server.HttpConnection(this); - protected override void OnConnecting(TcpSession connection) - { - OnInitialization((HttpConnection)connection); - base.OnConnecting(connection); - } - - public new void Start() => base.Start(); - - } -} \ No newline at end of file diff --git a/src/Libraries/Core/src/Network/Http/Server/HttpRequest.cs b/src/Libraries/Core/src/Network/Http/Server/HttpRequest.cs deleted file mode 100644 index 0638c0e73..000000000 --- a/src/Libraries/Core/src/Network/Http/Server/HttpRequest.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.Core.Network.Http.Server -{ - public class HttpRequest : IHttpRequest - { - public Uri Uri => new Uri(Url); - - public byte[] BodyBytes { get; private set; } - - public string Body { get; private set; } - - public long Cookies { get; private set; } - - public long Headers { get; private set; } - - public string Protocol { get; private set; } - - public string Url { get; private set; } - - public string Method { get; private set; } - - public bool KeepAlive { get; private set; } - - - public HttpRequest(NetCoreServer.HttpRequest request) - { - Url = request.Url; - BodyBytes = request.BodyBytes; - Body = request.Body; - Cookies = request.Cookies; - Headers = request.Headers; - Protocol = request.Protocol; - Method = request.Method; - KeepAlive = false; - - for (var m = 0; m < request.Headers; m++) - { - var k = request.Header(m); - if (k.Item1 == "Connection" && k.Item2.ToLower() == "keep-alive") - KeepAlive = true; - } - } - } -} \ No newline at end of file diff --git a/src/Libraries/Core/src/Network/NetworkEvents.cs b/src/Libraries/Core/src/Network/NetworkEvents.cs deleted file mode 100644 index cee7adc8b..000000000 --- a/src/Libraries/Core/src/Network/NetworkEvents.cs +++ /dev/null @@ -1,9 +0,0 @@ -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.Core.Events -{ - public delegate void OnConnectedEventHandler(); - public delegate void OnReceivedEventHandler(object buffer); - public delegate void OnDisconnectedEventHandler(); - public delegate IClient OnConnectingEventHandler(IConnection connection); -} \ No newline at end of file diff --git a/src/Libraries/Core/src/Network/Tcp/Client/UniSpyTcpClient.cs b/src/Libraries/Core/src/Network/Tcp/Client/UniSpyTcpClient.cs deleted file mode 100644 index ea9695994..000000000 --- a/src/Libraries/Core/src/Network/Tcp/Client/UniSpyTcpClient.cs +++ /dev/null @@ -1,47 +0,0 @@ -// using System; -// using System.Net; -// using UniSpy.Server.Core.Encryption; -// using UniSpy.Server.Core.Logging; -// using TcpClient = NetCoreServer.TcpClient; - -// namespace UniSpy.Server.Core.Network.Tcp.Client -// { - -// public abstract class UniSpyTcpClient : TcpClient -// { -// protected UniSpyTcpClient(IPEndPoint endpoint) : base(endpoint) -// { -// } - -// /// -// /// We automatic connect to remote server address -// /// - -// protected override void OnReceived(byte[] buffer, long offset, long size) -// { -// LogWriter.LogNetworkTraffic("Recv", Endpoint, buffer, size); -// byte[] tempBuffer = new byte[size]; -// Array.Copy(buffer, 0, tempBuffer, 0, size); -// OnReceived(tempBuffer); -// } - -// protected virtual void OnReceived(byte[] buffer) -// { -// OnReceived(UniSpyEncoding.GetString(buffer)); -// } - -// protected virtual void OnReceived(string buffer) { } - -// public override bool SendAsync(byte[] buffer, long offset, long size) -// { -// LogWriter.LogNetworkTraffic("Send", Endpoint, buffer, size); -// return base.SendAsync(buffer, offset, size); -// } - -// public override long Send(byte[] buffer, long offset, long size) -// { -// LogWriter.LogNetworkTraffic("Send", Endpoint, buffer, size); -// return base.Send(buffer, offset, size); -// } -// } -// } diff --git a/src/Libraries/Core/src/Network/Tcp/Server/TcpConnection.cs b/src/Libraries/Core/src/Network/Tcp/Server/TcpConnection.cs deleted file mode 100644 index 64470d66d..000000000 --- a/src/Libraries/Core/src/Network/Tcp/Server/TcpConnection.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System.Linq; -using System.Net; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Encryption; -using UniSpy.Server.Core.Events; - -namespace UniSpy.Server.Core.Network.Tcp.Server -{ - /// - /// This is a template class that helps creating a TCP Session (formerly TCP stream) - /// with logging functionality and ServerName, as required in the old network stack. - /// - public class TcpConnection : NetCoreServer.TcpSession, ITcpConnection - { - /// - /// remote endpoint will dispose when disconnecting, however we need that in some situation, - /// we must save it here for further use - /// - /// - public IPEndPoint RemoteIPEndPoint { get; private set; } - IConnectionManager IConnection.Manager => (IConnectionManager)base.Server; - public NetworkConnectionType ConnectionType => NetworkConnectionType.Tcp; - public event OnConnectedEventHandler OnConnect; - public event OnDisconnectedEventHandler OnDisconnect; - public event OnReceivedEventHandler OnReceive; - public TcpConnection(TcpConnectionManager server) : base(server) - { - } - protected override void OnConnecting() - { - // we set ipendpoint here - if (RemoteIPEndPoint is null) - { - RemoteIPEndPoint = (IPEndPoint)Socket.RemoteEndPoint; - } - base.OnConnecting(); - } - protected override void OnConnected() - { - OnConnect(); - base.OnConnected(); - } - protected override void OnDisconnected() - { - OnDisconnect(); - base.OnDisconnected(); - } - protected override void OnReceived(byte[] buffer, long offset, long size) - { - OnReceive(buffer.Skip((int)offset).Take((int)size).ToArray()); - base.OnReceived(buffer, offset, size); - } - void ITcpConnection.Disconnect() => Disconnect(); - public new void Send(string response) => Send(UniSpyEncoding.GetBytes(response)); - public new void Send(byte[] response) => base.SendAsync(response); - - } -} - diff --git a/src/Libraries/Core/src/Network/Tcp/Server/TcpConnectionManager.cs b/src/Libraries/Core/src/Network/Tcp/Server/TcpConnectionManager.cs deleted file mode 100644 index 4eefd03e4..000000000 --- a/src/Libraries/Core/src/Network/Tcp/Server/TcpConnectionManager.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Net; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Events; - -namespace UniSpy.Server.Core.Network.Tcp.Server -{ - /// - /// This is a template class that helps creating a TCP Server with logging functionality and ServerName, as required in the old network stack. - /// - public class TcpConnectionManager : NetCoreServer.TcpServer, IConnectionManager - { - public TcpConnectionManager(IPEndPoint endpoint) : base(endpoint) - { - } - - public event OnConnectingEventHandler OnInitialization; - - public new virtual void Start() - { - if (OptionSendBufferSize > int.MaxValue || OptionReceiveBufferSize > int.MaxValue) - { - throw new ArgumentException("Buffer size can not big than length of integer!"); - } - base.Start(); - } - protected override NetCoreServer.TcpSession CreateSession() => new TcpConnection(this); - - protected override void OnConnecting(NetCoreServer.TcpSession connection) - { - OnInitialization((IConnection)connection); - base.OnConnecting(connection); - } - } -} diff --git a/src/Libraries/Core/src/Network/Udp/Client/UniSpyUdpClient.cs b/src/Libraries/Core/src/Network/Udp/Client/UniSpyUdpClient.cs deleted file mode 100644 index 4db56d320..000000000 --- a/src/Libraries/Core/src/Network/Udp/Client/UniSpyUdpClient.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Net; -using System.Net.Sockets; -using UdpClient = NetCoreServer.UdpClient; - -namespace UniSpy.Server.Core.Network.Udp.Client -{ - public class UniSpyUdpClient : UdpClient - { - - public UniSpyUdpClient(IPAddress address, int port) : base(address, port) - { - } - protected override void OnConnected() - { - Console.WriteLine($"Echo UDP client connected a new connection with Id {Id}"); - - // Start receive datagrams - ReceiveAsync(); - } - protected override void OnDisconnected() - { - Console.WriteLine($"Echo UDP client disconnected a connection with Id {Id}"); - base.OnConnected(); - } - - protected override void OnReceived(EndPoint endpoint, byte[] buffer, long offset, long size) - { - // Continue receive datagrams - ReceiveAsync(); - } - - protected override void OnError(SocketError error) - { - Console.WriteLine($"Echo UDP client caught an error with code {error}"); - } - - } -} diff --git a/src/Libraries/Core/src/Network/Udp/Server/UdpConnection.cs b/src/Libraries/Core/src/Network/Udp/Server/UdpConnection.cs deleted file mode 100644 index 6efa2b967..000000000 --- a/src/Libraries/Core/src/Network/Udp/Server/UdpConnection.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System.Net; -using System.Threading; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Encryption; -using UniSpy.Server.Core.Events; - -namespace UniSpy.Server.Core.Network.Udp.Server -{ - /// - /// A remote endpoint wrapper for UDP server which unifies the interface for - /// - public class UdpConnection : IUdpConnection - { - public UdpConnectionManager Manager { get; private set; } - public IPEndPoint RemoteIPEndPoint { get; private set; } - IConnectionManager IConnection.Manager => Manager; - public NetworkConnectionType ConnectionType => NetworkConnectionType.Udp; - public event OnReceivedEventHandler OnReceive; - - public UdpConnection(UdpConnectionManager server, IPEndPoint endPoint) - { - Manager = server; - RemoteIPEndPoint = endPoint; - } - public virtual void OnReceived(byte[] message) - { - // Server.ReceiveAsync(); - ThreadPool.QueueUserWorkItem(o => { try { Manager.ReceiveAsync(); } catch { } }); - OnReceive(message); - } - - public bool Send(object response) - { - if (response.GetType() == typeof(string)) - { - return Manager.SendAsync(RemoteIPEndPoint, UniSpyEncoding.GetBytes((string)response)); - } - else if (response.GetType() == typeof(byte[])) - { - return Manager.SendAsync(RemoteIPEndPoint, (byte[])response); - } - else - { - throw new UniSpy.Exception("IUdpConnection.Send: response must be string or byte[]"); - } - } - public void Send(string response) => Send(RemoteIPEndPoint, UniSpyEncoding.GetBytes(response)); - public void Send(byte[] response) => Manager.Send(RemoteIPEndPoint, response); - public void Send(IPEndPoint endPoint, string response) => Send(endPoint, UniSpyEncoding.GetBytes(response)); - public void Send(IPEndPoint endPoint, byte[] response) => Manager.Send(endPoint, response); - } -} diff --git a/src/Libraries/Core/src/Network/Udp/Server/UdpConnectionManager.cs b/src/Libraries/Core/src/Network/Udp/Server/UdpConnectionManager.cs deleted file mode 100644 index ee96f7de9..000000000 --- a/src/Libraries/Core/src/Network/Udp/Server/UdpConnectionManager.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Linq; -using System.Net; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Events; - -namespace UniSpy.Server.Core.Network.Udp.Server -{ - /// - /// This is a template class that helps creating a UDP Server with - /// logging functionality and ServerName, as required in the old network stack. - /// - public class UdpConnectionManager : NetCoreServer.UdpServer, IConnectionManager - { - public UdpConnectionManager(IPEndPoint endpoint) : base(endpoint) - { - } - public event OnConnectingEventHandler OnInitialization; - - public new virtual void Start() - { - if (OptionSendBufferSize > int.MaxValue || OptionReceiveBufferSize > int.MaxValue) - { - throw new ArgumentException("Buffer size can not big than length of integer!"); - } - base.Start(); - } - protected override void OnStarted() => ReceiveAsync(); - - /// - /// Send unencrypted data - /// - /// plaintext - /// is sending succeed - protected override void OnReceived(EndPoint endPoint, byte[] buffer, long offset, long size) - { - var connection = CreateConnection((IPEndPoint)endPoint); - (connection as UdpConnection).OnReceived(buffer.Skip((int)offset).Take((int)size).ToArray()); - } - protected virtual IUdpConnection CreateConnection(IPEndPoint endPoint) - { - var connection = new UdpConnection(this, endPoint); - var client = OnInitialization(connection); - return client.Connection as IUdpConnection; - } - } -} - diff --git a/src/Libraries/Core/src/UniSpy.Server.Core.csproj b/src/Libraries/Core/src/UniSpy.Server.Core.csproj deleted file mode 100755 index 8b2a01c11..000000000 --- a/src/Libraries/Core/src/UniSpy.Server.Core.csproj +++ /dev/null @@ -1,30 +0,0 @@ - - - - net6.0 - ..\..\..\..\common\Icon\UniSpy_Logo.ico - - - AnyCPU - ..\..\..\..\build\$(Configuration) - - - ..\..\..\..\build\$(Configuration) - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Libraries/LinqToRedis/.gitignore b/src/Libraries/LinqToRedis/.gitignore deleted file mode 100644 index c14372969..000000000 --- a/src/Libraries/LinqToRedis/.gitignore +++ /dev/null @@ -1,391 +0,0 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. -## -## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore - -# User-specific files -*.rsuser -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Mono auto generated files -mono_crash.* - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -[Ww][Ii][Nn]32/ -[Aa][Rr][Mm]/ -[Aa][Rr][Mm]64/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ -[Ll]ogs/ - -# Visual Studio 2015/2017 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# Visual Studio 2017 auto generated files -Generated\ Files/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUnit -*.VisualState.xml -TestResult.xml -nunit-*.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# Benchmark Results -BenchmarkDotNet.Artifacts/ - -# .NET Core -project.lock.json -project.fragment.lock.json -artifacts/ - -# ASP.NET Scaffolding -ScaffoldingReadMe.txt - -# StyleCop -StyleCopReport.xml - -# Files built by Visual Studio -*_i.c -*_p.c -*_h.h -*.ilk -*.meta -*.obj -*.iobj -*.pch -*.pdb -*.ipdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*_wpftmp.csproj -*.log -*.tlog -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# Visual Studio Trace Files -*.e2e - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# AxoCover is a Code Coverage Tool -.axoCover/* -!.axoCover/settings.json - -# Coverlet is a free, cross platform Code Coverage Tool -coverage*.json -coverage*.xml -coverage*.info - -# Visual Studio code coverage results -*.coverage -*.coveragexml - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# Note: Comment the next line if you want to checkin your web deploy settings, -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# NuGet Symbol Packages -*.snupkg -# The packages folder can be ignored because of Package Restore -**/[Pp]ackages/* -# except build/, which is used as an MSBuild target. -!**/[Pp]ackages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/[Pp]ackages/repositories.config -# NuGet v3's project.json files produces more ignorable files -*.nuget.props -*.nuget.targets - -# Nuget personal access tokens and Credentials -nuget.config - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt -*.appx -*.appxbundle -*.appxupload - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!?*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -orleans.codegen.cs - -# Including strong name files can present a security risk -# (https://github.com/github/gitignore/pull/2483#issue-259490424) -#*.snk - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm -ServiceFabricBackup/ -*.rptproj.bak - -# SQL Server files -*.mdf -*.ldf -*.ndf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings -*.rptproj.rsuser -*- [Bb]ackup.rdl -*- [Bb]ackup ([0-9]).rdl -*- [Bb]ackup ([0-9][0-9]).rdl - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat -node_modules/ - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) -*.vbw - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# CodeRush personal settings -.cr/personal - -# Python Tools for Visual Studio (PTVS) -__pycache__/ -*.pyc - -# Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config - -# Tabs Studio -*.tss - -# Telerik's JustMock configuration file -*.jmconfig - -# BizTalk build output -*.btp.cs -*.btm.cs -*.odx.cs -*.xsd.cs - -# OpenCover UI analysis results -OpenCover/ - -# Azure Stream Analytics local run output -ASALocalRun/ - -# MSBuild Binary and Structured Log -*.binlog - -# NVidia Nsight GPU debugger configuration file -*.nvuser - -# MFractors (Xamarin productivity tool) working folder -.mfractor/ - -# Local History for Visual Studio -.localhistory/ - -# BeatPulse healthcheck temp database -healthchecksdb - -# Backup folder for Package Reference Convert tool in Visual Studio 2017 -MigrationBackup/ - -# Ionide (cross platform F# VS Code tools) working folder -.ionide/ - -# Fody - auto-generated XML schema -FodyWeavers.xsd - -# VS Code files for those working on multiple tools -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json -*.code-workspace - -# Local History for Visual Studio Code -.history/ - -# Windows Installer files from build outputs -*.cab -*.msi -*.msix -*.msm -*.msp - -# JetBrains Rider -.idea/ -*.sln.iml - -# MAC cache -*.DS_Store diff --git a/src/Libraries/LinqToRedis/LinqToRedis.sln b/src/Libraries/LinqToRedis/LinqToRedis.sln deleted file mode 100644 index 6964007f3..000000000 --- a/src/Libraries/LinqToRedis/LinqToRedis.sln +++ /dev/null @@ -1,28 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniSpy.LinqToRedis", "src\UniSpy.LinqToRedis.csproj", "{8EA3FD73-4113-4630-BC83-566A34AD0C11}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniSpy.LinqToRedis.Test", "test\UniSpy.LinqToRedis.Test.csproj", "{34A8446C-0ABD-4535-8AFF-F452E8DC65A8}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8EA3FD73-4113-4630-BC83-566A34AD0C11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8EA3FD73-4113-4630-BC83-566A34AD0C11}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8EA3FD73-4113-4630-BC83-566A34AD0C11}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8EA3FD73-4113-4630-BC83-566A34AD0C11}.Release|Any CPU.Build.0 = Release|Any CPU - {34A8446C-0ABD-4535-8AFF-F452E8DC65A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {34A8446C-0ABD-4535-8AFF-F452E8DC65A8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {34A8446C-0ABD-4535-8AFF-F452E8DC65A8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {34A8446C-0ABD-4535-8AFF-F452E8DC65A8}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection -EndGlobal diff --git a/src/Libraries/LinqToRedis/README.md b/src/Libraries/LinqToRedis/README.md deleted file mode 100644 index e2a56f628..000000000 --- a/src/Libraries/LinqToRedis/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# LinqToRedis -This small tool will give you the power to query redis key value data with Linq.
-This project is inspired by UniSpyServer. - -# Usage -The example is shown below. -1. You need to create your class inherent from RedisKeyValueObject -2. Define some properties with \[RedisKey\] attribute -3. Create your own class which inherent from RedisClient<>, remember to specify the database -4. Use (1) GetValue method (2) index access (3) Linq to query from redis - -# Note -1. The linq query buildin only support ==,&&,|| operation, you can not query more complex expression -2. The properties with \[RedisKey\] attribute are the key used to search on redis, the raw redis query string is build to query from redis -3. Use LinqToRedis to query simple condition, get the data from redis, then use linq for List<> or Dictionary<> to query more complex data - -# Example code -``` - public record UserInfo : RedisKeyValueObject - { - [RedisKey] - public Guid? ServerID { get; set; } - [RedisKey] - public int? Cookie { get; set; } - public string UserName { get; set; } - public string RemoteEndPoint { get; set; } - } - - - internal class RedisClient : UniSpyServer.LinqToRedis.RedisClient - { - public RedisClient() : base("127.0.0.1:6789", 0) - { - } - } -``` -Then you can use the general way to query from redis. -``` - var key = new UserInfo{ Cookie=1 }; - var client = new RedisClient(); - var results1 = client.GetValue(key); - var results2 = client[key]; - var results3 = client.Where(x => x.Cookie == 1).ToList(); -``` diff --git a/src/Libraries/LinqToRedis/src/Core/IRedisKey.cs b/src/Libraries/LinqToRedis/src/Core/IRedisKey.cs deleted file mode 100644 index 9560028c1..000000000 --- a/src/Libraries/LinqToRedis/src/Core/IRedisKey.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace UniSpy.LinqToRedis -{ - public interface IRedisKey - { - string SearchKey { get; } - string FullKey { get; } - } -} \ No newline at end of file diff --git a/src/Libraries/LinqToRedis/src/Core/RedisClient.cs b/src/Libraries/LinqToRedis/src/Core/RedisClient.cs deleted file mode 100644 index 454e2342e..000000000 --- a/src/Libraries/LinqToRedis/src/Core/RedisClient.cs +++ /dev/null @@ -1,201 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Threading.Tasks; -using Newtonsoft.Json; -using StackExchange.Redis; -using UniSpy.LinqToRedis.Linq; - -namespace UniSpy.LinqToRedis -{ - /// - /// TODO we need to implement get AllKeys, AllValues - /// - /// - public class RedisClient where TValue : RedisKeyValueObject - { - public TimeSpan? ExpireTime { get; private set; } - public IConnectionMultiplexer Multiplexer { get; private set; } - public IDatabase Db { get; private set; } - protected EndPoint[] _endPoints => Multiplexer.GetEndPoints(); - private RedisQueryProvider _provider; - /// - /// Search redis key value storage by key - /// - /// The redis key class - /// - public QueryableObject Context; - /// - /// The default keyvalue object, used to provide default information - /// - public readonly TValue DefaultKVObject = ((TValue)System.Activator.CreateInstance(typeof(TValue))); - public RedisClient(string connectionString) - { - CheckValidation(); - Multiplexer = ConnectionMultiplexer.Connect(connectionString); - Db = Multiplexer.GetDatabase((int)DefaultKVObject.Db); - _provider = new RedisQueryProvider(this); - Context = new QueryableObject(_provider); - } - /// - /// Use existing multiplexer for performance - /// - public RedisClient(IConnectionMultiplexer multiplexer) - { - CheckValidation(); - Multiplexer = multiplexer; - Db = Multiplexer.GetDatabase((int)DefaultKVObject.Db); - _provider = new RedisQueryProvider(this); - Context = new QueryableObject(_provider); - } - private void CheckValidation() - { - var properties = typeof(TValue).GetProperties().Where(p => p.GetCustomAttributes(typeof(RedisKeyAttribute), true).Select(a => a is RedisKeyAttribute).Any()).ToList(); - if (properties.Count() == 0) - { - throw new ArgumentNullException($"The RedisKeyValueObject:{this.GetType().Name} must have a key"); - } - // we need to check whether - var valueProperties = properties.Where(p => p.PropertyType.IsValueType == true && p.PropertyType.IsGenericType == false).ToList(); - if (valueProperties.Count >= 1) - { - var propNames = ""; - foreach (var prop in valueProperties) - { - propNames += $" {typeof(TValue).Name}.{prop.Name}"; - } - throw new ArgumentException($"The RedisKey object must be reference type, please convert the following properties to reference type:{propNames}"); - } - } - - public async Task DeleteKeyValueAsync(TValue key) - { - await Db.KeyDeleteAsync(key.FullKey); - } - public void DeleteKeyValue(TValue key) - { - Db.KeyDeleteAsync(key.FullKey); - } - public List GetValues(TValue key) - { - return GetKeyValues(key).Values.ToList(); - } - public async Task> GetValuesAsync(TValue key) - { - var dict = await GetKeyValuesAsync(key); - return dict.Values.ToList(); - } - public List GetMatchedKeys(IRedisKey key = null) - { - var matchedKeys = new List(); - var searchKey = key is null ? DefaultKVObject.SearchKey : key.SearchKey; - foreach (var end in _endPoints) - { - var server = Multiplexer.GetServer(end); - // we get matched key from database - foreach (var k in server.Keys(pattern: searchKey, database: Db.Database)) - { - matchedKeys.Add(k); - } - } - return matchedKeys; - } - public async Task> GetMatchedKeysAsync(IRedisKey key = null) - { - var matchedKeys = new List(); - var searchKey = key is null ? DefaultKVObject.SearchKey : key.SearchKey; - foreach (var end in _endPoints) - { - var server = Multiplexer.GetServer(end); - // we get specific key from database - await foreach (var k in server.KeysAsync(pattern: searchKey, database: Db.Database)) - { - matchedKeys.Add(k); - } - } - return matchedKeys; - } - /// - /// Get matched key value by key from database. - /// if key is null this will get all key value from database - /// - /// - /// - public Dictionary GetKeyValues(IRedisKey key = null) - { - var dict = new Dictionary(); - var keys = GetMatchedKeys(key); - foreach (var k in keys) - { - var value = Db.StringGet(k.ToString()); - dict.Add(k, JsonConvert.DeserializeObject(value)); - } - return dict; - } - - public async Task> GetKeyValuesAsync(IRedisKey key = null) - { - var dict = new Dictionary(); - var keys = await GetMatchedKeysAsync(key); - foreach (var k in keys) - { - var value = await Db.StringGetAsync(k.ToString()); - dict.Add(k, JsonConvert.DeserializeObject(value)); - } - return dict; - } - - public bool SetValue(TValue value) - { - return Db.StringSet(value.FullKey, JsonConvert.SerializeObject((TValue)value), value.ExpireTime); - } - public async Task SetValueAsync(TValue value) - { - return await Db.StringSetAsync(value.FullKey, JsonConvert.SerializeObject((TValue)value), value.ExpireTime); - } - public TValue GetValue(IRedisKey key) - { - var value = Db.StringGet(key.FullKey); - if (value.IsNull) - { - return default; - } - return JsonConvert.DeserializeObject(value); - } - public async Task GetValueAsync(IRedisKey key) - { - var value = await Db.StringGetAsync(key.FullKey); - if (value.IsNull) - { - return default; - } - return JsonConvert.DeserializeObject(value); - } - - /// - /// The index access of redis key value object is always sync - /// - public TValue this[IRedisKey key] - { - get => GetValue(key); - set => SetValue(value); - } - public async Task FlushDbAsync() - { - var keys = GetMatchedKeysAsync(); - foreach (var key in await keys) - { - await Db.KeyDeleteAsync(key); - } - } - public void FlushDb() - { - var keys = GetMatchedKeys(); - foreach (var key in keys) - { - Db.KeyDelete(key); - } - } - } -} diff --git a/src/Libraries/LinqToRedis/src/Core/RedisKeyAttribute.cs b/src/Libraries/LinqToRedis/src/Core/RedisKeyAttribute.cs deleted file mode 100644 index bea2d4935..000000000 --- a/src/Libraries/LinqToRedis/src/Core/RedisKeyAttribute.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; - -namespace UniSpy.LinqToRedis -{ - /// - /// Mark property as redis key attribute, so you can search by this key - /// The key must be simple object, which mean its ToString method can out put a valid string - /// Such as int, string, DateTime, Guid, IPEndPoint, etc. - /// - [AttributeUsage(validOn: AttributeTargets.Property | AttributeTargets.Field)] - public class RedisKeyAttribute : Attribute - { - public RedisKeyAttribute() { } - } -} \ No newline at end of file diff --git a/src/Libraries/LinqToRedis/src/Core/RedisKeyValueObject.cs b/src/Libraries/LinqToRedis/src/Core/RedisKeyValueObject.cs deleted file mode 100644 index f6eb0b795..000000000 --- a/src/Libraries/LinqToRedis/src/Core/RedisKeyValueObject.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Newtonsoft.Json; - -namespace UniSpy.LinqToRedis -{ - public abstract record RedisKeyValueObject : IRedisKey - { - - // [JsonIgnore] - // protected List _supportedTypes = new List - // { - // typeof(string), - // typeof(int), - // typeof(long), - // typeof(double), - // typeof(bool), - // typeof(int?), - // typeof(int), - // typeof(int?), - // typeof(long?), - // typeof(double?), - // typeof(bool?), - // typeof(DateTime), - // typeof(byte[]), - // typeof(byte?[]), - // typeof(Guid?), - // typeof(Guid), - // typeof(TimeSpan), - // typeof(IPEndPoint), - // typeof(Nullable), - // typeof(Enum) - // }; - [JsonIgnore] - public TimeSpan? ExpireTime { get; private set; } - [JsonIgnore] - public string FullKey => BuildFullKey(); - [JsonIgnore] - public string SearchKey => BuildSearchKey(); - [RedisKey] - public int? Db { get; private set; } - public RedisKeyValueObject(int db, TimeSpan? expireTime = null) - { - ExpireTime = expireTime; - Db = db; - } - /// - /// This is using for json deserialization - /// - protected RedisKeyValueObject() { } - - private string BuildFullKey() - { - string fullKey = null; - var properties = GetType().GetProperties().Where(p => p.GetCustomAttributes(typeof(RedisKeyAttribute), true).Select(a => a is RedisKeyAttribute).Any()).ToList(); - - foreach (var property in properties) - { - // if (!_supportedTypes.Contains(property.PropertyType)) - // { - // throw new NotSupportedException($"The complex type:{property.PropertyType} is not supported"); - // } - if (property.GetValue(this) is null) - { - throw new ArgumentNullException($"{property.Name} is null when building full key."); - } - var keyValueStr = $"{property.Name}={property.GetValue(this)}"; - if (fullKey is null) - { - fullKey = $"{keyValueStr}"; - } - else - { - fullKey = $"{fullKey}:{keyValueStr}"; - } - } - return fullKey; - } - private string BuildSearchKey() - { - var builder = new StringBuilder(); - var properties = GetType().GetProperties().Where(p => p.GetCustomAttributes(typeof(RedisKeyAttribute), false).Where(a => a is RedisKeyAttribute).Any()).ToList(); - if (properties.Count() == 0) - { - throw new ArgumentNullException($"The RedisKeyValueObject:{this.GetType().Name} must have a key"); - } - - - var propKVList = new List>(); - foreach (var property in properties) - { - propKVList.Add(new KeyValuePair(property.Name, property.GetValue(this))); - } - - foreach (var item in propKVList) - { - if (item.Value is null) - { - builder.Append($"{item.Key}=*"); - } - else - { - builder.Append($"{item.Key}={item.Value}"); - } - - if (item.Key != propKVList.Last().Key) - { - builder.Append(":"); - } - } - return builder.ToString(); - } - } -} \ No newline at end of file diff --git a/src/Libraries/LinqToRedis/src/Linq/QueryEvaluator.cs b/src/Libraries/LinqToRedis/src/Linq/QueryEvaluator.cs deleted file mode 100644 index 0097de414..000000000 --- a/src/Libraries/LinqToRedis/src/Linq/QueryEvaluator.cs +++ /dev/null @@ -1,106 +0,0 @@ - -using System; -using System.Collections.Generic; -using System.Linq.Expressions; - -namespace UniSpy.LinqToRedis.Linq -{ - public static class QueryEvaluator - { - /// - /// Performs evaluation and replacement of independent sub-trees - /// - /// The root of the noderession tree. - /// A function that decides whether a given noderession node can be part of the local function. - /// A new tree with sub-trees evaluated and replaced. - public static Expression PartialEval(Expression noderession, Func fnCanBeEvaluated) - => new SubtreeEvaluator(new Nominator(fnCanBeEvaluated).Nominate(noderession)).Eval(noderession); - - /// - /// Performs evaluation and replacement of independent sub-trees - /// - /// The root of the noderession tree. - /// A new tree with sub-trees evaluated and replaced. - public static Expression PartialEval(Expression noderession) => PartialEval(noderession, QueryEvaluator.CanBeEvaluatedLocally); - - private static bool CanBeEvaluatedLocally(Expression noderession) => noderession.NodeType != ExpressionType.Parameter; - - /// - /// Evaluates and replaces sub-trees when first candidate is reached (top-down) - /// - class SubtreeEvaluator : ExpressionVisitor - { - HashSet candidates; - internal SubtreeEvaluator(HashSet candidates) - { - this.candidates = candidates; - } - internal Expression Eval(Expression node) => this.Visit(node); - - public override Expression Visit(Expression node) - { - if (node is null) - { - return null; - } - if (this.candidates.Contains(node)) - { - return this.Evaluate(node); - } - return base.Visit(node); - } - private Expression Evaluate(Expression node) - { - if (node.NodeType == ExpressionType.Constant) - { - return node; - } - LambdaExpression lambda = Expression.Lambda(node); - Delegate fn = lambda.Compile(); - return Expression.Constant(fn.DynamicInvoke(null), node.Type); - } - } - /// - /// Performs bottom-up analysis to determine which nodes can possibly - /// be part of an evaluated sub-tree. - /// - internal class Nominator : ExpressionVisitor - { - Func fnCanBeEvaluated; - HashSet candidates; - bool cannotBeEvaluated; - internal Nominator(Func fnCanBeEvaluated) - { - this.fnCanBeEvaluated = fnCanBeEvaluated; - } - internal HashSet Nominate(Expression noderession) - { - this.candidates = new HashSet(); - this.Visit(noderession); - return this.candidates; - } - public override Expression Visit(Expression node) - { - if (node is not null) - { - bool saveCannotBeEvaluated = this.cannotBeEvaluated; - this.cannotBeEvaluated = false; - base.Visit(node); - if (!this.cannotBeEvaluated) - { - if (this.fnCanBeEvaluated(node)) - { - this.candidates.Add(node); - } - else - { - this.cannotBeEvaluated = true; - } - } - this.cannotBeEvaluated |= saveCannotBeEvaluated; - } - return node; - } - } - } -} \ No newline at end of file diff --git a/src/Libraries/LinqToRedis/src/Linq/QueryProviderBase.cs b/src/Libraries/LinqToRedis/src/Linq/QueryProviderBase.cs deleted file mode 100644 index c697385e3..000000000 --- a/src/Libraries/LinqToRedis/src/Linq/QueryProviderBase.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Linq; -using System.Linq.Expressions; - -namespace UniSpy.LinqToRedis.Linq -{ - public abstract class QueryProviderBase : IQueryProvider - { - public QueryProviderBase() { } - IQueryable IQueryProvider.CreateQuery(Expression expression) => new QueryableObject(this, expression); - IQueryable IQueryProvider.CreateQuery(Expression expression) => (IQueryable)Activator.CreateInstance(typeof(QueryableObject<>).MakeGenericType(expression.Type), new object[] { this, expression }); - T IQueryProvider.Execute(Expression expression) => (T)Execute(expression); - object IQueryProvider.Execute(Expression expression) => Execute(expression); - public abstract object Execute(Expression expression); - } -} \ No newline at end of file diff --git a/src/Libraries/LinqToRedis/src/Linq/QueryableObject.cs b/src/Libraries/LinqToRedis/src/Linq/QueryableObject.cs deleted file mode 100644 index ba967bea0..000000000 --- a/src/Libraries/LinqToRedis/src/Linq/QueryableObject.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; - -namespace UniSpy.LinqToRedis.Linq -{ - public class QueryableObject : IQueryable - { - private QueryProviderBase _provider; - private Expression _expression; - public QueryableObject(QueryProviderBase provider) - { - if (provider is null) - { - throw new ArgumentNullException("provider"); - } - _provider = provider; - _expression = Expression.Constant(this); - } - public QueryableObject(QueryProviderBase provider, Expression expression) - { - if (provider is null) - { - throw new ArgumentNullException("provider"); - } - - if (expression is null) - { - throw new ArgumentNullException("expression"); - } - - if (!typeof(IQueryable).IsAssignableFrom(expression.Type)) - { - throw new ArgumentOutOfRangeException("expression"); - } - - _provider = provider; - _expression = expression; - } - public Type ElementType => typeof(T); - public Expression Expression => _expression; - public IQueryProvider Provider => _provider; - - public IEnumerator GetEnumerator() => ((IEnumerable)_provider.Execute(_expression)).GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); - } -} \ No newline at end of file diff --git a/src/Libraries/LinqToRedis/src/Linq/RedisQueryBuilder.cs b/src/Libraries/LinqToRedis/src/Linq/RedisQueryBuilder.cs deleted file mode 100644 index 82e2d304e..000000000 --- a/src/Libraries/LinqToRedis/src/Linq/RedisQueryBuilder.cs +++ /dev/null @@ -1,139 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; - -namespace UniSpy.LinqToRedis.Linq -{ - /// - /// Provide high level API for redis query building - /// - /// - public class RedisQueryBuilder : ExpressionVisitor where TKey : RedisKeyValueObject - { - public TKey KeyObject { get; private set; } - private List _builderStack = new List(); - private Expression _expression; - public RedisQueryBuilder(Expression expression) - { - _expression = expression; - } - - public void Build() - { - KeyObject = (TKey)Activator.CreateInstance(typeof(TKey)); - Visit(_expression); - System.Threading.Tasks.Parallel.For(0, _builderStack.Count, - i => - { - if (i % 2 == 0) - { - var keyProperty = KeyObject.GetType().GetProperty((string)_builderStack[i]); - // get target type - var targetType = IsNullableType(keyProperty.PropertyType) ? Nullable.GetUnderlyingType(keyProperty.PropertyType) : keyProperty.PropertyType; - // convert value to target type - var value = _builderStack[i + 1]; - // _builderStack[i + 1] = Convert.ChangeType(_builderStack[i + 1], targetType); - if (targetType.IsEnum) - { - value = Enum.ToObject(targetType, value); - } - else - { - value = Convert.ChangeType(value, targetType); - } - keyProperty.SetValue(KeyObject, value); - } - }); - } - private static bool IsNullableType(Type type) => type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>)); - - private static Expression StripQuotes(Expression node) - { - while (node.NodeType == ExpressionType.Quote) - { - node = ((UnaryExpression)node).Operand; - } - return node; - } - - protected override Expression VisitMethodCall(MethodCallExpression node) - { - Expression correctNode; - if (node.Arguments.Count > 1) - { - // this indicate the first linq expression - if (node.Arguments[0].Type.GenericTypeArguments.FirstOrDefault().IsSubclassOf(typeof(RedisKeyValueObject))) - { - correctNode = node.Arguments[1]; - } - else - { - correctNode = node.Arguments[0]; - } - } - else - { - correctNode = node.Arguments[0]; - } - - - switch (node.Method.Name) - { - case "Where": - case "Count": - case "First": - case "FirstOrDefault": - Visit(correctNode); - break; - default: - throw new NotSupportedException(string.Format("The method '{0}' is not supported", node.Method.Name)); - } - - return node; - } - protected override Expression VisitParameter(ParameterExpression node) - { - return base.VisitParameter(node); - } - protected override Expression VisitMember(MemberExpression node) - { - // we check if property do not have RedisKeyAttribute - // every property that queries must have RedisKeyAttribute - - var property = node.Member.DeclaringType.GetProperty(node.Member.Name); - if (property.GetCustomAttributes(typeof(RedisKeyAttribute), true).Count() != 1) - { - throw new NotSupportedException($"The property: {node.Member.Name} is not key, please use the property with RedisKeyAttribute or add RedisKeyAttribute to this property."); - } - _builderStack.Add(node.Member.Name); - - return node; - } - protected override Expression VisitBinary(BinaryExpression node) - { - Visit(node.Left); - switch (node.NodeType) - { - case ExpressionType.And: - case ExpressionType.AndAlso: - case ExpressionType.Equal: - break; - default: - throw new NotSupportedException(string.Format("The binary operator '{0}' is not supported", node.NodeType)); - } - Visit(node.Right); - return node; - } - - protected override Expression VisitConstant(ConstantExpression node) - { - if (node.Value is null) - { - throw new NotSupportedException("The constant must have value"); - } - _builderStack.Add(node.Value); - return node; - } - } -} \ No newline at end of file diff --git a/src/Libraries/LinqToRedis/src/Linq/RedisQueryProvider.cs b/src/Libraries/LinqToRedis/src/Linq/RedisQueryProvider.cs deleted file mode 100644 index aa535848a..000000000 --- a/src/Libraries/LinqToRedis/src/Linq/RedisQueryProvider.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; - -namespace UniSpy.LinqToRedis.Linq -{ - public class RedisQueryProvider : QueryProviderBase where TValue : RedisKeyValueObject - { - private RedisClient _client; - public RedisQueryProvider(RedisClient client) : base() - { - _client = client; - } - - public override object Execute(Expression expression) - { - // if (node.Method.Name == "ToList") - /* TODO currently we do not know how to get the ToList() function name - we just simply do this*/ - if (expression.GetType() == typeof(ConstantExpression)) - { - return _client.GetKeyValues().Values; - } - var node = (MethodCallExpression)expression; - - if (node.Method.Name == "Count" && node.Arguments.Count == 1) - { - return _client.GetMatchedKeys().Count; - } - - var matchedKeys = new List(); - expression = QueryEvaluator.PartialEval(expression); - var builder = new RedisQueryBuilder(expression); - builder.Build(); - - if (node.Method.Name == "Count" && node.Arguments.Count != 1) - { - return _client.GetMatchedKeys(builder.KeyObject).Count; - } - - var values = _client.GetValues(builder.KeyObject); - - switch (node.Method.Name) - { - case "Where": - return values; - case "FirstOrDefault": - return values.FirstOrDefault(); - case "First": - if (values.Count == 0) - { - throw new InvalidOperationException("The result is empty, try to use FirstOrDefault instead."); - } - return values[0]; - // return values.First(); - default: - throw new NotSupportedException(string.Format("The method '{0}' is not supported", node.Method.Name)); - } - } - } -} \ No newline at end of file diff --git a/src/Libraries/LinqToRedis/src/UniSpy.LinqToRedis.csproj b/src/Libraries/LinqToRedis/src/UniSpy.LinqToRedis.csproj deleted file mode 100644 index 7f852da9c..000000000 --- a/src/Libraries/LinqToRedis/src/UniSpy.LinqToRedis.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - net6.0 - UniSpy.LinqToRedis - 1.0.4 - xiaojiuwo - GameProgressive - true - ..\..\..\..\common\Icon\UniSpy_Logo.ico - - - AnyCPU - ..\..\..\..\build\$(Configuration) - - - ..\..\..\..\build\$(Configuration) - - - - - - - diff --git a/src/Libraries/LinqToRedis/test/LinqToRedisTest.cs b/src/Libraries/LinqToRedis/test/LinqToRedisTest.cs deleted file mode 100644 index a82e797b6..000000000 --- a/src/Libraries/LinqToRedis/test/LinqToRedisTest.cs +++ /dev/null @@ -1,173 +0,0 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using Newtonsoft.Json; -using UniSpy.LinqToRedis; -using Xunit; - -namespace UniSpy.Redis.Test -{ - public class LinqToRedisTest - { - [Fact] - public void GetAllValues() - { - var redis = new RedisClient(); - var data = redis.Context.ToList(); - } - [Fact] - public void PerformaceTest() - { - // Given - var redisClient = new RedisClient(); - var value = new UserInfo - { - Cookie = 0, - ServerID = new Guid(), - UserName = "hello0", - RemoteEndPoint = "127.0.0.1:7890" - }; - - // linqtoredis performance - // When - var start = System.DateTime.Now; - for (var i = 0; i < 100; i++) - { - redisClient.SetValue(value); - value.Cookie++; - } - Console.WriteLine("linqtoredis sync: {0}", (System.DateTime.Now.Subtract(start).TotalSeconds)); - - start = System.DateTime.Now; - - for (var i = 0; i < 100; i++) - { - _ = redisClient.SetValueAsync(value); - value.Cookie++; - } - - Console.WriteLine("linqtoredis async: {0}", (System.DateTime.Now.Subtract(start).TotalSeconds)); - // natural redis api performance - start = System.DateTime.Now; - for (var i = 0; i < 100; i++) - { - redisClient.Db.StringSet(value.FullKey, JsonConvert.SerializeObject(value)); - value.Cookie++; - } - Console.WriteLine("natural redis api sync: {0}", (System.DateTime.Now.Subtract(start).TotalSeconds)); - start = System.DateTime.Now; - - for (var i = 0; i < 100; i++) - { - redisClient.Db.StringSetAsync(value.FullKey, JsonConvert.SerializeObject(value)); - value.Cookie++; - } - Console.WriteLine("natural redis api async: {0}", (System.DateTime.Now.Subtract(start).TotalSeconds)); - } - [Fact] - public void ReadTest1() - { - var redis = new RedisClient(); - var data2 = redis.Context.Where(k => k.Cookie == 0).ToList(); - var data3 = redis.Context.Where(k => k.Cookie == 0).FirstOrDefault(); - var data4 = redis.Context.FirstOrDefault(k => k.Cookie == 0); - } - [Fact] - public void ReadTest2() - { - var redis = new RedisClient(); - var data2 = redis.Context.Where(k => k.RemoteEndPoint == "127.0.0.1:7777").ToList(); - Console.WriteLine(data2.Count); - } - [Fact] - public void WriteTest1() - { - var redis = new RedisClient(); - var value = new UserInfo - { - Cookie = 0, - ServerID = new Guid(), - UserName = "hello0", - RemoteEndPoint = "127.0.0.1:7890" - }; - - redis.SetValue(value); - } - [Fact] - public void WriteTest2() - { - var redis = new RedisClient(); - - for (int i = 0; i < 100; i++) - { - var value = new UserInfo - { - Cookie = 0, - ServerID = new Guid(), - UserName = "hello2", - RemoteEndPoint = $"127.0.0.1:{i}" - }; - redis.SetValue(value); - } - } - [Fact] - public void IndexWriteTest() - { - var redis = new RedisClient(); - - for (int i = 0; i < 100; i++) - { - var value = new UserInfo - { - Cookie = 0, - ServerID = new Guid(), - UserName = "hello2", - RemoteEndPoint = $"127.0.0.1:{i}" - }; - // you can directly using value object to set value - redis[value] = value; - // or for understanding you can convert value object to IRedisKey - var key = (IRedisKey)value; - redis[key] = value; - } - } - [Fact] - public void IndexReadTest() - { - var redis = new RedisClient(); - - for (int i = 0; i < 100; i++) - { - var key = new UserInfo - { - Cookie = i, - ServerID = new Guid() - }; - var value = redis[key]; - } - } - - [Fact] - public void CountTest() - { - var redis = new RedisClient(); - var data1 = redis.Context.Count(); - var data2 = redis.Context.Count(k => k.Cookie == 134); - Assert.Throws(() => redis.Context.First(k => k.Cookie == 134)); - var data4 = redis.Context.Where(k => k.Cookie == 0).First(); - } - [Fact] - public void SearchKeyBuild() - { - // Given - var user1 = new UserInfo() { Cookie = 0 }; - var key1 = user1.SearchKey; - - var user2 = new UserInfo() { ServerID = Guid.NewGuid(), Cookie = 0 }; - var key2 = user2.SearchKey; - - var user3 = new UserInfo() { ServerID = Guid.NewGuid(), Cookie = 0, UserName = "xiaojiuwo", RemoteEndPoint = "192.168.1.1" }; - var key3 = user3.SearchKey; - } - } -} diff --git a/src/Libraries/LinqToRedis/test/NatNeg/RedisClient.cs b/src/Libraries/LinqToRedis/test/NatNeg/RedisClient.cs deleted file mode 100644 index 179b6338b..000000000 --- a/src/Libraries/LinqToRedis/test/NatNeg/RedisClient.cs +++ /dev/null @@ -1,10 +0,0 @@ - -namespace UniSpy.Redis.Test -{ - internal class RedisClient : UniSpy.LinqToRedis.RedisClient - { - public RedisClient() : base("127.0.0.1:6379", 10) - { - } - } -} \ No newline at end of file diff --git a/src/Libraries/LinqToRedis/test/NatNeg/UserInfo.cs b/src/Libraries/LinqToRedis/test/NatNeg/UserInfo.cs deleted file mode 100644 index 5ffd9b2d7..000000000 --- a/src/Libraries/LinqToRedis/test/NatNeg/UserInfo.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using UniSpy.LinqToRedis; - -namespace UniSpy.Redis.Test -{ - public record UserInfo : RedisKeyValueObject - { - [RedisKey] - public Guid? ServerID { get; set; } - [RedisKey] - public int? Cookie { get; set; } - [RedisKey] - public string RemoteEndPoint { get; set; } - public string UserName { get; set; } - public UserInfo() : base(TimeSpan.FromMinutes(3)) - { - // we set the expire time to 3 minutes - } - - } -} \ No newline at end of file diff --git a/src/Libraries/LinqToRedis/test/UniSpy.LinqToRedis.Test.csproj b/src/Libraries/LinqToRedis/test/UniSpy.LinqToRedis.Test.csproj deleted file mode 100644 index 8c5e9adbf..000000000 --- a/src/Libraries/LinqToRedis/test/UniSpy.LinqToRedis.Test.csproj +++ /dev/null @@ -1,24 +0,0 @@ - - - - net6.0 - - false - - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - diff --git a/src/Servers/Chat/src/Abstraction/BaseClass/Channel/ChannelHandlerBase.cs b/src/Servers/Chat/src/Abstraction/BaseClass/Channel/ChannelHandlerBase.cs deleted file mode 100755 index ca0c2364c..000000000 --- a/src/Servers/Chat/src/Abstraction/BaseClass/Channel/ChannelHandlerBase.cs +++ /dev/null @@ -1,57 +0,0 @@ -using UniSpy.Server.Chat.Error.IRC.Channel; -using UniSpy.Server.Chat.Error.IRC.General; -using UniSpy.Server.Chat.Aggregate; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Chat.Abstraction.Interface; - -namespace UniSpy.Server.Chat.Abstraction.BaseClass -{ - public abstract class ChannelHandlerBase : LogedInHandlerBase - { - /// - /// The matched channel of chat request - /// - protected Channel _channel; - /// - /// The channel user of current IClient - /// - protected ChannelUser _user; - private new ChannelRequestBase _request => (ChannelRequestBase)base._request; - public ChannelHandlerBase(IChatClient client, IRequest request) : base(client, request) { } - - protected override void RequestCheck() - { - // we handle join when get user nickname - if (!_client.Info.IsNickNameSet) - { - lock (_client.Info.HandlerStack) - { - _client.Info.HandlerStack.Add(this); - } - throw new Chat.HandleLaterException($"{this.GetType().Name} is saved until nickname is set."); - } - if (_request.RawRequest is not null) - { - base.RequestCheck(); - } - _channel = _client.Info.GetJoinedChannel(_request.ChannelName); - if (_channel is null) - { - throw new NoSuchChannelException($"No such channel {_request.ChannelName}", _request.ChannelName); - } - _user = _channel.GetUser(_client); - if (_user is null) - { - throw new NoSuchNickException($"Can not find user with nickname: {_client.Info.NickName} username: {_client.Info.UserName}"); - } - } - protected override void PublishMessage() - { - if (_channel is null) - { - return; - } - base.PublishMessage(); - } - } -} diff --git a/src/Servers/Chat/src/Abstraction/BaseClass/Channel/ChannelRequestBase.cs b/src/Servers/Chat/src/Abstraction/BaseClass/Channel/ChannelRequestBase.cs deleted file mode 100755 index 97a561766..000000000 --- a/src/Servers/Chat/src/Abstraction/BaseClass/Channel/ChannelRequestBase.cs +++ /dev/null @@ -1,20 +0,0 @@ - -namespace UniSpy.Server.Chat.Abstraction.BaseClass -{ - public class ChannelRequestBase : RequestBase - { - public string ChannelName { get; set; } - public ChannelRequestBase() { } - public ChannelRequestBase(string rawRequest) : base(rawRequest) { } - public override void Parse() - { - base.Parse(); - - if (_cmdParams is null || _cmdParams?.Count < 1) - { - throw new Chat.Exception("Channel name is missing."); - } - ChannelName = _cmdParams[0]; - } - } -} diff --git a/src/Servers/Chat/src/Abstraction/BaseClass/Channel/ChannelResponseBase.cs b/src/Servers/Chat/src/Abstraction/BaseClass/Channel/ChannelResponseBase.cs deleted file mode 100755 index 05436bc31..000000000 --- a/src/Servers/Chat/src/Abstraction/BaseClass/Channel/ChannelResponseBase.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace UniSpy.Server.Chat.Abstraction.BaseClass -{ - public abstract class ChannelResponseBase : ResponseBase - { - protected new ChannelRequestBase _request => (ChannelRequestBase)base._request; - protected ChannelResponseBase(RequestBase request, ResultBase result) : base(request, result){ } - } -} diff --git a/src/Servers/Chat/src/Abstraction/BaseClass/CmdHandlerBase.cs b/src/Servers/Chat/src/Abstraction/BaseClass/CmdHandlerBase.cs deleted file mode 100755 index f8ad166d4..000000000 --- a/src/Servers/Chat/src/Abstraction/BaseClass/CmdHandlerBase.cs +++ /dev/null @@ -1,82 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Aggregate.Redis.Contract; -using UniSpy.Server.Chat.Error.IRC.General; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Logging; - -namespace UniSpy.Server.Chat.Abstraction.BaseClass -{ - /// - /// error code condition is complicated - /// there are 2 types error code - /// 1.irc numeric error code - /// 2.self defined code - /// we do not want to send self defined code, so if we find errorCode < noerror - /// we just return. - /// if error code bigger than noerror we need to process it in ConstructResponse() - ///we also need to check the error code != noerror in ConstructResponse() - /// - public abstract class CmdHandlerBase : UniSpy.Server.Core.Abstraction.BaseClass.CmdHandlerBase - { - protected new IChatClient _client => (IChatClient)base._client; - protected new RequestBase _request => (RequestBase)base._request; - protected new ResultBase _result { get => (ResultBase)base._result; set => base._result = value; } - protected new ResponseBase _response { get => (ResponseBase)base._response; set => base._response = value; } - public CmdHandlerBase(IChatClient client, IRequest request) : base(client, request) { } - //if we use this structure the error response should also write to _sendingBuffer - protected override void HandleException(System.Exception ex) - { - if (ex is IRCException) - { - _client.Send(((IRCException)ex)); - } - else if (ex is HandleLaterException) - { - // if the exception is HandleLaterException, we log it as warning - _client.LogWarn(ex.Message); - return; - } - - base.HandleException(ex); - } - protected override void Response() - { - if (_client.Info.IsQuietMode) - { - return; - } - base.Response(); - } - /// - /// publish message to redis channel - /// - protected virtual void PublishMessage() - { - // we do not publish message when the message is received from remote client - if (_client.Info.IsRemoteClient) - { - return; - } - // if rawrequest is null means the request is generated by us, we do not publish custom requests - if (_request.RawRequest is null) - { - return; - } - var msg = new RemoteMessage(_request, _client.GetRemoteClient()); - Application.Server.GeneralChannel.PublishMessage(msg); - } - public override void Handle() - { - base.Handle(); - try - { - // we publish this message to redis channel - PublishMessage(); - } - catch (Exception ex) - { - HandleException(ex); - } - } - } -} diff --git a/src/Servers/Chat/src/Abstraction/BaseClass/General/LogedInHandlerBase.cs b/src/Servers/Chat/src/Abstraction/BaseClass/General/LogedInHandlerBase.cs deleted file mode 100755 index 1c6237992..000000000 --- a/src/Servers/Chat/src/Abstraction/BaseClass/General/LogedInHandlerBase.cs +++ /dev/null @@ -1,29 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.Chat.Abstraction.BaseClass -{ - public abstract class LogedInHandlerBase : CmdHandlerBase - { - public LogedInHandlerBase(IChatClient client, IRequest request) : base(client, request) { } - - // public override void Handle() - // { - // if (!_client.Info.IsLoggedIn) - // { - // _client.LogInfo($"{_client.Info.NickName} Please login first!"); - // return; - // } - - // base.Handle(); - // } - protected override void RequestCheck() - { - if (!_client.Info.IsLoggedIn) - { - new Chat.Exception($"{_client.Info.NickName} Please login first!"); - } - base.RequestCheck(); - } - } -} diff --git a/src/Servers/Chat/src/Abstraction/BaseClass/Message/MessageHandlerBase.cs b/src/Servers/Chat/src/Abstraction/BaseClass/Message/MessageHandlerBase.cs deleted file mode 100755 index ebc05eedc..000000000 --- a/src/Servers/Chat/src/Abstraction/BaseClass/Message/MessageHandlerBase.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System.Linq; -using UniSpy.Server.Chat.Abstraction.BaseClass.Message; -using UniSpy.Server.Chat.Error.IRC.General; -using UniSpy.Server.Chat.Aggregate; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Chat.Application; -using UniSpy.Server.Chat.Abstraction.Interface; - -namespace UniSpy.Server.Chat.Abstraction.BaseClass -{ - public abstract class MessageHandlerBase : ChannelHandlerBase - { - protected new MessageRequestBase _request => (MessageRequestBase)base._request; - protected new MessageResultBase _result { get => (MessageResultBase)base._result; set => base._result = value; } - protected ChannelUser _receiver; - public MessageHandlerBase(IChatClient client, IRequest request) : base(client, request) { } - - protected override void RequestCheck() - { - _request.Parse(); - switch (_request.Type) - { - case MessageType.ChannelMessage: - ChannelMessageRequestCheck(); - break; - case MessageType.UserMessage: - UserMessageRequestCheck(); - break; - default: - throw new Chat.Exception("Unknown chat message request type."); - } - } - protected virtual void ChannelMessageRequestCheck() => base.RequestCheck(); - protected virtual void UserMessageRequestCheck() - { - // todo check if we only allow user join one channel - // fist we find this user in our local client pool, beacuse nick name is unique, this search is safe - var client = ClientManager.GetClientByNickName(_request.NickName); - // we get a first channel in his joined list - _channel = client.Info.JoinedChannels.Values.First(); - // we find this user in this channel - _receiver = _channel.GetUser(_request.NickName); - if (_receiver is null) - { - throw new NoSuchNickException( - $"No nickname: {_request.NickName} found in channel: {_channel.Name}."); - } - } - protected override void DataOperation() - { - _result.UserIRCPrefix = _client.Info.IRCPrefix; - switch (_request.Type) - { - case MessageType.ChannelMessage: - _result.TargetName = _request.ChannelName; - ChannelMessageDataOpration(); - break; - case MessageType.UserMessage: - _result.TargetName = _request.NickName; - UserMessageDataOperation(); - break; - } - } - - protected virtual void ChannelMessageDataOpration() { } - protected virtual void UserMessageDataOperation() { } - protected override void Response() - { - // response can not be null! - switch (_request.Type) - { - case MessageType.ChannelMessage: - _channel.MultiCast(_user.Client, _response, true); - break; - case MessageType.UserMessage: - _receiver.Client.Send(_response); - break; - } - } - } -} diff --git a/src/Servers/Chat/src/Abstraction/BaseClass/Message/MessageRequestBase.cs b/src/Servers/Chat/src/Abstraction/BaseClass/Message/MessageRequestBase.cs deleted file mode 100644 index 7aa6ea71d..000000000 --- a/src/Servers/Chat/src/Abstraction/BaseClass/Message/MessageRequestBase.cs +++ /dev/null @@ -1,34 +0,0 @@ -namespace UniSpy.Server.Chat.Abstraction.BaseClass -{ - public enum MessageType - { - ChannelMessage, - UserMessage - } - - public abstract class MessageRequestBase : ChannelRequestBase - { - public MessageRequestBase(string rawRequest) : base(rawRequest){ } - public MessageType? Type { get; protected set; } - public string NickName { get; protected set; } - public string Message { get; protected set; } - - public override void Parse() - { - base.Parse(); - - if (ChannelName.Contains("#")) - { - Type = MessageType.ChannelMessage; - } - else - { - // todo check if there need user message - Type = MessageType.UserMessage; - ChannelName = null; - NickName = _cmdParams[0]; - } - Message = _longParam; - } - } -} diff --git a/src/Servers/Chat/src/Abstraction/BaseClass/Message/MessageResultBase.cs b/src/Servers/Chat/src/Abstraction/BaseClass/Message/MessageResultBase.cs deleted file mode 100755 index e39e9434a..000000000 --- a/src/Servers/Chat/src/Abstraction/BaseClass/Message/MessageResultBase.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace UniSpy.Server.Chat.Abstraction.BaseClass.Message -{ - public abstract class MessageResultBase : ResultBase - { - public string UserIRCPrefix { get; set; } - public string TargetName { get; set; } - protected MessageResultBase(){ } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Abstraction/BaseClass/RequestBase.cs b/src/Servers/Chat/src/Abstraction/BaseClass/RequestBase.cs deleted file mode 100755 index 6402a933c..000000000 --- a/src/Servers/Chat/src/Abstraction/BaseClass/RequestBase.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Newtonsoft.Json; - -namespace UniSpy.Server.Chat.Abstraction.BaseClass -{ - public class RequestBase : UniSpy.Server.Core.Abstraction.BaseClass.RequestBase - { - /// - /// True means there are no errors - /// False means there are errors - /// - [JsonProperty] - public new string RawRequest { get => (string)base.RawRequest; set => base.RawRequest = value; } - [JsonProperty] - public new string CommandName { get => (string)base.CommandName; protected set => base.CommandName = value; } - [JsonProperty] - protected string _prefix; - [JsonProperty] - protected List _cmdParams; - [JsonProperty] - protected string _longParam; - public RequestBase() { } - /// - /// create instance for Handler - /// - /// - public RequestBase(string rawRequest) : base(rawRequest) { } - - public override void Parse() - { - // at most 2 colon character - // we do not sure about all command - // so i block this code here - RawRequest = RawRequest.Replace("\r", "").Replace("\n", ""); - List dataFrag = new List(); - - if (RawRequest.Where(r => r.Equals(':')).Count() > 2) - { - throw new Chat.Exception($"IRC request is invalid {RawRequest}"); - } - - int indexOfColon = RawRequest.IndexOf(':'); - - string rawRequest = RawRequest; - if (indexOfColon == 0 && indexOfColon != -1) - { - int prefixIndex = rawRequest.IndexOf(' '); - _prefix = rawRequest.Substring(indexOfColon, prefixIndex); - rawRequest = rawRequest.Substring(prefixIndex); - } - - indexOfColon = rawRequest.IndexOf(':'); - if (indexOfColon != 0 && indexOfColon != -1) - { - _longParam = rawRequest.Substring(indexOfColon + 1); - //reset the request string - rawRequest = rawRequest.Remove(indexOfColon); - } - - dataFrag = rawRequest.Trim(' ').Split(' ', StringSplitOptions.RemoveEmptyEntries).ToList(); - - CommandName = dataFrag[0]; - - if (dataFrag.Count > 1) - { - _cmdParams = dataFrag.Skip(1).ToList(); - } - } - - public static string GetCommandName(string request) - { - // at most 2 colon character - // we do not sure about all command - // so i block this code here - List dataFrag = new List(); - - if (request.Where(r => r.Equals(':')).Count() > 2) - { - return null; - } - - int indexOfColon = request.IndexOf(':'); - - string rawRequest = request; - if (indexOfColon == 0 && indexOfColon != -1) - { - int prefixIndex = rawRequest.IndexOf(' '); - var prefix = rawRequest.Substring(indexOfColon, prefixIndex); - rawRequest = rawRequest.Substring(prefixIndex); - } - - indexOfColon = rawRequest.IndexOf(':'); - if (indexOfColon != 0 && indexOfColon != -1) - { - var longParam = rawRequest.Substring(indexOfColon + 1); - //reset the request string - rawRequest = rawRequest.Remove(indexOfColon); - } - - dataFrag = rawRequest.Trim(' ').Split(' ', StringSplitOptions.RemoveEmptyEntries).ToList(); - - return dataFrag[0]; - } - } -} diff --git a/src/Servers/Chat/src/Abstraction/BaseClass/ResponseBase.cs b/src/Servers/Chat/src/Abstraction/BaseClass/ResponseBase.cs deleted file mode 100755 index 7fa64e9fe..000000000 --- a/src/Servers/Chat/src/Abstraction/BaseClass/ResponseBase.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace UniSpy.Server.Chat.Abstraction.BaseClass -{ - public abstract class ResponseBase : UniSpy.Server.Core.Abstraction.BaseClass.ResponseBase - { - public const string ServerDomain = "unispy.net"; - public new string SendingBuffer{ get => (string)base.SendingBuffer; - protected set => base.SendingBuffer = value; } - protected new ResultBase _result => (ResultBase)base._result; - protected new RequestBase _request => (RequestBase)base._request; - public ResponseBase(RequestBase request, ResultBase result) : base(request, result){ } - } -} diff --git a/src/Servers/Chat/src/Abstraction/BaseClass/ResultBase.cs b/src/Servers/Chat/src/Abstraction/BaseClass/ResultBase.cs deleted file mode 100755 index 20652bb87..000000000 --- a/src/Servers/Chat/src/Abstraction/BaseClass/ResultBase.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace UniSpy.Server.Chat.Abstraction.BaseClass -{ - public abstract class ResultBase : UniSpy.Server.Core.Abstraction.BaseClass.ResultBase - { - public ResultBase(){ } - } -} diff --git a/src/Servers/Chat/src/Abstraction/Interface/IChannel.cs b/src/Servers/Chat/src/Abstraction/Interface/IChannel.cs deleted file mode 100644 index c61e5f6c4..000000000 --- a/src/Servers/Chat/src/Abstraction/Interface/IChannel.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Chat.Aggregate; -using UniSpy.Server.Chat.Contract.Request.Channel; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.Chat.Abstraction.Interface -{ - public interface IChannel - { - void MultiCast(IClient sender, IResponse message, bool isSkipSender); - // void MultiCastExceptSender(ChannelUser sender, IResponse message); - string GetAllUsersNickString(); - void AddBindOnUserAndChannel(ChannelUser joiner); - void RemoveBindOnUserAndChannel(ChannelUser leaver); - ChannelUser GetChannelUser(IClient client); - bool IsUserBanned(ChannelUser user); - void SetProperties(ChannelUser changer, ModeRequest request); - void SetChannelKeyValue(Dictionary keyValue); - string GetChannelValueString(List keys); - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Abstraction/Interface/IChatClient.cs b/src/Servers/Chat/src/Abstraction/Interface/IChatClient.cs deleted file mode 100644 index dca1ab89d..000000000 --- a/src/Servers/Chat/src/Abstraction/Interface/IChatClient.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.Chat.Aggregate; -using UniSpy.Server.Chat.Application; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.Chat.Abstraction.Interface -{ - public interface IChatClient : IClient - { - public new ClientInfo Info { get; } - public RemoteClient GetRemoteClient(); - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Abstraction/Interface/IStorageOperation.cs b/src/Servers/Chat/src/Abstraction/Interface/IStorageOperation.cs deleted file mode 100644 index 4a33f559e..000000000 --- a/src/Servers/Chat/src/Abstraction/Interface/IStorageOperation.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace UniSpy.Server.Chat.Abstraction.Interface -{ - public interface IStorageOperation - { - (int userId, int profileId, bool emailVerified, bool banned) NickAndEmailLogin(string nickName, string email, string passwordHash); - (int userId, int profileId, bool emailVerified, bool banned) UniqueNickLogin(string uniqueNick, int namespaceId); - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Aggregate/ChannelManager.cs b/src/Servers/Chat/src/Aggregate/ChannelManager.cs deleted file mode 100644 index 1c4e9349d..000000000 --- a/src/Servers/Chat/src/Aggregate/ChannelManager.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.Collections.Concurrent; -using UniSpy.Server.Chat.Abstraction.Interface; - -namespace UniSpy.Server.Chat.Aggregate -{ - public static class ChannelManager - { - public static readonly ConcurrentDictionary Channels = new ConcurrentDictionary(); - public static bool IsChannelExist(string name) - { - return Channels.ContainsKey(name); - } - /// - /// You need to manually check channel existance then get channel - /// - /// - /// - public static Channel GetChannel(string name) - { - if (!Channels.TryGetValue(name, out var channel)) - { - throw new Chat.Exception("Channel do not exist!"); - } - return channel; - } - public static void RemoveChannel(string name) - { - Channels.TryRemove(name, out var chan); - var chanInfo = chan.GetChannelCache(); - QueryReport.Application.StorageOperation.RemoveChannel(chanInfo); - } - public static Channel CreateChannel(string name, string password = null, IChatClient creator = null) - { - var channel = new Channel(name, creator, password); - - if (!Channels.TryAdd(name, channel)) - { - Channels.TryGetValue(name, out channel); - } - return channel; - } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Aggregate/ChannelMode.cs b/src/Servers/Chat/src/Aggregate/ChannelMode.cs deleted file mode 100755 index 3d5df82c2..000000000 --- a/src/Servers/Chat/src/Aggregate/ChannelMode.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System.Collections.Generic; -using System.Text; -using Newtonsoft.Json; -using UniSpy.Server.Chat.Contract.Request.Channel; - -namespace UniSpy.Server.Chat.Aggregate -{ - public sealed class ChannelMode - { - //i - toggle the invite-only channel flag; - [JsonProperty] - public bool IsInviteOnly { get; private set; } = false; - //p - toggle the private channel flag; - [JsonProperty] - public bool IsPrivateChannel { get; private set; } = false; - //s - toggle the secret channel flag; - [JsonProperty] - public bool IsSecretChannel { get; private set; } = false; - //m - toggle the moderated channel; - [JsonProperty] - public bool IsModeratedChannel { get; private set; } = false; - //n - toggle the no messages to channel from clients on the outside; - [JsonProperty] - public bool IsAllowExternalMessage { get; private set; } = false; - //t - toggle the topic settable by channel operator only flag; - [JsonProperty] - public bool IsTopicOnlySetByChannelOperator { get; private set; } = true; - // e - toggle the operator allow channel limits flag; - [JsonProperty] - public bool IsOperatorAbeyChannelLimits { get; private set; } = true; - public List InviteNickNames { get; private set; } = new List(); - /// - /// default constructor - /// - public ChannelMode() - { - } - - public void SetChannelModes(ModeOperationType operation) - { - switch (operation) - { - case ModeOperationType.SetOperatorAbeyChannelLimits: - IsOperatorAbeyChannelLimits = true; - break; - case ModeOperationType.RemoveOperatorAbeyChannelLimits: - IsOperatorAbeyChannelLimits = false; - break; - case ModeOperationType.SetInvitedOnly: - IsInviteOnly = true; - break; - case ModeOperationType.RemoveInvitedOnly: - IsInviteOnly = false; - break; - case ModeOperationType.SetPrivateChannelFlag: - IsPrivateChannel = true; - break; - case ModeOperationType.RemovePrivateChannelFlag: - IsPrivateChannel = false; - break; - case ModeOperationType.SetSecretChannelFlag: - IsSecretChannel = true; - break; - case ModeOperationType.RemoveSecretChannelFlag: - IsSecretChannel = false; - break; - case ModeOperationType.SetModeratedChannelFlag: - IsModeratedChannel = true; - break; - case ModeOperationType.RemoveModeratedChannelFlag: - IsModeratedChannel = false; - break; - case ModeOperationType.EnableExternalMessagesFlag: - IsAllowExternalMessage = true; - break; - case ModeOperationType.DisableExternalMessagesFlag: - IsAllowExternalMessage = false; - break; - case ModeOperationType.SetTopicChangeByOperatorFlag: - IsTopicOnlySetByChannelOperator = true; - break; - case ModeOperationType.RemoveTopicChangeByOperatorFlag: - IsTopicOnlySetByChannelOperator = false; - break; - } - } - - public override string ToString() - { - - var buffer = new StringBuilder(); - - buffer.Append("+"); - if (IsInviteOnly) - { - buffer.Append("i"); - } - if (IsPrivateChannel) - { - buffer.Append("p"); - } - if (IsSecretChannel) - { - buffer.Append("s"); - } - if (IsModeratedChannel) - { - buffer.Append("m"); - } - if (IsAllowExternalMessage) - { - buffer.Append("n"); - } - if (IsTopicOnlySetByChannelOperator) - { - buffer.Append("t"); - } - - //response is like +nt - return buffer.ToString(); - } - } -} diff --git a/src/Servers/Chat/src/Aggregate/ChannelProperty/ChannelGeneral.cs b/src/Servers/Chat/src/Aggregate/ChannelProperty/ChannelGeneral.cs deleted file mode 100755 index a663dbebc..000000000 --- a/src/Servers/Chat/src/Aggregate/ChannelProperty/ChannelGeneral.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Linq; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.QueryReport.Aggregate.Redis.Channel; - -namespace UniSpy.Server.Chat.Aggregate -{ - public sealed partial class Channel - { - public Guid ServerId { get; private set; } - public string GameName { get; private set; } - /// - /// Channel name - /// - public string Name { get; private set; } - /// - /// The maximum number of users that can be in the channel - /// - public int MaxNumberUser { get; private set; } = 200; - public DateTime CreateTime { get; private set; } = DateTime.Now; - /// - /// Channel key values - /// - public KeyValueManager KeyValues { get; private set; } = new KeyValueManager(); - public PeerRoomType? RoomType { get; private set; } - public string Password { get; private set; } - public string Topic { get; set; } - public Redis.ChatMessageChannel MessageBroker { get; private set; } - public int? GroupId { get; private set; } - public string RoomName { get; private set; } - public bool IsValidPeerRoom => GroupId is not null && RoomName is not null; - public string PreviousJoinedChannel { get; private set; } - public Channel(string name, IChatClient client, string password = null) - { - ServerId = client.Server.Id; - Name = name; - Password = password; - RoomType = PeerRoom.GetRoomType(Name); - GameName = client.Info.GameName; - PreviousJoinedChannel = client.Info.PreviousJoinedChannel; - switch (RoomType) - { - case PeerRoomType.Group: - GetGroupId(); - GetPeerRoomName(); - break; - case PeerRoomType.Staging: - GetStagingRoomName(); - break; - case PeerRoomType.Title: - GetTitileRoomName(); - break; - } - MessageBroker = new Redis.ChatMessageChannel(Name); - MessageBroker.Subscribe(); - } - private void GetGroupId() - { - var groupIdStr = Name.Split("!", StringSplitOptions.RemoveEmptyEntries)[1]; - if (!int.TryParse(groupIdStr, out var groupId)) - { - throw new Chat.Exception("Peer room group id is incorrect"); - } - GroupId = groupId; - } - private void GetPeerRoomName() - { - if (QueryReport.Application.StorageOperation.PeerGroupList.ContainsKey(GameName)) - { - var grouplist = QueryReport.Application.StorageOperation.PeerGroupList[GameName]; - var room = grouplist.Where(g => g.Groupid == GroupId).FirstOrDefault(); - if (room is null) - { - throw new Chat.Exception($"Invalid peer room: {Name}"); - } - RoomName = room.Roomname; - } - } - private void GetStagingRoomName() - { - RoomName = Name.Split('!', StringSplitOptions.RemoveEmptyEntries).Last(); - } - private void GetTitileRoomName() => GetStagingRoomName(); - } -} diff --git a/src/Servers/Chat/src/Aggregate/ChannelProperty/ChannelModeRelated.cs b/src/Servers/Chat/src/Aggregate/ChannelProperty/ChannelModeRelated.cs deleted file mode 100644 index 19ef95dd4..000000000 --- a/src/Servers/Chat/src/Aggregate/ChannelProperty/ChannelModeRelated.cs +++ /dev/null @@ -1,62 +0,0 @@ -using Newtonsoft.Json; -using UniSpy.Server.Chat.Contract.Request.Channel; - -namespace UniSpy.Server.Chat.Aggregate -{ - public partial class Channel - { - [JsonProperty] - public ChannelMode Mode { get; private set; } = new ChannelMode(); - - /// - /// We only care about how to set mode in this channel - /// we do not need to care about if the user is legal - /// because MODEHandler will check for us - /// - /// - /// - public void SetProperties(ChannelUser changer, ModeRequest request) - { - // todo check permission of each operation - foreach (var op in request.ModeOperations) - { - switch (op) - { - case ModeOperationType.AddChannelUserLimits: - MaxNumberUser = request.LimitNumber; - break; - case ModeOperationType.RemoveChannelUserLimits: - MaxNumberUser = 200; - break; - case ModeOperationType.AddBanOnUser: - BanUser(request); - break; - case ModeOperationType.RemoveBanOnUser: - UnBanUser(request); - break; - case ModeOperationType.AddChannelPassword: - Password = request.Password; - break; - case ModeOperationType.RemoveChannelPassword: - Password = null; - break; - case ModeOperationType.AddChannelOperator: - AddChannelOperator(request); - break; - case ModeOperationType.RemoveChannelOperator: - RemoveChannelOperator(request); - break; - case ModeOperationType.EnableUserVoicePermission: - EnableUserVoicePermission(request); - break; - case ModeOperationType.DisableUserVoicePermission: - DisableUserVoicePermission(request); - break; - default: - Mode.SetChannelModes(op); - break; - } - } - } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Aggregate/ChannelProperty/ChannelOperation.cs b/src/Servers/Chat/src/Aggregate/ChannelProperty/ChannelOperation.cs deleted file mode 100644 index cb92487bf..000000000 --- a/src/Servers/Chat/src/Aggregate/ChannelProperty/ChannelOperation.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Linq; -using UniSpy.Server.QueryReport.Aggregate.Redis.Channel; - -namespace UniSpy.Server.Chat.Aggregate -{ - public partial class Channel - { - public ChannelInfo GetChannelCache() - { - var chanInfo = new ChannelInfo() - { - ServerId = this.ServerId, - Name = this.Name, - MaxNumberUser = this.MaxNumberUser, - CreateTime = this.CreateTime, - RoomType = this.RoomType, - GameName = this.GameName, - PreviousJoinedChannel = this.PreviousJoinedChannel, - Users = this.Users.Where(u => u.Value.Info.IsRemoteClient == false).Select(u => u.Key).ToList() - }; - return chanInfo; - } - public static void UpdateChannelCache(ChannelUser user) - { - if (user.Client.Info.IsRemoteClient) - { - return; - } - var channelInfo = user.Channel.GetChannelCache(); - if (!QueryReport.Application.StorageOperation.UpdateChannel(channelInfo)) - { - throw new Error.IRC.Channel.NoSuchChannelException("Update channel on redis fail.", user.Channel.Name); - } - } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Aggregate/ChannelProperty/ChannelUserRelated.cs b/src/Servers/Chat/src/Aggregate/ChannelProperty/ChannelUserRelated.cs deleted file mode 100644 index d5fbff554..000000000 --- a/src/Servers/Chat/src/Aggregate/ChannelProperty/ChannelUserRelated.cs +++ /dev/null @@ -1,225 +0,0 @@ -using Newtonsoft.Json; -using System.Collections.Concurrent; -using System.Linq; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Contract.Request.Channel; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Logging; -using UniSpy.Server.QueryReport.Aggregate.Redis.Channel; - -namespace UniSpy.Server.Chat.Aggregate -{ - public partial class Channel - { - /// - /// | key -> Nickname | value -> ChannelUser| - /// - [JsonProperty] - public ConcurrentDictionary BanList { get; private set; } = new ConcurrentDictionary(); - /// - /// | key -> Nickname | value -> ChannelUser| - /// - [JsonProperty] - public ConcurrentDictionary Users { get; private set; } = new ConcurrentDictionary(); - [JsonProperty] - public string _creatorNickName { get; private set; } - [JsonIgnore] - public ChannelUser Creator - { - get - { - if (Users.Values.Where(u => u.Info.NickName == _creatorNickName).Count() == 1) - { - return Users[_creatorNickName]; - } - else - { - return null; - } - } - } - private void BanUser(ModeRequest request) - { - var result = Users.Values.Where(u => u.Info.NickName == request.NickName); - if (result.Count() != 1) - { - return; - } - ChannelUser user = result.First(); - - if (BanList.Values.Where(u => u.Info.NickName == request.NickName).Count() == 1) - { - return; - } - - BanList.TryAdd(user.Info.NickName, user); - } - private void UnBanUser(ModeRequest request) - { - var result = BanList.Where(u => u.Value.Info.NickName == request.NickName); - if (result.Count() == 1) - { - var keyValue = result.First(); - BanList.TryRemove(keyValue); - return; - } - if (result.Count() > 1) - { - LogWriter.LogError($"Multiple user with same nick name in channel {Name}"); - } - } - - private void AddChannelOperator(ModeRequest request) - { - //check whether this user is in this channel - var result = Users.Where(u => u.Value.Info.UserName == request.UserName); - if (result.Count() != 1) - { - return; - } - var kv = result.First(); - - //if this user is already in operator we do not add it - if (kv.Value.IsChannelOperator) - { - return; - } - kv.Value.IsChannelOperator = true; - } - - private void RemoveChannelOperator(ModeRequest request) - { - var result = Users.Where(u => u.Value.Info.UserName == request.UserName); - if (result.Count() != 1) - { - return; - } - var keyValue = result.First(); - - if (keyValue.Value.IsChannelCreator) - { - keyValue.Value.IsChannelCreator = false; - } - } - - private void EnableUserVoicePermission(ModeRequest request) - { - var result = Users.Where(u => u.Value.Info.UserName == request.UserName); - if (result.Count() != 1) - { - return; - } - - var kv = result.First(); - - if (kv.Value.IsVoiceable) - { - kv.Value.IsVoiceable = true; - } - - } - private void DisableUserVoicePermission(ModeRequest request) - { - var result = Users.Where(u => u.Value.Info.UserName == request.UserName); - if (result.Count() != 1) - { - return; - } - - var kv = result.First(); - if (kv.Value.IsVoiceable) - { - kv.Value.IsVoiceable = false; - } - } - public ChannelUser GetUser(string nickName) => Users.ContainsKey(nickName) == true ? Users[nickName] : null; - public ChannelUser GetUser(IChatClient client) => Users.Values.FirstOrDefault(u => u.Connection.RemoteIPEndPoint == client.Connection.RemoteIPEndPoint); - public ChannelUser AddUser(IChatClient client, string password = null, bool isChannelCreator = false, bool isChannelOperator = false) - { - Validation(client, password); - var user = new ChannelUser(client, this); - switch (RoomType) - { - case PeerRoomType.Normal: - case PeerRoomType.Staging: - // user created room - user.IsChannelCreator = isChannelCreator; - user.IsChannelOperator = isChannelOperator; - break; - } - AddBindOnUserAndChannel(user); - return user; - } - - public void RemoveUser(ChannelUser user) - { - user.Info.PreviousJoinedChannel = Name; - RemoveBindOnUserAndChannel(user); - } - - public bool IsUserExisted(ChannelUser user) => IsUserExisted(user.Client); - public bool IsUserExisted(IChatClient client) => Users.ContainsKey(client.Info.NickName); - public bool IsUserBanned(ChannelUser user) => IsUserBanned(user.Client); - private bool IsUserBanned(IChatClient client) - { - if (!BanList.ContainsKey(client.Info.NickName)) - { - return false; - } - if (BanList[client.Info.NickName].Connection.RemoteIPEndPoint != client.Connection.RemoteIPEndPoint) - { - return false; - } - return true; - } - public string GetAllUsersNickString() - { - string nicks = ""; - foreach (var user in Users.Values) - { - if (user.IsChannelCreator) - { - nicks += $"@{user.Client.Info.NickName}"; - } - else - { - nicks += user.Client.Info.NickName; - } - - if (!user.Equals(Users.Values.Last())) - { - nicks += " "; - } - } - return nicks; - } - public static void AddBindOnUserAndChannel(ChannelUser joiner) - { - joiner.Channel.Users.TryAdd(joiner.Info.NickName, joiner); - joiner.Info.JoinedChannels.TryAdd(joiner.Channel.Name, joiner.Channel); - } - public static void RemoveBindOnUserAndChannel(ChannelUser leaver) - { - leaver.Channel.Users.TryRemove(leaver.Info.NickName, out _); - leaver.Info.JoinedChannels.TryRemove(leaver.Channel.Name, out _); - } - /// - /// Send message to all users in this channel - /// except the sender - /// - /// - public void MultiCast(IClient sender, IResponse message, bool isSkipSender = false) - { - foreach (var user in Users.Values) - { - if (user.IsRemoteUser - || (isSkipSender - && user.RemoteIPEndPoint.Equals(sender.Connection.RemoteIPEndPoint))) - { - continue; - } - user.Client.Send(message); - } - } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Aggregate/ChannelProperty/ChannelValidation.cs b/src/Servers/Chat/src/Aggregate/ChannelProperty/ChannelValidation.cs deleted file mode 100644 index 5b8cbdbd2..000000000 --- a/src/Servers/Chat/src/Aggregate/ChannelProperty/ChannelValidation.cs +++ /dev/null @@ -1,62 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Error.IRC.Channel; - -namespace UniSpy.Server.Chat.Aggregate -{ - public partial class Channel - { - public void VerifyPassword(string pass) - { - if (Password != pass) - { - throw new Chat.Exception("Password is not correct"); - } - } - private void Validation(IChatClient client, string password) - { - if (Mode.IsInviteOnly) - { - //invited only - throw new IRCChannelException("This is an invited only channel.", IRCErrorCode.InviteOnlyChan, Name); - } - if (IsUserBanned(client)) - { - throw new BannedFromChanException($"You are banned from this channel:{Name}.", Name); - } - if (IsUserExisted(client)) - { - throw new Chat.Exception($"{client.Info.NickName} is already in channel {Name}"); - } - if (client.Info.IsJoinedChannel(Name)) - { - // we do not send anything to this user and users in this channel - throw new Chat.Exception($"User: {client.Info.NickName} is already joined the channel: {Name}"); - } - if (Password is not null) - { - if (password is null) - { - throw new Chat.Exception("You must input password to join this channel."); - } - if (Password != password) - { - throw new Chat.Exception("Password is not correct"); - } - } - - if (Mode.IsInviteOnly) - { - if (!Mode.InviteNickNames.Contains(client.Info.NickName)) - { - throw new InviteOnlyChanException("You must invited to this channel", Name); - } - else - { - // user is already join, we remove him from list - Mode.InviteNickNames.Remove(client.Info.NickName); - } - } - } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Aggregate/ChannelUser.cs b/src/Servers/Chat/src/Aggregate/ChannelUser.cs deleted file mode 100755 index 79be39ad2..000000000 --- a/src/Servers/Chat/src/Aggregate/ChannelUser.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using System.Net; -using System.Text; -using Newtonsoft.Json; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Application; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Misc; - -namespace UniSpy.Server.Chat.Aggregate -{ - public sealed class ChannelUser - { - [JsonProperty] - public Guid? ServerId { get; private set; } - /// - /// Indicate whether this client is shared from redis channel - /// - [JsonProperty] - public bool IsRemoteUser => Info.IsRemoteClient; - public bool IsVoiceable { get; set; } = true; - public bool IsChannelCreator { get; set; } - public bool IsChannelOperator { get; set; } - /// - /// The remote ip end point of this user - /// - [JsonProperty] - [JsonConverter(typeof(IPEndPointConverter))] - public IPEndPoint RemoteIPEndPoint { get; private set; } - /// - /// The client reference - /// - [JsonIgnore] - public IChatClient Client { get; private set; } - [JsonIgnore] - public ClientInfo Info => Client.Info; - [JsonIgnore] - public IConnection Connection => Client.Connection; - /// - /// The user key values storage - /// - public KeyValueManager KeyValues { get; private set; } = new KeyValueManager(); - /// - /// The channel where user current in. - /// - [JsonIgnore] - public Channel Channel { get; private set; } - [JsonIgnore] - public string Modes - { - get - { - var buffer = new StringBuilder(); - - if (IsChannelOperator) - { - buffer.Append("@"); - } - - if (IsVoiceable) - { - buffer.Append("+"); - } - - return buffer.ToString(); - } - } - public ChannelUser() { } - public ChannelUser(IChatClient client, Channel channel) - { - Client = client; - Channel = channel; - ServerId = client.Server.Id; - RemoteIPEndPoint = client.Connection.RemoteIPEndPoint; - } - } -} diff --git a/src/Servers/Chat/src/Aggregate/KeyValueManager.cs b/src/Servers/Chat/src/Aggregate/KeyValueManager.cs deleted file mode 100644 index daf71e313..000000000 --- a/src/Servers/Chat/src/Aggregate/KeyValueManager.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Collections.Concurrent; -using System.Collections.Generic; - - -namespace UniSpy.Server.Chat.Aggregate -{ - public class KeyValueManager - { - public ConcurrentDictionary Dict { get; private set; } = new ConcurrentDictionary(); - - public KeyValueManager() - { - } - - public void Update(Dictionary data) - { - // TODO check if all key is send through the request or - // TODO only updated key send through the request - foreach (var key in data.Keys) - { - //we update the key value - Dict[key] = data[key]; - } - } - public void Update(KeyValuePair data) - { - Dict[data.Key] = data.Value; - } - public static string BuildKeyValueString(Dictionary keyValues) - { - string flags = ""; - foreach (var kv in keyValues) - { - flags += $@"\{kv.Key}\{kv.Value}"; - } - return flags; - } - public string GetValueString(List keys) - { - string values = ""; - foreach (var key in keys) - { - if (Dict.ContainsKey(key)) - { - values += @"\" + Dict[key]; - } - else - { - values += @"\"; - // throw new Chat.Exception($"Can not find key: {key}"); - } - } - return values; - } - - public bool IsContainAllKey(List keys) - { - foreach (var key in keys) - { - if (!Dict.ContainsKey(key)) - { - return false; - } - } - return true; - } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Aggregate/Misc/BufferCache.cs b/src/Servers/Chat/src/Aggregate/Misc/BufferCache.cs deleted file mode 100644 index 90a82509b..000000000 --- a/src/Servers/Chat/src/Aggregate/Misc/BufferCache.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.Linq; - -namespace UniSpy.Server.Chat.Aggregate.Misc -{ - public class BufferCache : Core.Misc.BufferCacheBase - { - public BufferCache() - { - } - - public override bool ProcessBuffer(byte[] buffer, out byte[] completeBuffer) - { - if (buffer[buffer.Length - 1] == 0x0A) - { - // check last _incomplteBuffer if it has incomplete message, then combine them - if (InCompleteBuffer is not null) - { - completeBuffer = InCompleteBuffer.Concat(buffer).ToArray(); - InCompleteBuffer = null; - } - else - { - completeBuffer = buffer; - } - return true; - } - else - { - // message is not finished, we add it in _completeBuffer - if (InCompleteBuffer is null) - { - InCompleteBuffer = buffer; - } - else - { - InCompleteBuffer = InCompleteBuffer.Concat(buffer).ToArray(); - } - completeBuffer = null; - return false; - } - } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Aggregate/Misc/ChatConstants.cs b/src/Servers/Chat/src/Aggregate/Misc/ChatConstants.cs deleted file mode 100755 index 760e2f41e..000000000 --- a/src/Servers/Chat/src/Aggregate/Misc/ChatConstants.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace UniSpy.Server.Chat.Aggregate.Misc -{ - public sealed class ChatConstants - { - //we hard coded random key here for simplisity - } -} diff --git a/src/Servers/Chat/src/Aggregate/Misc/ChatCrypt.cs b/src/Servers/Chat/src/Aggregate/Misc/ChatCrypt.cs deleted file mode 100755 index e2b5a258b..000000000 --- a/src/Servers/Chat/src/Aggregate/Misc/ChatCrypt.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Encryption; - -namespace UniSpy.Server.Chat.Aggregate.Misc -{ - /// - /// This class is used to encrypt and decrypt the data for Chat. - /// - /// Note: this is a C-sharp version of the peerchat algorithm created by aluigi. - /// Original C implementation: http://aluigi.altervista.org/papers/gs_peerchat.h - /// - public sealed class ChatCrypt : ICryptography - { - public const string DigitsHex = "0123456789abcdef"; - public const string DigitsCrypt = "aFl4uOD9sfWq1vGp"; - public const string NewDigitsCrypt = "qJ1h4N9cP3lzD0Ka"; - public const uint IPXorMask = 0xc3801dc7; - public const string ClientKey = "0000000000000000"; - public const string ServerKey = "0000000000000000"; - public static byte[] Handle(PeerChatCTX ctx, byte[] data) - { - byte num1 = ctx.Buffer1; - byte num2 = ctx.Buffer2; - byte t; - int datapos = 0; - List buffer = new List(); - long size = data.Length; - - while (size-- > 0) - { - num1 = (byte)((num1 + 1) % 256); - num2 = (byte)((ctx.SBox[num1] + num2) % 256); - t = ctx.SBox[num1]; - ctx.SBox[num1] = ctx.SBox[num2]; - ctx.SBox[num2] = t; - t = (byte)((ctx.SBox[num2] + ctx.SBox[num1]) % 256); - byte temp = (byte)(data[datapos++] ^ ctx.SBox[t]); - buffer.Add(temp); - } - - ctx.Buffer1 = num1; - ctx.Buffer2 = num2; - return buffer.ToArray(); - } - - /// - /// Prepare the key - /// - /// - /// - /// - public static void Init(PeerChatCTX ctx, string challengeKey, string secretKey) - { - byte[] challengeBytes = UniSpyEncoding.GetBytes(challengeKey); - byte[] secretKeyBytes = UniSpyEncoding.GetBytes(secretKey); - - ctx.Buffer1 = 0; - ctx.Buffer2 = 0; - - int secretKeyIndex = 0; - for (int i = 0; i < challengeBytes.Length; i++, secretKeyIndex++) - { - if (secretKeyIndex >= secretKeyBytes.Length) - { - secretKeyIndex = 0; - } - - challengeBytes[i] ^= secretKeyBytes[secretKeyIndex]; - } - - byte index1 = 255; - - for (int i = 0; i < 256; i++, index1--) - { - ctx.SBox[i] = index1; - } - - index1 = 0; - - for (int i = 0, index2 = 0; i < ctx.SBox.Length; i++, index1++) - { - if (index1 >= challengeBytes.Length) - { - index1 = 0; - } - - index2 = (byte)((challengeBytes[index1] + ctx.SBox[i] + index2) % 256); - byte t = ctx.SBox[i]; - ctx.SBox[i] = ctx.SBox[index2]; - ctx.SBox[index2] = t; - } - } - - public static bool EncodeIP() - { - return false; - } - public PeerChatCTX ClientCtx { get; private set; } - public PeerChatCTX ServerCtx { get; private set; } - public ChatCrypt(string gameSecretKey) - { - ClientCtx = new PeerChatCTX(); - ServerCtx = new PeerChatCTX(); - Init(ClientCtx, ClientKey, gameSecretKey); - Init(ServerCtx, ServerKey, gameSecretKey); - } - public byte[] Encrypt(byte[] data) - { - return Handle(ServerCtx, data); - } - - public byte[] Decrypt(byte[] data) - { - return Handle(ClientCtx, data); - } - } -} diff --git a/src/Servers/Chat/src/Aggregate/Misc/IRCErrorCode.cs b/src/Servers/Chat/src/Aggregate/Misc/IRCErrorCode.cs deleted file mode 100755 index 2e8bad287..000000000 --- a/src/Servers/Chat/src/Aggregate/Misc/IRCErrorCode.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace UniSpy.Server.Chat.Aggregate.Misc -{ - public sealed class IRCErrorCode - { - //GameSpy standard irc error - public const string NoSuchNick = "401"; - public const string NoSuchChannel = "403"; - public const string TooManyChannels = "405"; - public const string ErrOneUSNickName = "432"; - public const string NickNameInUse = "433"; - public const string MoreParameters = "461"; - public const string ChannelIsFull = "471"; - public const string InviteOnlyChan = "473"; - public const string BannedFromChan = "474"; - public const string BadChannelKey = "475"; - public const string BadChanMask = "476"; - public const string LoginFailed = "708"; - public const string NoUniqueNick = "709"; - public const string UniqueNIickExpired = "710"; - public const string RegisterNickFailed = "711"; - } -} diff --git a/src/Servers/Chat/src/Aggregate/Misc/IRCReplyBuilder.cs b/src/Servers/Chat/src/Aggregate/Misc/IRCReplyBuilder.cs deleted file mode 100755 index 653250c46..000000000 --- a/src/Servers/Chat/src/Aggregate/Misc/IRCReplyBuilder.cs +++ /dev/null @@ -1,133 +0,0 @@ -// using System.Collections.Generic; -// using UniSpy.Server.Chat.Abstraction.BaseClass; - -// namespace UniSpy.Server.Chat.Aggregate.Misc -// { -// public sealed class IRCReplyBuilder -// { -// #region advance irc reply builder - -// public static string BuildChannelError(string ircError, string channelName, string message) -// { -// return Build(ircError, $"* {channelName}", message); -// } - -// public static string BuildBadChanMaskError(string channelName) -// { -// return BuildChannelError(IRCErrorCode.BadChanMask, channelName, "Bad channel mask."); -// } - -// public static string BuildBadChannelKeyError(string channelName) -// { -// return BuildChannelError(IRCErrorCode.BannedFromChan, channelName, "Wrong channel password."); -// } - -// public static string BuildBannedFromChannelError(string channelName) -// { -// return BuildChannelError(IRCErrorCode.BadChannelKey, channelName, "Banned from channel."); -// } - -// public static string BuildChannelIsFullError(string channelName) -// { -// return BuildChannelError(IRCErrorCode.ChannelIsFull, channelName, "Channel is full."); -// } - -// public static string BuildInvitedOnlyChannelError(string channelName) -// { -// return BuildChannelError(IRCErrorCode.InviteOnlyChan, channelName, "Invite only channel."); -// } -// public static string BuildNoSuchChannelError(string channelName) -// { -// return BuildChannelError(IRCErrorCode.NoSuchChannel, channelName, "There is no such channel."); -// } -// public static string BuildToManyChannelError(string channelName) -// { -// return BuildChannelError(IRCErrorCode.TooManyChannels, channelName, "You have joined to many channels."); -// } - -// public static string BuildNickNameInUseError(string oldNick, string newNick) -// { -// return Build(IRCErrorCode.NickNameInUse, $"{oldNick} {newNick} 0"); -// } - -// public static string BuildLoginFailedError() -// { -// return Build(IRCErrorCode.LoginFailed); -// } - -// public static string BuildNoUniqueNickError() -// { -// return Build(IRCErrorCode.NoUniqueNick); -// } - -// public static string BuildUniquenickExpireError() -// { -// return Build(IRCErrorCode.UniqueNIickExpired); -// } - -// public static string BuildRegisterNickFailedError(List nickNames) -// { -// string suggestNicks = ""; - -// foreach (var nick in nickNames) -// { -// suggestNicks += @"\" + nick; -// } -// return Build(IRCErrorCode.RegisterNickFailed, $"* numberOfSuggestNick {suggestNicks} 0"); -// } - -// public static string BuildErrOneUSNickNameError(string userPrefix) -// { -// return Build(userPrefix, IRCErrorCode.ErrOneUSNickName, null, null); -// } - -// public static string BuildNoSuchNickError() -// { -// return Build(IRCErrorCode.NoSuchNick); -// } -// #endregion - -// #region Basic IRC reply builder -// public static string Build(string command) -// { -// return Build(command, null); -// } - -// public static string Build(string cmd, string cmdParams) -// { -// return Build(cmd, cmdParams, null); -// } - -// public static string Build(string cmd, string cmdParams, string tailing) -// { -// return Build(ResponseBase.ServerDomain, cmd, cmdParams, tailing); -// } -// public static string Build(IRCErrorCode cmd, string cmdParams, string tailing) -// { -// return Build(cmd.ToString(), cmdParams, tailing); -// } -// public static string Build(string prefix, string cmd, string cmdParams, string tailing) -// { -// string buffer = ""; - -// if (prefix != "" || prefix is not null) -// { -// buffer = $":{prefix} "; -// } - -// buffer += $"{cmd} {cmdParams}"; - -// if (tailing == "" || tailing is null) -// { -// buffer += "\r\n"; -// } -// else -// { -// buffer += $" :{tailing}\r\n"; -// } - -// return buffer; -// } -// #endregion -// } -// } diff --git a/src/Servers/Chat/src/Aggregate/Misc/PeerChatCTX.cs b/src/Servers/Chat/src/Aggregate/Misc/PeerChatCTX.cs deleted file mode 100755 index 99b439ace..000000000 --- a/src/Servers/Chat/src/Aggregate/Misc/PeerChatCTX.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace UniSpy.Server.Chat.Aggregate.Misc -{ - public sealed class PeerChatCTX - { - public byte Buffer1; - public byte Buffer2; - public byte[] SBox = new byte[256]; - } -} diff --git a/src/Servers/Chat/src/Aggregate/Misc/ResponseName.cs b/src/Servers/Chat/src/Aggregate/Misc/ResponseName.cs deleted file mode 100755 index e3ffd89ef..000000000 --- a/src/Servers/Chat/src/Aggregate/Misc/ResponseName.cs +++ /dev/null @@ -1,87 +0,0 @@ -namespace UniSpy.Server.Chat.Aggregate.Misc -{ - public sealed class ResponseName - { - public const string Welcome = "001"; - public const string UserIP = "302"; - public const string WhoIsUser = "311"; - public const string EndOfWho = "315"; - public const string EndOfWhoIs = "318"; - public const string WhoIsChannels = "319"; - public const string ListStart = "321"; - public const string List = "322"; - public const string ListEnd = "323"; - public const string ChannelModels = "324"; - public const string NoTopic = "331"; - public const string Topic = "332"; - public const string WhoReply = "352"; - public const string NameReply = "353"; - public const string EndOfNames = "366"; - public const string BanList = "367"; - public const string EndOfBanList = "368"; - public const string GetKey = "700"; - public const string EndGetKey = "701"; - public const string GetCKey = "702"; - public const string EndGetCKey = "703"; - public const string GetChanKey = "704"; - public const string SecureKey = "705"; - public const string CDKey = "706"; - public const string Login = "707"; - public const string GetUDPRelay = "712"; - - /// - /// Send a private message - /// - public const string PrivateMsg = "PRIVMSG"; - /// - /// Send a notice message - /// - public const string Notice = "NOTICE"; - /// - /// Send an under the table message - /// - public const string UnderTheTableMsg = "UTM"; - /// - /// Send an above the table message - /// - public const string AboveTheTableMsg = "ATM"; - public const string Ping = "PING"; - public const string Pong = "PONG"; - /// - /// Search with nickname - /// - public const string Nick = "NICK"; - /// - /// Join a channel - /// - public const string Join = "JOIN"; - /// - /// Leave a channel - /// - public const string Part = "PART"; - /// - /// Kick a user from a channel - /// - public const string Kick = "KICK"; - /// - /// Quit irc chat server - /// - public const string Quit = "QUIT"; - - public const string Kill = "KILL"; - /// - /// Change channel topic - /// - public const string ChannelTopic = "TOPIC"; - /// - /// Change channel mode - /// - public const string Mode = "MODE"; - - public const string Error = "ERROR"; - /// - /// Invite a user to a channel - /// - public const string Invite = "INVITE"; - } -} diff --git a/src/Servers/Chat/src/Aggregate/Redis/Contract/ChannelMessage.cs b/src/Servers/Chat/src/Aggregate/Redis/Contract/ChannelMessage.cs deleted file mode 100644 index c3951868e..000000000 --- a/src/Servers/Chat/src/Aggregate/Redis/Contract/ChannelMessage.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Newtonsoft.Json; -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Core.Encryption; - -namespace UniSpy.Server.Chat.Aggregate.Redis.Contract -{ - public class RemoteMessage - { - [JsonProperty] - public string Type { get; private set; } - [JsonProperty] - public byte[] RawRequest { get; private set; } - [JsonProperty] - public RemoteClient Client { get; private set; } - /// - /// Constructor for json deserialization - /// - public RemoteMessage(){} - public RemoteMessage(RequestBase request, RemoteClient client) - { - RawRequest = UniSpyEncoding.GetBytes(request.RawRequest); - Type = request.CommandName; - Client = client; - } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Aggregate/Redis/Contract/DisconnectRequest.cs b/src/Servers/Chat/src/Aggregate/Redis/Contract/DisconnectRequest.cs deleted file mode 100644 index f0efd7bd6..000000000 --- a/src/Servers/Chat/src/Aggregate/Redis/Contract/DisconnectRequest.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - -namespace UniSpy.Server.Chat.Aggregate.Redis.Contract -{ - public class DisconnectRequest : RequestBase - { - public DisconnectRequest() : base("DISCONNECT") - { - Parse(); - } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Aggregate/Redis/RedisChannel.cs b/src/Servers/Chat/src/Aggregate/Redis/RedisChannel.cs deleted file mode 100644 index 948822e49..000000000 --- a/src/Servers/Chat/src/Aggregate/Redis/RedisChannel.cs +++ /dev/null @@ -1,87 +0,0 @@ -using UniSpy.Server.Chat.Aggregate.Redis.Contract; -using UniSpy.Server.Chat.Handler; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Extension.Redis; -using System.Threading.Tasks; -using UniSpy.Server.Chat.Application; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Core.Encryption; - -namespace UniSpy.Server.Chat.Aggregate.Redis -{ - /// - /// The general chat message will process here - /// - public class GeneralMessageChannel : RedisChannelBase - { - public GeneralMessageChannel() : base(RedisChannelName.ChatChannelPrefix) - { - } - public override void ReceivedMessage(RemoteMessage message) - { - if (message.Client.Server.Id == ServerLauncher.Server.Id) - { - return; - } - if (message.Type == "DISCONNECT") - { - ClientManager.RemoveClient(message.Client); - return; - } - IChatClient client = (IChatClient)ClientManager.GetClient(message.Client); - if (client is null) - { - ClientManager.AddClient(message.Client); - client = message.Client; - } - else - { - // we update the remote client info - ((RemoteClient)client).Info = message.Client.Info; - } - - var switcher = new CmdSwitcher(client, UniSpyEncoding.GetString(message.RawRequest)); - if (System.Diagnostics.Debugger.IsAttached) - { - switcher.Handle(); - } - else - { - Task.Run(() => switcher.Handle()); - } - } - } - /// - /// When a local channel is created the user message will send to redis channel - /// redis channel is like a broadcast platform which will broadcast the message to all the user - /// when user is connected to unispy chat server - /// - public class ChatMessageChannel : RedisChannelBase - { - public ChatMessageChannel(string chatChannelName) : base($"{RedisChannelName.ChatChannelPrefix}:{chatChannelName}") { } - - public override void ReceivedMessage(RemoteMessage message) - { - // base.ReceivedMessage(message); - if (message.Client.Server.Id == ServerLauncher.Server.Id) - { - return; - } - IChatClient client = (IChatClient)ClientManager.GetClient(message.Client); - if (client is null) - { - throw new Chat.Exception($"There are no remote client found in RemoteClients pool, the client must be login on the remote server."); - } - - var switcher = new CmdSwitcher(client, UniSpyEncoding.GetString(message.RawRequest)); - if (System.Diagnostics.Debugger.IsAttached) - { - switcher.Handle(); - } - else - { - Task.Run(() => switcher.Handle()); - } - } - } -} diff --git a/src/Servers/Chat/src/Aggregate/RemoteObjects.cs b/src/Servers/Chat/src/Aggregate/RemoteObjects.cs deleted file mode 100644 index 10793c713..000000000 --- a/src/Servers/Chat/src/Aggregate/RemoteObjects.cs +++ /dev/null @@ -1,120 +0,0 @@ -using System; -using System.Net; -using Newtonsoft.Json; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Application; -using UniSpy.Server.Chat.Handler; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Encryption; -using UniSpy.Server.Core.Events; -using UniSpy.Server.Core.Logging; -using UniSpy.Server.Core.Misc; - -namespace UniSpy.Server.Chat.Aggregate -{ - public class ConcreteTypeConverter : JsonConverter - { - public override bool CanConvert(Type objectType) - { - //assume we can convert to anything for now - return true; - } - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - //explicitly specify the concrete type we want to create - return serializer.Deserialize(reader); - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - //use the default serialization - it works fine - serializer.Serialize(writer, value); - } - } - public class RemoteServer : IServer - { - public Guid Id { get; private set; } - public string Name { get; private set; } - [JsonConverter(typeof(IPEndPointConverter))] - public IPEndPoint ListeningIPEndPoint { get; private set; } - [JsonConverter(typeof(IPEndPointConverter))] - public IPEndPoint PublicIPEndPoint { get; private set; } - public RemoteServer() - { - } - public RemoteServer(IServer server) - { - Id = server.Id; - Name = server.Name; - ListeningIPEndPoint = server.ListeningIPEndPoint; - PublicIPEndPoint = server.PublicIPEndPoint; - } - public void Start() { } - } - public class RemoteClient : IChatClient, Core.Abstraction.Interface.ITestClient - { - public bool IsLogRaw { get; set; } - [JsonConverter(typeof(ConcreteTypeConverter))] - public IConnection Connection { get; set; } - public ICryptography Crypto => null; - [JsonConverter(typeof(ConcreteTypeConverter))] - public ClientInfoBase Info { get; set; } - ClientInfo IChatClient.Info => (ClientInfo)Info; - [JsonConverter(typeof(ConcreteTypeConverter))] - public IServer Server { get; set; } - - // public RemoteClient() { } - public RemoteClient(RemoteTcpConnection conn, ClientInfo info, IServer server) - { - Connection = conn; - // we need to copy the client info because it is a reference type - Info = info.DeepCopy(); - Server = server; - (Info as ClientInfo).IsRemoteClient = true; - } - public void Send(IResponse response) => this.LogDebug("Ignore remote client Send() operation"); - public RemoteClient GetRemoteClient() => this; - - public void TestReceived(byte[] buffer) - { - this.LogNetworkReceiving(buffer); - var switcher = new CmdSwitcher(this, UniSpyEncoding.GetString(buffer)); - switcher.Handle(); - } - } - public class RemoteTcpConnectionManager : IConnectionManager - { -#pragma warning disable CS0067 - public event OnConnectingEventHandler OnInitialization; - public void Start() => throw new Chat.Exception("Remote tcp connection do not have this method."); - public RemoteTcpConnectionManager() { } - } - - public class RemoteTcpConnection : ITcpConnection - { - - [JsonConverter(typeof(ConcreteTypeConverter))] - public IConnectionManager Manager { get; set; } - [JsonConverter(typeof(IPEndPointConverter))] - public IPEndPoint RemoteIPEndPoint { get; set; } - public NetworkConnectionType ConnectionType { get; set; } -#pragma warning disable CS0067 - public event OnConnectedEventHandler OnConnect; -#pragma warning disable CS0067 - public event OnDisconnectedEventHandler OnDisconnect; -#pragma warning disable CS0067 - public event OnReceivedEventHandler OnReceive; - public RemoteTcpConnection() { } - public RemoteTcpConnection(ITcpConnection conn, IConnectionManager manager) - { - Manager = manager; - RemoteIPEndPoint = conn.RemoteIPEndPoint; - ConnectionType = conn.ConnectionType; - } - public void Disconnect() => LogWriter.LogDebug("Remote tcp connection do not have this method."); - public void Send(string response) => LogWriter.LogDebug("Remote tcp connection do not have this method."); - public void Send(byte[] response) => LogWriter.LogDebug("Remote tcp connection do not have this method."); - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Application/Client.cs b/src/Servers/Chat/src/Application/Client.cs deleted file mode 100644 index c08ed18a8..000000000 --- a/src/Servers/Chat/src/Application/Client.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System.Threading.Tasks; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Aggregate; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Aggregate.Redis.Contract; -using UniSpy.Server.Chat.Contract.Request.General; -using UniSpy.Server.Chat.Handler; -using UniSpy.Server.Chat.Handler.CmdHandler.General; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Encryption; -using UniSpy.Server.Core.Logging; - -namespace UniSpy.Server.Chat.Application -{ - public class Client : ClientBase, IChatClient - { - public new ClientInfo Info { get => (ClientInfo)base.Info; private set => base.Info = value; } - public new ITcpConnection Connection => (ITcpConnection)base.Connection; - private BufferCache _bufferCache = new BufferCache(); - public Client(IConnection connection, IServer server) : base(connection, server) - { - Info = new ClientInfo(); - } - - protected override void OnReceived(object buffer) - { - var message = DecryptMessage((byte[])buffer); - if (_bufferCache.ProcessBuffer(message, out var completeBuffer)) - { - this.LogNetworkReceiving(completeBuffer); - var switcher = CreateSwitcher(completeBuffer); - if (System.Diagnostics.Debugger.IsAttached) - { - switcher.Handle(); - } - else - { - Task.Run(() => switcher.Handle()); - } - } - } - protected override void OnDisconnected() - { - if (Info.IsLoggedIn) - { - var req = new QuitRequest() - { - Reason = $"{Info.NickName} Disconnected." - }; - new QuitHandler(this, req).Handle(); - Info.IsLoggedIn = false; - } - Task.Run(() => PublishDisconnectMessage()); - base.OnDisconnected(); - } - private void PublishDisconnectMessage() - { - var message = new RemoteMessage(new DisconnectRequest(), GetRemoteClient()); - Chat.Application.Server.GeneralChannel.PublishMessage(message); - } - protected override ISwitcher CreateSwitcher(object buffer) => new CmdSwitcher(this, UniSpyEncoding.GetString((byte[])buffer)); - public RemoteClient GetRemoteClient() - { - var manager = new RemoteTcpConnectionManager(); - var conn = new RemoteTcpConnection(Connection, manager); - var server = new RemoteServer(Server); - var client = new RemoteClient(conn, Info, server); - return client; - } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Application/ClientInfo.cs b/src/Servers/Chat/src/Application/ClientInfo.cs deleted file mode 100755 index 5b9d23a6c..000000000 --- a/src/Servers/Chat/src/Application/ClientInfo.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System.Collections.Concurrent; -using System.Collections.Generic; -using Newtonsoft.Json; -using UniSpy.Server.Chat.Aggregate; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.Chat.Application -{ - public sealed class ClientInfo : ClientInfoBase - { - /// - /// indicates which channel this user is in - /// (We do not send this information to our public channel) - /// - [JsonIgnore] - public ConcurrentDictionary JoinedChannels { get; private set; } = new ConcurrentDictionary(); - // secure connection - public string GameName { get; set; } - public string NickName { get; set; } - public string UserName { get; set; } - public string Name { get; set; } - public string ServerIP { get; set; } - public int NameSpaceID { get; set; } = 0; - public string UniqueNickName { get; set; } - public string GameSecretKey { get; set; } - public bool IsLoggedIn { get; set; } = false; - public bool IsUsingEncryption { get; set; } = false; - public bool IsQuietMode { get; set; } = false; - [JsonIgnore] - public string IRCPrefix => $"{NickName}!{UserName}@{Chat.Abstraction.BaseClass.ResponseBase.ServerDomain}"; - public bool IsRemoteClient { get; set; } - public string PreviousJoinedChannel { get; set; } = ""; - /// - /// Global user key values - /// - /// - public KeyValueManager KeyValues { get; private set; } = new KeyValueManager(); - /// - /// Store Handler here processing later. - /// Some game is using * as nickname, and nickname will send in SETCHANKEY request, so we need to store handlers and process it latter - /// - [JsonIgnore] - public List HandlerStack { get; private set; } = new List(); - public bool IsNickNameSet => NickName != "*"; - public ClientInfo() - { - } - - public bool IsJoinedChannel(string channelName) => JoinedChannels.ContainsKey(channelName); - - public Channel GetJoinedChannel(string channelName) - { - if (JoinedChannels.ContainsKey(channelName)) - { - return JoinedChannels[channelName]; - } - else - { - return null; - } - } - public ClientInfo DeepCopy() - { - var infoCopy = (ClientInfo)this.MemberwiseClone(); - return infoCopy; - } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Application/ClientManager.cs b/src/Servers/Chat/src/Application/ClientManager.cs deleted file mode 100644 index 6411b9442..000000000 --- a/src/Servers/Chat/src/Application/ClientManager.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Aggregate; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.Chat.Application -{ - public sealed class ClientManager : ClientManagerBase - { - public static readonly ConcurrentDictionary RemoteClientPool = new ConcurrentDictionary(); - private static string RemoteClientDictionaryKey(RemoteClient client) - { - return $"{client.Server.Id} {client.Connection.RemoteIPEndPoint}"; - } - public static new void AddClient(IClient client) - { - if (((IChatClient)client).Info.IsRemoteClient) - { - var key = RemoteClientDictionaryKey((RemoteClient)client); - RemoteClientPool.TryAdd(key, (RemoteClient)client); - } - else - { - ClientManagerBase.AddClient(client); - } - } - public static new IClient RemoveClient(IClient client) - { - if (((IChatClient)client).Info.IsRemoteClient) - { - var key = RemoteClientDictionaryKey((RemoteClient)client); - RemoteClientPool.TryRemove(key, out _); - return client; - } - else - { - return ClientManagerBase.RemoveClient(client); - } - } - public static IClient GetClient(IClient client) - { - if (((IChatClient)client).Info.IsRemoteClient) - { - var key = RemoteClientDictionaryKey((RemoteClient)client); - if (RemoteClientPool.TryGetValue(key, out var c)) - { - return c; - - } - else - { - return null; - } - } - else - { - return ClientManagerBase.GetClient(client.Connection.RemoteIPEndPoint); - } - } - /// - /// We need to make sure client is get by nickname, otherwise we throw exception - /// - /// - /// - public static IChatClient GetClientByNickName(string nickName) - { - IChatClient client; - client = (IChatClient)ClientPool.Values.Where(c => ((ClientInfo)(c.Info)).NickName == nickName).FirstOrDefault(); - if (client is null) - { - client = (IChatClient)RemoteClientPool.Values.Where(c => ((ClientInfo)(c.Info)).NickName == nickName).FirstOrDefault(); - } - if (client is null) - { - throw new Chat.Exception($"No client named {nickName} found."); - } - return client; - } - public static List GetAllClientInfo() - { - var infos = ClientPool.Values.Select(c => ((ClientInfo)(c.Info))).ToList(); - infos.AddRange(RemoteClientPool.Values.Select(c => ((ClientInfo)(c.Info))).ToList()); - return infos; - } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Application/Program.cs b/src/Servers/Chat/src/Application/Program.cs deleted file mode 100755 index 78112d0cd..000000000 --- a/src/Servers/Chat/src/Application/Program.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using UniSpy.Server.Core.Logging; - -namespace UniSpy.Server.Chat.Application -{ - public class Program - { - static void Main(string[] args) - { - try - { - new ServerLauncher().Start(); - Console.WriteLine("Press < Q > to exit. "); - while (Console.ReadKey().Key != ConsoleKey.Q) { } - } - catch (System.Exception e) - { - LogWriter.LogError(e); - } - } - } -} diff --git a/src/Servers/Chat/src/Application/Server.cs b/src/Servers/Chat/src/Application/Server.cs deleted file mode 100644 index 0279bacb8..000000000 --- a/src/Servers/Chat/src/Application/Server.cs +++ /dev/null @@ -1,30 +0,0 @@ -using UniSpy.Server.Chat.Aggregate.Redis; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Network.Tcp.Server; -using UniSpy.Server.Core.Abstraction.Interface; -using System.Net; - -namespace UniSpy.Server.Chat.Application -{ - public sealed class Server : ServerBase - { - public static GeneralMessageChannel GeneralChannel = new GeneralMessageChannel(); - static Server() - { - _name = "Chat"; - } - public Server(){ } - - public Server(IConnectionManager manager) : base(manager){} - - public override void Start() - { - base.Start(); - GeneralChannel.Subscribe(); - } - - protected override IClient CreateClient(IConnection connection) => new Client(connection, this); - - protected override IConnectionManager CreateConnectionManager(IPEndPoint endPoint) => new TcpConnectionManager(endPoint); - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Application/ServerLauncher.cs b/src/Servers/Chat/src/Application/ServerLauncher.cs deleted file mode 100644 index 90e96853b..000000000 --- a/src/Servers/Chat/src/Application/ServerLauncher.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Core.Abstraction.BaseClass.Factory; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.Chat.Application -{ - public sealed class ServerLauncher : ServerLauncherBase - { - public static IServer Server => ServerInstances[0]; - protected override List LaunchNetworkService() => new List { new Server() }; - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Application/StorageOperation.cs b/src/Servers/Chat/src/Application/StorageOperation.cs deleted file mode 100644 index 846104592..000000000 --- a/src/Servers/Chat/src/Application/StorageOperation.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System.Linq; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Core.Database.DatabaseModel; -using UniSpy.Server.QueryReport.Aggregate.Redis.Channel; - -namespace UniSpy.Server.Chat.Application -{ - public sealed class StorageOperation : IStorageOperation - { - public static IStorageOperation Persistance = new StorageOperation(); - private static RedisClient _redisClient = new RedisClient(); - public (int userId, int profileId, bool emailVerified, bool banned) NickAndEmailLogin(string nickName, string email, string passwordHash) - { - using (var db = new UniSpyContext()) - { - var result = from u in db.Users - join p in db.Profiles on u.UserId equals p.Userid - where u.Email == email - && p.Nick == nickName - && u.Password == passwordHash - select new - { - userId = u.UserId, - profileId = p.ProfileId, - emailVerified = u.Emailverified, - banned = u.Banned - }; - - if (result.Count() != 1) - { - throw new Chat.Exception($"Can not find user with nickname:{nickName} in database."); - } - return (userId: result.First().userId, - profileId: result.First().profileId, - emailVerified: (bool)result.First().emailVerified, - banned: result.First().banned); - } - } - public (int userId, int profileId, bool emailVerified, bool banned) UniqueNickLogin(string uniqueNick, int namespaceId) - { - using (var db = new UniSpyContext()) - { - var result = from n in db.Subprofiles - join p in db.Profiles on n.ProfileId equals p.ProfileId - join u in db.Users on p.Userid equals u.UserId - where n.Uniquenick == uniqueNick - && n.NamespaceId == namespaceId - select new - { - userId = u.UserId, - profileId = p.ProfileId, - uniquenick = n.Uniquenick, - emailVerified = u.Emailverified, - banned = u.Banned - }; - if (result.Count() != 1) - { - throw new Chat.Exception($"Can not find user with uniquenick:{uniqueNick} in database."); - } - // _result.ProfileId = result.First().profileid; - // _result.UserID = result.First().userid; - // Select( - return (userId: result.First().userId, - profileId: result.First().profileId, - emailVerified: (bool)result.First().emailVerified, - banned: result.First().banned); - } - } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Contract/Request/Channel/GetCKeyRequest.cs b/src/Servers/Chat/src/Contract/Request/Channel/GetCKeyRequest.cs deleted file mode 100755 index fcb9c2d5b..000000000 --- a/src/Servers/Chat/src/Contract/Request/Channel/GetCKeyRequest.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.Channel -{ - public enum GetKeyReqeustType - { - GetChannelAllUserKeyValue, - GetChannelSpecificUserKeyValue - } - - - public sealed class GetCKeyRequest : ChannelRequestBase - { - public GetKeyReqeustType RequestType { get; private set; } - public string NickName { get; private set; } - public string Cookie { get; private set; } - public List Keys { get; private set; } - public GetCKeyRequest(string rawRequest) : base(rawRequest) - { - Keys = new List(); - } - - public override void Parse() - { - base.Parse(); - - if (_cmdParams.Count != 4) - { - throw new Chat.Exception("The number of IRC parameters are incorrect."); - } - - if (_longParam is null) - { - throw new Chat.Exception("The IRC long parameter is incorrect."); - } - - NickName = _cmdParams[1]; - - if (NickName == "*") - { - RequestType = GetKeyReqeustType.GetChannelAllUserKeyValue; - } - else - { - RequestType = GetKeyReqeustType.GetChannelSpecificUserKeyValue; - } - Cookie = _cmdParams[2]; - - if (!_longParam.Contains("\0") && !_longParam.Contains("\\")) - { - throw new Chat.Exception("The key provide is incorrect."); - } - - Keys = _longParam.TrimStart('\\').TrimEnd('\0').Split("\\").ToList(); - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/Channel/GetChannelKeyRequest.cs b/src/Servers/Chat/src/Contract/Request/Channel/GetChannelKeyRequest.cs deleted file mode 100755 index 18106d8ac..000000000 --- a/src/Servers/Chat/src/Contract/Request/Channel/GetChannelKeyRequest.cs +++ /dev/null @@ -1,33 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using System.Collections.Generic; -using System.Linq; - -namespace UniSpy.Server.Chat.Contract.Request.Channel -{ - - public sealed class GetChannelKeyRequest : ChannelRequestBase - { - public GetChannelKeyRequest(string rawRequest) : base(rawRequest){ } - public string Cookie { get; private set; } - public List Keys { get; private set; } - - public override void Parse() - { - base.Parse(); - - if (_cmdParams.Count != 3) - { - throw new Chat.Exception("The cmdParams number is invalid."); - } - - if (_longParam is null || _longParam.Last() != '\0') - { - throw new Chat.Exception("The longParam number is invalid."); - } - - Cookie = _cmdParams[1]; - - Keys = _longParam.TrimStart('\\').TrimEnd('\0').Split("\\").ToList(); - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/Channel/JoinRequest.cs b/src/Servers/Chat/src/Contract/Request/Channel/JoinRequest.cs deleted file mode 100755 index bccc49aac..000000000 --- a/src/Servers/Chat/src/Contract/Request/Channel/JoinRequest.cs +++ /dev/null @@ -1,25 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - -namespace UniSpy.Server.Chat.Contract.Request.Channel -{ - - public sealed class JoinRequest : ChannelRequestBase - { - public string Password { get; private set; } - public JoinRequest(string rawRequest) : base(rawRequest) { } - public override void Parse() - { - base.Parse(); - - if (_cmdParams.Count > 2) - { - throw new Chat.Exception("number of IRC parameters are incorrect."); - } - - if (_cmdParams.Count == 2) - { - Password = _cmdParams[1]; - } - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/Channel/KickRequest.cs b/src/Servers/Chat/src/Contract/Request/Channel/KickRequest.cs deleted file mode 100755 index 29a36e957..000000000 --- a/src/Servers/Chat/src/Contract/Request/Channel/KickRequest.cs +++ /dev/null @@ -1,34 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.Channel -{ - - public sealed class KickRequest : ChannelRequestBase - { - public new string ChannelName{ get => base.ChannelName; set => base.ChannelName = value; } - public KickRequest() { } - public KickRequest(string rawRequest) : base(rawRequest){ } - public string KickeeNickName { get; set; } - public string Reason { get; set; } - - public override void Parse() - { - base.Parse(); - - if (_cmdParams.Count != 2) - { - throw new Chat.Exception("The number of IRC parameters are incorrect."); - } - - KickeeNickName = _cmdParams[1]; - - if (_longParam is null) - { - throw new Chat.Exception("The IRC long parameters is missing."); - } - - Reason = _longParam; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/Channel/ModeRequest.cs b/src/Servers/Chat/src/Contract/Request/Channel/ModeRequest.cs deleted file mode 100755 index 2572e353e..000000000 --- a/src/Servers/Chat/src/Contract/Request/Channel/ModeRequest.cs +++ /dev/null @@ -1,219 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.Channel -{ - //request: - //"MODE +/-q" - - //"MODE +/-k " - - // "MODE +l " - // "MODE -l" - - // "MODE +b" actually we do not care about this request - // "MODE +/-b " - - // "MODE +/-co " - // "MODE +/-cv " - - // "MODE " - // "MODE " - public enum ModeOperationType - { - EnableUserQuietFlag, - DisableUserQuietFlag, - AddChannelPassword, - RemoveChannelPassword, - AddChannelUserLimits, - RemoveChannelUserLimits, - AddBanOnUser, - GetBannedUsers, - RemoveBanOnUser, - AddChannelOperator, - RemoveChannelOperator, - EnableUserVoicePermission, - DisableUserVoicePermission, - SetInvitedOnly, - RemoveInvitedOnly, - SetPrivateChannelFlag, - RemovePrivateChannelFlag, - SetSecretChannelFlag, - RemoveSecretChannelFlag, - SetModeratedChannelFlag, - RemoveModeratedChannelFlag, - EnableExternalMessagesFlag, - DisableExternalMessagesFlag, - SetTopicChangeByOperatorFlag, - RemoveTopicChangeByOperatorFlag, - SetOperatorAbeyChannelLimits, - RemoveOperatorAbeyChannelLimits, - } - public enum ModeRequestType - { - GetChannelModes, - GetChannelAndUserModes, - SetChannelModes - - } - - public sealed class ModeRequest : ChannelRequestBase - { - public ModeRequestType RequestType { get; set; } - public List ModeOperations { get; set; } - public string NickName { get; set; } - public string UserName { get; set; } - public int LimitNumber { get; set; } - public string ModeFlag { get; set; } - public string Password { get; set; } - public ModeRequest(string rawRequest) : base(rawRequest) - { - ModeOperations = new List(); - } - public ModeRequest() { } - - public override void Parse() - { - // we skip parsing when this request is created manmually - if (RawRequest is null) - { - return; - } - base.Parse(); - if (_cmdParams.Count == 1) - { - RequestType = ModeRequestType.GetChannelModes; - } - else if (_cmdParams.Count == 2 || _cmdParams.Count == 3) - { - RequestType = ModeRequestType.SetChannelModes; - ModeFlag = _cmdParams[1]; - var modeFlags = Regex.Split(ModeFlag, @"(?=\+|\-)").Where(s => !String.IsNullOrEmpty(s)).ToArray(); - foreach (var flag in modeFlags) - { - switch (flag) - { - case "+e": - ModeOperations.Add(ModeOperationType.SetOperatorAbeyChannelLimits); - break; - case "-e": - ModeOperations.Add(ModeOperationType.RemoveOperatorAbeyChannelLimits); - break; - case "+t": - ModeOperations.Add(ModeOperationType.SetTopicChangeByOperatorFlag); - break; - case "-t": - ModeOperations.Add(ModeOperationType.RemoveTopicChangeByOperatorFlag); - break; - case "+n": - ModeOperations.Add(ModeOperationType.EnableExternalMessagesFlag); - break; - case "-n": - ModeOperations.Add(ModeOperationType.DisableExternalMessagesFlag); - break; - case "+m": - ModeOperations.Add(ModeOperationType.SetModeratedChannelFlag); - break; - case "-m": - ModeOperations.Add(ModeOperationType.RemoveModeratedChannelFlag); - break; - case "+s": - ModeOperations.Add(ModeOperationType.SetSecretChannelFlag); - break; - case "-s": - ModeOperations.Add(ModeOperationType.RemoveSecretChannelFlag); - break; - case "+i": - ModeOperations.Add(ModeOperationType.SetInvitedOnly); - break; - case "-i": - ModeOperations.Add(ModeOperationType.RemoveInvitedOnly); - break; - case "-p": - ModeOperations.Add(ModeOperationType.RemovePrivateChannelFlag); - break; - case "+p": - ModeOperations.Add(ModeOperationType.SetPrivateChannelFlag); - break; - case "+q": - NickName = _cmdParams[0]; - ModeOperations.Add(ModeOperationType.EnableUserQuietFlag); - break; - case "-q": - NickName = _cmdParams[0]; - ModeOperations.Add(ModeOperationType.DisableUserQuietFlag); - break; - case "+k": - ChannelName = _cmdParams[0]; - Password = _cmdParams[2]; - ModeOperations.Add(ModeOperationType.AddChannelPassword); - break; - case "-k": - ChannelName = _cmdParams[0]; - Password = _cmdParams[2]; - ModeOperations.Add(ModeOperationType.RemoveChannelPassword); - break; - case "+l": - ChannelName = _cmdParams[0]; - LimitNumber = int.Parse(_cmdParams[2]); - ModeOperations.Add(ModeOperationType.AddChannelUserLimits); - break; - case "-l": - ChannelName = _cmdParams[0]; - ModeOperations.Add(ModeOperationType.RemoveChannelUserLimits); - break; - case "+b": - ChannelName = _cmdParams[0]; - if (_cmdParams.Count == 3) - { - NickName = _cmdParams[2]; - ModeOperations.Add(ModeOperationType.AddBanOnUser); - } - else - { - ModeOperations.Add(ModeOperationType.GetBannedUsers); - } - break; - case "-b": - ChannelName = _cmdParams[0]; - ModeOperations.Add(ModeOperationType.RemoveBanOnUser); - break; - case "+co": - ChannelName = _cmdParams[0]; - UserName = _cmdParams[2]; - ModeOperations.Add(ModeOperationType.AddChannelOperator); - break; - case "-co": - ChannelName = _cmdParams[0]; - UserName = _cmdParams[2]; - ModeOperations.Add(ModeOperationType.RemoveChannelOperator); - break; - case "+cv": - ChannelName = _cmdParams[0]; - NickName = _cmdParams[2]; - ModeOperations.Add(ModeOperationType.EnableUserVoicePermission); - break; - case "-cv": - ChannelName = _cmdParams[0]; - NickName = _cmdParams[2]; - ModeOperations.Add(ModeOperationType.DisableUserVoicePermission); - break; - default: - throw new Chat.Exception("Unknown mode request type."); - } - - } - // TODO! We ignore multiple mode flags, maybe we need it in future for supporting games - - } - else - { - throw new Chat.Exception("number of IRC parameters are incorrect."); - } - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/Channel/PartRequest.cs b/src/Servers/Chat/src/Contract/Request/Channel/PartRequest.cs deleted file mode 100755 index fc708029c..000000000 --- a/src/Servers/Chat/src/Contract/Request/Channel/PartRequest.cs +++ /dev/null @@ -1,23 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.Channel -{ - - public sealed class PartRequest : ChannelRequestBase - { - public new string ChannelName{ get => base.ChannelName; set => base.ChannelName = value; } - public string Reason { get; set; } - public PartRequest() { } - public PartRequest(string rawRequest) : base(rawRequest){ } - public override void Parse() - { - base.Parse(); - if (_longParam is null) - { - throw new Chat.Exception("The reason of living channel is missing."); - } - Reason = _longParam; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/Channel/SetCKeyRequest.cs b/src/Servers/Chat/src/Contract/Request/Channel/SetCKeyRequest.cs deleted file mode 100755 index dc31307e2..000000000 --- a/src/Servers/Chat/src/Contract/Request/Channel/SetCKeyRequest.cs +++ /dev/null @@ -1,50 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using System.Collections.Generic; -using UniSpy.Server.Core.Extension; -using System.Linq; - -namespace UniSpy.Server.Chat.Contract.Request.Channel -{ - - public sealed class SetCKeyRequest : ChannelRequestBase - { - public string Channel { get; private set; } - public string NickName { get; private set; } - public string Cookie { get; private set; } - public bool IsBroadCast { get; private set; } - public string KeyValueString { get; private set; } - public Dictionary KeyValues { get; private set; } - - public SetCKeyRequest(string rawRequest) : base(rawRequest) - { - KeyValues = new Dictionary(); - } - - public override void Parse() - { - base.Parse(); - - if (_cmdParams is null) - { - throw new Chat.Exception("The cmdParams from SETCKEY request are missing."); - } - - if (_longParam is null) - { - throw new Chat.Exception("The longParam from SETCKEY request is missing."); - } - - Channel = _cmdParams[0]; - NickName = _cmdParams[1]; - _longParam = _longParam.Substring(1); - KeyValues = StringExtensions.ConvertKVStringToDictionary(_longParam); - KeyValueString = _longParam; - // todo check whether there exists other b_* key value - if (KeyValues.Keys.Where(x => x.Contains("b_")).Count() > 0) - { - Cookie = "BCAST"; - IsBroadCast = true; - } - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/Channel/SetChannelKeyRequest.cs b/src/Servers/Chat/src/Contract/Request/Channel/SetChannelKeyRequest.cs deleted file mode 100755 index b9a53bfbd..000000000 --- a/src/Servers/Chat/src/Contract/Request/Channel/SetChannelKeyRequest.cs +++ /dev/null @@ -1,29 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using System.Collections.Generic; -using UniSpy.Server.Core.Extension; - -namespace UniSpy.Server.Chat.Contract.Request.Channel -{ - - public sealed class SetChannelKeyRequest : ChannelRequestBase - { - public string KeyValueString { get; private set; } - public Dictionary KeyValues { get; private set; } - - public SetChannelKeyRequest(string rawRequest) : base(rawRequest) { } - - public override void Parse() - { - base.Parse(); - - if (_longParam is null) - { - throw new Chat.Exception("Channel keys and values are missing."); - } - _longParam = _longParam.Substring(1); - - KeyValues = StringExtensions.ConvertKVStringToDictionary(_longParam); - KeyValueString = _longParam; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/Channel/TopicRequest.cs b/src/Servers/Chat/src/Contract/Request/Channel/TopicRequest.cs deleted file mode 100755 index 6f64860a3..000000000 --- a/src/Servers/Chat/src/Contract/Request/Channel/TopicRequest.cs +++ /dev/null @@ -1,36 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.Channel -{ - public enum TopicRequestType - { - GetChannelTopic, - SetChannelTopic - } - - - public sealed class TopicRequest : ChannelRequestBase - { - public new string ChannelName{ get => base.ChannelName; set => base.ChannelName = value; } - public TopicRequest(string rawRequest) : base(rawRequest){ } - - public string Channel { get; private set; } - public string ChannelTopic { get; private set; } - public TopicRequestType RequestType { get; private set; } - - public override void Parse() - { - base.Parse(); - - if (_longParam is null) - { - RequestType = TopicRequestType.GetChannelTopic; - return; - } - - RequestType = TopicRequestType.SetChannelTopic; - ChannelTopic = _longParam; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/General/CdKeyRequest.cs b/src/Servers/Chat/src/Contract/Request/General/CdKeyRequest.cs deleted file mode 100755 index c5d14a55b..000000000 --- a/src/Servers/Chat/src/Contract/Request/General/CdKeyRequest.cs +++ /dev/null @@ -1,24 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.General -{ - - public sealed class CdKeyRequest : RequestBase - { - - public string CdKey { get; private set; } - public CdKeyRequest(string rawRequest) : base(rawRequest) { } - public override void Parse() - { - base.Parse(); - - if (_cmdParams.Count < 1) - { - throw new Chat.Exception("The number of IRC cmdParams are incorrect."); - } - - CdKey = _cmdParams[0]; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/General/CryptRequest.cs b/src/Servers/Chat/src/Contract/Request/General/CryptRequest.cs deleted file mode 100755 index b38a3428e..000000000 --- a/src/Servers/Chat/src/Contract/Request/General/CryptRequest.cs +++ /dev/null @@ -1,26 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.General -{ - - public sealed class CryptRequest : RequestBase - { - - public string VersionID { get; private set; } - public string GameName { get; private set; } - public CryptRequest(string rawRequest) : base(rawRequest) { } - public override void Parse() - { - base.Parse(); - - if (_cmdParams.Count < 3) - { - throw new Chat.Exception("The number of IRC params in CRYPT request is incorrect."); - } - - VersionID = _cmdParams[1]; - GameName = _cmdParams[2]; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/General/GetKeyRequest.cs b/src/Servers/Chat/src/Contract/Request/General/GetKeyRequest.cs deleted file mode 100755 index 13e5a50d8..000000000 --- a/src/Servers/Chat/src/Contract/Request/General/GetKeyRequest.cs +++ /dev/null @@ -1,49 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using System.Collections.Generic; -using UniSpy.Server.Core.Extension; - -namespace UniSpy.Server.Chat.Contract.Request.General -{ - /// - /// Retrieves a list of global key/value for a single user, or all users. - /// - - public sealed class GetKeyRequest : RequestBase - { - public bool IsGetAllUser { get; private set; } - public string NickName { get; private set; } - public string Cookie { get; private set; } - public string UnkownCmdParam { get; private set; } - public List Keys { get; private set; } - public GetKeyRequest(string rawRequest) : base(rawRequest) - { - Keys = new List(); - } - - public override void Parse() - { - base.Parse(); - - if (_cmdParams.Count < 2) - { - throw new Chat.Exception("The number of IRC cmd params in GETKEY request is incorrect."); - } - - if (_longParam is null) - { - throw new Chat.Exception("The number of IRC long params in GETKEY request is incorrect."); - } - - NickName = _cmdParams[0]; - Cookie = _cmdParams[1]; - UnkownCmdParam = _cmdParams[2]; - - _longParam = _longParam.Substring(0, _longParam.Length); - if (NickName == "*") - { - IsGetAllUser = true; - } - Keys = StringExtensions.ConvertKeyStrToList(_longParam); - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/General/GetUdpRelayRequest.cs b/src/Servers/Chat/src/Contract/Request/General/GetUdpRelayRequest.cs deleted file mode 100755 index 84f97f258..000000000 --- a/src/Servers/Chat/src/Contract/Request/General/GetUdpRelayRequest.cs +++ /dev/null @@ -1,11 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.General -{ - - public sealed class GetUdpRelayRequest : ChannelRequestBase - { - public GetUdpRelayRequest(string rawRequest) : base(rawRequest){ } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/General/InviteRequest.cs b/src/Servers/Chat/src/Contract/Request/General/InviteRequest.cs deleted file mode 100755 index 900fdf5ea..000000000 --- a/src/Servers/Chat/src/Contract/Request/General/InviteRequest.cs +++ /dev/null @@ -1,25 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.General -{ - - public sealed class InviteRequest : RequestBase - { - public string ChannelName { get; private set; } - public string NickName { get; private set; } - public InviteRequest(string rawRequest) : base(rawRequest) { } - public override void Parse() - { - base.Parse(); - - if (_cmdParams.Count != 2) - { - throw new Chat.Exception("The number of IRC cmd params in GETKEY request is incorrect."); - } - - ChannelName = _cmdParams[0]; - NickName = _cmdParams[1]; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/General/ListLimitRequest.cs b/src/Servers/Chat/src/Contract/Request/General/ListLimitRequest.cs deleted file mode 100755 index 558a3cbca..000000000 --- a/src/Servers/Chat/src/Contract/Request/General/ListLimitRequest.cs +++ /dev/null @@ -1,31 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.General -{ - - public sealed class ListLimitRequest : RequestBase - { - public int MaxNumberOfChannels { get; private set; } - public string Filter { get; private set; } - public ListLimitRequest(string rawRequest) : base(rawRequest) { } - public override void Parse() - { - base.Parse(); - - if (_cmdParams.Count != 2) - { - throw new Chat.Exception("The number of IRC cmd params in GETKEY request is incorrect."); - } - - int max; - if (!int.TryParse(_cmdParams[0], out max)) - { - throw new Chat.Exception("The max number format is incorrect."); - } - - MaxNumberOfChannels = max; - Filter = _cmdParams[1]; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/General/ListRequest.cs b/src/Servers/Chat/src/Contract/Request/General/ListRequest.cs deleted file mode 100755 index f20fd2b1f..000000000 --- a/src/Servers/Chat/src/Contract/Request/General/ListRequest.cs +++ /dev/null @@ -1,28 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.General -{ - - public sealed class ListRequest : RequestBase - { - public ListRequest(string rawRequest) : base(rawRequest) { } - - public bool IsSearchingChannel { get; private set; } - public bool IsSearchingUser { get; private set; } - public string Filter { get; private set; } - - public override void Parse() - { - base.Parse(); - - if (_cmdParams is null || _cmdParams?.Count == 0) - { - throw new Chat.Exception("The Search filter is missing."); - } - - IsSearchingChannel = true; - Filter = _cmdParams[0]; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/General/LoginPreAuthRequest.cs b/src/Servers/Chat/src/Contract/Request/General/LoginPreAuthRequest.cs deleted file mode 100755 index c4c1ff2d8..000000000 --- a/src/Servers/Chat/src/Contract/Request/General/LoginPreAuthRequest.cs +++ /dev/null @@ -1,23 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.General -{ - - - public sealed class LoginPreAuth : RequestBase - { - public LoginPreAuth(string rawRequest) : base(rawRequest){ } - - public string AuthToken { get; private set; } - public string PartnerChallenge { get; private set; } - - public override void Parse() - { - base.Parse(); - - AuthToken = _cmdParams[0]; - PartnerChallenge = _cmdParams[1]; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/General/LoginRequest.cs b/src/Servers/Chat/src/Contract/Request/General/LoginRequest.cs deleted file mode 100755 index 8461818b3..000000000 --- a/src/Servers/Chat/src/Contract/Request/General/LoginRequest.cs +++ /dev/null @@ -1,55 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using System.Linq; - -namespace UniSpy.Server.Chat.Contract.Request.General -{ - public enum LoginReqeustType - { - UniqueNickLogin, - NickAndEmailLogin, - } - - public sealed class LoginRequest : RequestBase - { - public LoginRequest(string rawRequest) : base(rawRequest){ } - - public LoginReqeustType ReqeustType { get; private set; } - public int NamespaceId { get; private set; } - public string NickName { get; private set; } - public string Email { get; private set; } - public string UniqueNick { get; private set; } - public string PasswordHash { get; private set; } - - public override void Parse() - { - base.Parse(); - - int namespaceid; - if (!int.TryParse(_cmdParams[0], out namespaceid)) - { - throw new Chat.Exception("The namespaceid format is incorrect."); - } - NamespaceId = namespaceid; - - if (_cmdParams[1] == "*") - { - ReqeustType = LoginReqeustType.NickAndEmailLogin; - PasswordHash = _cmdParams[2]; - - if (_longParam.Count(c => c == '@') != 2) - { - throw new Chat.Exception("The profile nick format is incorrect."); - } - - int profilenickIndex = _longParam.IndexOf("@"); - NickName = _longParam.Substring(0, profilenickIndex); - Email = _longParam.Substring(profilenickIndex + 1); - return; - } - - ReqeustType = LoginReqeustType.UniqueNickLogin; - UniqueNick = _cmdParams[1]; - PasswordHash = _cmdParams[2]; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/General/NamesRequest.cs b/src/Servers/Chat/src/Contract/Request/General/NamesRequest.cs deleted file mode 100755 index 6bf1cb476..000000000 --- a/src/Servers/Chat/src/Contract/Request/General/NamesRequest.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.General -{ - - public sealed class NamesRequest : ChannelRequestBase - { - public new string ChannelName{ get => base.ChannelName; set => base.ChannelName = value; } - public NamesRequest(string rawRequest) : base(rawRequest){ } - public NamesRequest() { } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/General/NickRequest.cs b/src/Servers/Chat/src/Contract/Request/General/NickRequest.cs deleted file mode 100755 index c9e05adb4..000000000 --- a/src/Servers/Chat/src/Contract/Request/General/NickRequest.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Error.IRC.General; - -namespace UniSpy.Server.Chat.Contract.Request.General -{ - - public sealed class NickRequest : RequestBase - { - private static List _invalidChars = new List() { '#', '@', '$', '%', '^', '&', '!', '~' }; - public NickRequest(string rawRequest) : base(rawRequest) { } - - public string NickName { get; private set; } - - public override void Parse() - { - base.Parse(); - - if (_cmdParams?.Count == 1) - { - NickName = _cmdParams[0]; - } - else if (_longParam is not null) - { - NickName = _longParam; - } - else - { - throw new Chat.Exception("NICK request is invalid."); - } - - foreach (var c in _invalidChars) - { - if (NickName.Contains(c)) - { - var validNickName = NickName.Replace(c, '0'); - throw new NickNameInUseException( - $"The nick name: {NickName} contains invalid character", - NickName, - validNickName); - } - } - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/General/PingRequest.cs b/src/Servers/Chat/src/Contract/Request/General/PingRequest.cs deleted file mode 100755 index 1c32b8289..000000000 --- a/src/Servers/Chat/src/Contract/Request/General/PingRequest.cs +++ /dev/null @@ -1,11 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.General -{ - - public sealed class PingRequest : RequestBase - { - public PingRequest(string rawRequest) : base(rawRequest){ } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/General/PongRequest.cs b/src/Servers/Chat/src/Contract/Request/General/PongRequest.cs deleted file mode 100755 index 20b65250a..000000000 --- a/src/Servers/Chat/src/Contract/Request/General/PongRequest.cs +++ /dev/null @@ -1,24 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.General -{ - - public sealed class PongRequest : RequestBase - { - public PongRequest(string rawRequest) : base(rawRequest){ } - - public string EchoMessage { get; private set; } - - public override void Parse() - { - base.Parse(); - - if (_longParam is null) - { - throw new Chat.Exception("Echo message is missing."); - } - EchoMessage = _longParam; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/General/QuitRequest.cs b/src/Servers/Chat/src/Contract/Request/General/QuitRequest.cs deleted file mode 100755 index 15081e03f..000000000 --- a/src/Servers/Chat/src/Contract/Request/General/QuitRequest.cs +++ /dev/null @@ -1,26 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.General -{ - - public sealed class QuitRequest : RequestBase - { - public QuitRequest() { } - public QuitRequest(string rawRequest) : base(rawRequest){ } - - public string Reason { get; set; } - - public override void Parse() - { - base.Parse(); - - if (_longParam is null) - { - throw new Chat.Exception("Quit reason is missing."); - } - - Reason = _longParam; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/General/RegisterNickRequest.cs b/src/Servers/Chat/src/Contract/Request/General/RegisterNickRequest.cs deleted file mode 100755 index c9decbf51..000000000 --- a/src/Servers/Chat/src/Contract/Request/General/RegisterNickRequest.cs +++ /dev/null @@ -1,23 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.General -{ - - public sealed class RegisterNickRequest : RequestBase - { - public RegisterNickRequest(string rawRequest) : base(rawRequest){ } - - public string NamespaceID { get; private set; } - public string UniqueNick { get; private set; } - public string CDKey { get; private set; } - public override void Parse() - { - base.Parse(); - - NamespaceID = _cmdParams[0]; - UniqueNick = _cmdParams[1]; - CDKey = _cmdParams[2]; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/General/SetGroupRequest.cs b/src/Servers/Chat/src/Contract/Request/General/SetGroupRequest.cs deleted file mode 100755 index 217ad9958..000000000 --- a/src/Servers/Chat/src/Contract/Request/General/SetGroupRequest.cs +++ /dev/null @@ -1,24 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.General -{ - - public sealed class SetGroupRequest : ChannelRequestBase - { - public SetGroupRequest(string rawRequest) : base(rawRequest){ } - - public string GroupName { get; private set; } - public override void Parse() - { - base.Parse(); - - if (_cmdParams.Count != 1) - { - throw new Chat.Exception("The number of IRC cmd params in GETKEY request is incorrect."); - } - - GroupName = _cmdParams[0]; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/General/SetKeyRequest.cs b/src/Servers/Chat/src/Contract/Request/General/SetKeyRequest.cs deleted file mode 100755 index ca43b45d0..000000000 --- a/src/Servers/Chat/src/Contract/Request/General/SetKeyRequest.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Core.Extension; - -namespace UniSpy.Server.Chat.Contract.Request.General -{ - - public sealed class SetKeyRequest : RequestBase - { - public Dictionary KeyValues { get; private set; } - - public SetKeyRequest(string rawRequest) : base(rawRequest){ } - - public override void Parse() - { - base.Parse(); - - if (_longParam is null) - { - throw new Chat.Exception("The keys and values are missing."); - } - KeyValues = StringExtensions.ConvertKVStringToDictionary(_longParam); - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/General/UserIPRequest.cs b/src/Servers/Chat/src/Contract/Request/General/UserIPRequest.cs deleted file mode 100755 index e2198e6c6..000000000 --- a/src/Servers/Chat/src/Contract/Request/General/UserIPRequest.cs +++ /dev/null @@ -1,17 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.General -{ - - public sealed class UserIPRequest : RequestBase - { - public UserIPRequest(string rawRequest) : base(rawRequest){ } - - public override void Parse() - { - base.Parse(); - // USRIP content is empty! - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/General/UserRequest.cs b/src/Servers/Chat/src/Contract/Request/General/UserRequest.cs deleted file mode 100755 index 33243ee08..000000000 --- a/src/Servers/Chat/src/Contract/Request/General/UserRequest.cs +++ /dev/null @@ -1,35 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.General -{ - - public sealed class UserRequest : RequestBase - { - public UserRequest(string rawRequest) : base(rawRequest) { } - - public string UserName { get; private set; } - public string Hostname { get; private set; } - public string ServerName { get; private set; } - public string NickName { get; private set; } - public string Name { get; private set; } - - public override void Parse() - { - base.Parse(); - if (_cmdParams.Count == 3) - { - UserName = _cmdParams[0]; - Hostname = _cmdParams[1]; - ServerName = _cmdParams[2]; - } - else - { - Hostname = _cmdParams[0]; - ServerName = _cmdParams[1]; - } - - Name = _longParam; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/General/WhoIsRequest.cs b/src/Servers/Chat/src/Contract/Request/General/WhoIsRequest.cs deleted file mode 100755 index 2433f55ec..000000000 --- a/src/Servers/Chat/src/Contract/Request/General/WhoIsRequest.cs +++ /dev/null @@ -1,25 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.General -{ - - public sealed class WhoIsRequest : RequestBase - { - public WhoIsRequest(string rawRequest) : base(rawRequest){ } - - public string NickName { get; private set; } - - public override void Parse() - { - base.Parse(); - - if (_cmdParams.Count != 1) - { - throw new Chat.Exception("The number of IRC cmd params in WHOIS request is incorrect."); - } - - NickName = _cmdParams[0]; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/General/WhoRequest.cs b/src/Servers/Chat/src/Contract/Request/General/WhoRequest.cs deleted file mode 100755 index 0cb558bcd..000000000 --- a/src/Servers/Chat/src/Contract/Request/General/WhoRequest.cs +++ /dev/null @@ -1,39 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.General -{ - public enum WhoRequestType - { - GetChannelUsersInfo, - GetUserInfo - } - - public sealed class WhoRequest : RequestBase - { - public WhoRequest(string rawRequest) : base(rawRequest){ } - - public WhoRequestType RequestType { get; private set; } - public string ChannelName { get; private set; } - public string NickName { get; private set; } - public override void Parse() - { - base.Parse(); - - if (_cmdParams.Count != 1) - { - throw new Chat.Exception("The number of IRC cmd params in WHO request is incorrect."); - } - - if (_cmdParams[0].Contains("#")) - { - RequestType = WhoRequestType.GetChannelUsersInfo; - ChannelName = _cmdParams[0]; - return; - } - - RequestType = WhoRequestType.GetUserInfo; - NickName = _cmdParams[0]; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/Message/AtmRequest.cs b/src/Servers/Chat/src/Contract/Request/Message/AtmRequest.cs deleted file mode 100644 index d0914c3ed..000000000 --- a/src/Servers/Chat/src/Contract/Request/Message/AtmRequest.cs +++ /dev/null @@ -1,11 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.Message -{ - - public sealed class AtmRequest : MessageRequestBase - { - public AtmRequest(string rawRequest) : base(rawRequest){ } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/Message/NoticeRequest.cs b/src/Servers/Chat/src/Contract/Request/Message/NoticeRequest.cs deleted file mode 100644 index c1c005f13..000000000 --- a/src/Servers/Chat/src/Contract/Request/Message/NoticeRequest.cs +++ /dev/null @@ -1,11 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.Message -{ - - public sealed class NoticeRequest : MessageRequestBase - { - public NoticeRequest(string rawRequest) : base(rawRequest){ } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/Message/PrivateRequest.cs b/src/Servers/Chat/src/Contract/Request/Message/PrivateRequest.cs deleted file mode 100644 index 2a6b33c07..000000000 --- a/src/Servers/Chat/src/Contract/Request/Message/PrivateRequest.cs +++ /dev/null @@ -1,11 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.Message -{ - - public sealed class PrivateRequest : MessageRequestBase - { - public PrivateRequest(string rawRequest) : base(rawRequest){ } - } -} diff --git a/src/Servers/Chat/src/Contract/Request/Message/UtmRequest.cs b/src/Servers/Chat/src/Contract/Request/Message/UtmRequest.cs deleted file mode 100644 index b4528986c..000000000 --- a/src/Servers/Chat/src/Contract/Request/Message/UtmRequest.cs +++ /dev/null @@ -1,11 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - - -namespace UniSpy.Server.Chat.Contract.Request.Message -{ - - public sealed class UtmRequest : MessageRequestBase - { - public UtmRequest(string rawRequest) : base(rawRequest){ } - } -} diff --git a/src/Servers/Chat/src/Contract/Response/Channel/GetCKeyResponse.cs b/src/Servers/Chat/src/Contract/Response/Channel/GetCKeyResponse.cs deleted file mode 100755 index 808743404..000000000 --- a/src/Servers/Chat/src/Contract/Response/Channel/GetCKeyResponse.cs +++ /dev/null @@ -1,26 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Request.Channel; -using UniSpy.Server.Chat.Contract.Result.Channel; - -namespace UniSpy.Server.Chat.Contract.Response.Channel -{ - public sealed class GetCKeyResponse : ResponseBase - { - private new GetCKeyRequest _request => (GetCKeyRequest)base._request; - private new GetCKeyResult _result => (GetCKeyResult)base._result; - - public GetCKeyResponse(GetCKeyRequest request, GetCKeyResult result) : base(request, result) { } - - public override void Build() - { - SendingBuffer = ""; - foreach (var data in _result.DataResults) - { - SendingBuffer += $":{ServerDomain} {ResponseName.GetCKey} * {_request.ChannelName} {data.NickName} {_request.Cookie} {data.UserValues}\r\n"; - } - - SendingBuffer += $":{ServerDomain} {ResponseName.EndGetCKey} * {_request.ChannelName} {_request.Cookie} :End Of GETCKEY.\r\n"; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Response/Channel/GetChannelKeyResponse.cs b/src/Servers/Chat/src/Contract/Response/Channel/GetChannelKeyResponse.cs deleted file mode 100755 index 0522b3955..000000000 --- a/src/Servers/Chat/src/Contract/Response/Channel/GetChannelKeyResponse.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Request.Channel; -using UniSpy.Server.Chat.Contract.Result.Channel; - -namespace UniSpy.Server.Chat.Contract.Response.Channel -{ - public sealed class GetChannelKeyResponse : ChannelResponseBase - { - private new GetChannelKeyRequest _request => (GetChannelKeyRequest)base._request; - private new GetChannelKeyResult _result => (GetChannelKeyResult)base._result; - public GetChannelKeyResponse(GetChannelKeyRequest request, GetChannelKeyResult result) : base(request, result) { } - - public override void Build() - { - SendingBuffer = $":{_result.ChannelUserIRCPrefix} {ResponseName.GetChanKey} * {_result.ChannelName} {_request.Cookie} {_result.Values}\r\n"; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Response/Channel/JoinResponse.cs b/src/Servers/Chat/src/Contract/Response/Channel/JoinResponse.cs deleted file mode 100755 index 28e6f0deb..000000000 --- a/src/Servers/Chat/src/Contract/Response/Channel/JoinResponse.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Request.Channel; -using UniSpy.Server.Chat.Contract.Result.Channel; - -namespace UniSpy.Server.Chat.Contract.Response.Channel -{ - public sealed class JoinResponse : ResponseBase - { - private new JoinRequest _request => (JoinRequest)base._request; - private new JoinResult _result => (JoinResult)base._result; - // public string SendingBufferOfChannelUsers { get; private set; } - public JoinResponse(JoinRequest request, JoinResult result) : base(request, result) { } - - public override void Build() - { - SendingBuffer = $":{_result.JoinerPrefix} {ResponseName.Join} {_request.ChannelName}\r\n"; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Response/Channel/KickResponse.cs b/src/Servers/Chat/src/Contract/Response/Channel/KickResponse.cs deleted file mode 100755 index 42a39fa47..000000000 --- a/src/Servers/Chat/src/Contract/Response/Channel/KickResponse.cs +++ /dev/null @@ -1,18 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Request.Channel; -using UniSpy.Server.Chat.Contract.Result.Channel; - -namespace UniSpy.Server.Chat.Contract.Response.Channel -{ - public sealed class KickResponse : ResponseBase - { - private new KickRequest _request => (KickRequest)base._request; - private new KickResult _result => (KickResult)base._result; - public KickResponse(KickRequest request, KickResult result) : base(request, result) { } - public override void Build() - { - SendingBuffer = $":{_result.KickerIRCPrefix} {ResponseName.Kick} {_result.ChannelName} {_result.KickeeNickName} :{_request.Reason}\r\n"; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Response/Channel/ModeResponse.cs b/src/Servers/Chat/src/Contract/Response/Channel/ModeResponse.cs deleted file mode 100755 index 129592d6a..000000000 --- a/src/Servers/Chat/src/Contract/Response/Channel/ModeResponse.cs +++ /dev/null @@ -1,29 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Request.Channel; -using UniSpy.Server.Chat.Contract.Result.Channel; - -namespace UniSpy.Server.Chat.Contract.Response.Channel -{ - //TODO apply channel abstraction into this class - public sealed class ModeResponse : ResponseBase - { - private new ModeRequest _request => (ModeRequest)base._request; - private new ModeResult _result => (ModeResult)base._result; - public ModeResponse(ModeRequest request, ModeResult result) : base(request, result) { } - public override void Build() - { - if (_request.RequestType == ModeRequestType.GetChannelModes) - { - //channel modes reply - SendingBuffer = $":{ServerDomain} {ResponseName.ChannelModels} * {_result.ChannelName} {_result.ChannelModes}\r\n"; - } - else - { - //channel user mode reply - // the client will know which mode its ask for - SendingBuffer = $":{ServerDomain} {ResponseName.Mode} * {_result.ChannelName} {_result.ChannelModes}\r\n"; - } - } - } -} diff --git a/src/Servers/Chat/src/Contract/Response/Channel/NamesResponse.cs b/src/Servers/Chat/src/Contract/Response/Channel/NamesResponse.cs deleted file mode 100755 index 901541eff..000000000 --- a/src/Servers/Chat/src/Contract/Response/Channel/NamesResponse.cs +++ /dev/null @@ -1,21 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Request.General; -using UniSpy.Server.Chat.Contract.Result.Channel; - -namespace UniSpy.Server.Chat.Contract.Response.Channel -{ - public sealed class NamesResponse : ChannelResponseBase - { - private new NamesRequest _request => (NamesRequest)base._request; - private new NamesResult _result => (NamesResult)base._result; - public NamesResponse(NamesRequest request, NamesResult result) : base(request, result) { } - public override void Build() - { - SendingBuffer = $":{ServerDomain} {ResponseName.NameReply} {_result.RequesterNickName} = {_result.ChannelName} :{_result.AllChannelUserNicks}\r\n"; - - SendingBuffer += $":{ServerDomain} {ResponseName.EndOfNames} {_result.RequesterNickName} {_result.ChannelName} :End of NAMES list.\r\n"; - - } - } -} diff --git a/src/Servers/Chat/src/Contract/Response/Channel/PartResponse.cs b/src/Servers/Chat/src/Contract/Response/Channel/PartResponse.cs deleted file mode 100755 index 2f27b39b1..000000000 --- a/src/Servers/Chat/src/Contract/Response/Channel/PartResponse.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Request.Channel; -using UniSpy.Server.Chat.Contract.Result.Channel; - -namespace UniSpy.Server.Chat.Contract.Response.Channel -{ - public sealed class PartResponse : ResponseBase - { - private new PartRequest _request => (PartRequest)base._request; - private new PartResult _result => (PartResult)base._result; - public PartResponse(PartRequest request, PartResult result) : base(request, result) { } - - public override void Build() - { - SendingBuffer = $":{_result.LeaverIRCPrefix} {ResponseName.Part} {_result.ChannelName} :{_request.Reason ?? "Unknown reason"}\r\n"; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Response/Channel/SetCKeyResponse.cs b/src/Servers/Chat/src/Contract/Response/Channel/SetCKeyResponse.cs deleted file mode 100755 index 153a6ceee..000000000 --- a/src/Servers/Chat/src/Contract/Response/Channel/SetCKeyResponse.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Request.Channel; - -namespace UniSpy.Server.Chat.Contract.Response.Channel -{ - public sealed class SetCKeyResponse : ResponseBase - { - private new SetCKeyRequest _request => (SetCKeyRequest)base._request; - public SetCKeyResponse(SetCKeyRequest request) : base(request, null) { } - public override void Build() - { - // the broadcast message must contain keys and values. - SendingBuffer = $":{ServerDomain} {ResponseName.GetCKey} * {_request.ChannelName} {_request.NickName} {_request.Cookie} {_request.KeyValueString}\r\n"; - - SendingBuffer += $":{ServerDomain} {ResponseName.EndGetCKey} * {_request.ChannelName} {_request.Cookie} :End Of SETCKEY.\r\n"; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Response/Channel/SetChannelKeyResponse.cs b/src/Servers/Chat/src/Contract/Response/Channel/SetChannelKeyResponse.cs deleted file mode 100755 index 7c773050d..000000000 --- a/src/Servers/Chat/src/Contract/Response/Channel/SetChannelKeyResponse.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Request.Channel; -using UniSpy.Server.Chat.Contract.Result.Channel; - -namespace UniSpy.Server.Chat.Contract.Response.Channel -{ - public sealed class SetChannelKeyResponse : ChannelResponseBase - { - private new SetChannelKeyRequest _request => (SetChannelKeyRequest)base._request; - private new SetChannelKeyResult _result => (SetChannelKeyResult)base._result; - public SetChannelKeyResponse(SetChannelKeyRequest request, SetChannelKeyResult result) : base(request, result) { } - - public override void Build() - { - // the broadcast message must contain key and values. - SendingBuffer = $":{_result.ChannelUserIRCPrefix} {ResponseName.GetChanKey} * {_request.ChannelName} BCAST {_request.KeyValueString}\r\n"; - } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Contract/Response/Channel/TopicResponse.cs b/src/Servers/Chat/src/Contract/Response/Channel/TopicResponse.cs deleted file mode 100755 index 0cd53a854..000000000 --- a/src/Servers/Chat/src/Contract/Response/Channel/TopicResponse.cs +++ /dev/null @@ -1,26 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Request.Channel; -using UniSpy.Server.Chat.Contract.Result.Channel; - -namespace UniSpy.Server.Chat.Contract.Response.Channel -{ - public sealed class TopicResponse : ResponseBase - { - private new TopicRequest _request => (TopicRequest)base._request; - private new TopicResult _result => (TopicResult)base._result; - public TopicResponse(TopicRequest request, TopicResult result) : base(request, result) { } - - public override void Build() - { - if (_result.ChannelTopic == "" || _result.ChannelTopic is null) - { - SendingBuffer = $":{ServerDomain} {ResponseName.NoTopic} * {_result.ChannelName}\r\n"; - } - else - { - SendingBuffer = $":{ServerDomain} {ResponseName.Topic} * {_result.ChannelName} :{_result.ChannelTopic}\r\n"; - } - } - } -} diff --git a/src/Servers/Chat/src/Contract/Response/General/CdKeyResponse.cs b/src/Servers/Chat/src/Contract/Response/General/CdKeyResponse.cs deleted file mode 100755 index 59fcb1f28..000000000 --- a/src/Servers/Chat/src/Contract/Response/General/CdKeyResponse.cs +++ /dev/null @@ -1,16 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; - -namespace UniSpy.Server.Chat.Contract.Response.General -{ - public sealed class CdKeyResponse : ResponseBase - { - public CdKeyResponse(RequestBase request, ResultBase result) : base(request, result) { } - - public override void Build() - { - //CDKey is always true - SendingBuffer = $":{ServerDomain} {ResponseName.CDKey} * 1 :Authenticated \r\n"; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Response/General/CryptResponse.cs b/src/Servers/Chat/src/Contract/Response/General/CryptResponse.cs deleted file mode 100755 index a53507e40..000000000 --- a/src/Servers/Chat/src/Contract/Response/General/CryptResponse.cs +++ /dev/null @@ -1,16 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Result.General; - -namespace UniSpy.Server.Chat.Contract.Response.General -{ - public sealed class CryptResponse : ResponseBase - { - private new CryptResult _result => (CryptResult)base._result; - public CryptResponse(RequestBase request, ResultBase result) : base(request, result) { } - public override void Build() - { - SendingBuffer = $":{ServerDomain} {ResponseName.SecureKey} * {ChatCrypt.ClientKey} {ChatCrypt.ServerKey}\r\n"; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Response/General/GetKeyResponse.cs b/src/Servers/Chat/src/Contract/Response/General/GetKeyResponse.cs deleted file mode 100755 index 0463a8903..000000000 --- a/src/Servers/Chat/src/Contract/Response/General/GetKeyResponse.cs +++ /dev/null @@ -1,24 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Request.General; -using UniSpy.Server.Chat.Contract.Result.General; - -namespace UniSpy.Server.Chat.Contract.Response.General -{ - public sealed class GetKeyResponse : ResponseBase - { - private new GetKeyResult _result => (GetKeyResult)base._result; - private new GetKeyRequest _request => (GetKeyRequest)base._request; - public GetKeyResponse(RequestBase request, ResultBase result) : base(request, result) { } - - public override void Build() - { - SendingBuffer = ""; - foreach (var value in _result.Values) - { - SendingBuffer += $":{ServerDomain} {ResponseName.GetKey} * {_result.NickName} {_request.Cookie} {value}\r\n"; - } - SendingBuffer += $":{ServerDomain} {ResponseName.EndGetKey} * {_request.Cookie} * :End of GETKEY.\r\n"; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Response/General/ListResponse.cs b/src/Servers/Chat/src/Contract/Response/General/ListResponse.cs deleted file mode 100755 index b18eb561f..000000000 --- a/src/Servers/Chat/src/Contract/Response/General/ListResponse.cs +++ /dev/null @@ -1,21 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Result.General; - -namespace UniSpy.Server.Chat.Contract.Response.General -{ - public sealed class ListResponse : ResponseBase - { - private new ListResult _result => (ListResult)base._result; - public ListResponse(RequestBase request, ResultBase result) : base(request, result) { } - public override void Build() - { - SendingBuffer = ""; - foreach (var info in _result.ChannelInfoList) - { - SendingBuffer += $":{_result.UserIRCPrefix} {ResponseName.ListStart} * {info.ChannelName} {info.TotalChannelUsers} {info.ChannelTopic}\r\n"; - } - SendingBuffer += $":{_result.UserIRCPrefix} {ResponseName.ListEnd}\r\n"; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Response/General/LoginResponse.cs b/src/Servers/Chat/src/Contract/Response/General/LoginResponse.cs deleted file mode 100755 index 5c057c043..000000000 --- a/src/Servers/Chat/src/Contract/Response/General/LoginResponse.cs +++ /dev/null @@ -1,17 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Result.General; - -namespace UniSpy.Server.Chat.Contract.Response.General -{ - public sealed class LoginResponse : ResponseBase - { - private new LoginResult _result => (LoginResult)base._result; - public LoginResponse(RequestBase request, ResultBase result) : base(request, result) { } - - public override void Build() - { - SendingBuffer = $":{ServerDomain} {ResponseName.Login} * {_result.UserID} {_result.ProfileId}\r\n"; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Response/General/NickResponse.cs b/src/Servers/Chat/src/Contract/Response/General/NickResponse.cs deleted file mode 100755 index b0acdc63d..000000000 --- a/src/Servers/Chat/src/Contract/Response/General/NickResponse.cs +++ /dev/null @@ -1,16 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Request.General; - -namespace UniSpy.Server.Chat.Contract.Response.General -{ - public sealed class NickResponse : ResponseBase - { - private new NickRequest _request => (NickRequest)base._request; - public NickResponse(RequestBase request, ResultBase result) : base(request, result) { } - public override void Build() - { - SendingBuffer = $":{ServerDomain} {ResponseName.Welcome} {_request.NickName} :Welcome to UniSpy!\r\n"; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Response/General/PingResponse.cs b/src/Servers/Chat/src/Contract/Response/General/PingResponse.cs deleted file mode 100755 index 7912dfee5..000000000 --- a/src/Servers/Chat/src/Contract/Response/General/PingResponse.cs +++ /dev/null @@ -1,17 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Result.General; - -namespace UniSpy.Server.Chat.Contract.Response.General -{ - public sealed class PingResponse : ResponseBase - { - private new PingResult _result => (PingResult)base._result; - public PingResponse(RequestBase request, ResultBase result) : base(request, result) { } - - public override void Build() - { - SendingBuffer = $":{_result.RequesterIRCPrefix} {ResponseName.Pong}\r\n"; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Response/General/UserIPResponse.cs b/src/Servers/Chat/src/Contract/Response/General/UserIPResponse.cs deleted file mode 100755 index 9476d62e4..000000000 --- a/src/Servers/Chat/src/Contract/Response/General/UserIPResponse.cs +++ /dev/null @@ -1,17 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Result.General; - -namespace UniSpy.Server.Chat.Contract.Response.General -{ - public sealed class UserIPResponse : ResponseBase - { - private new UserIPResult _result => (UserIPResult)base._result; - public UserIPResponse(RequestBase request, ResultBase result) : base(request, result) { } - - public override void Build() - { - SendingBuffer = $":{ServerDomain} {ResponseName.UserIP} :@{_result.RemoteIPAddress}\r\n"; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Response/General/WhoIsResponse.cs b/src/Servers/Chat/src/Contract/Response/General/WhoIsResponse.cs deleted file mode 100755 index 3efb098a9..000000000 --- a/src/Servers/Chat/src/Contract/Response/General/WhoIsResponse.cs +++ /dev/null @@ -1,31 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Result.General; -using System.Linq; - -namespace UniSpy.Server.Chat.Contract.Response.General -{ - public sealed class WhoIsResponse : ResponseBase - { - private new WhoIsResult _result => (WhoIsResult)base._result; - public WhoIsResponse(RequestBase request, ResultBase result) : base(request, result) { } - public override void Build() - { - SendingBuffer = $":{ServerDomain} {ResponseName.WhoIsUser} {_result.NickName} {_result.Name} {_result.UserName} {_result.PublicIPAddress} * :{_result.UserName}\r\n"; - - if (_result.JoinedChannelName.Count() != 0) - { - string channelNames = ""; - //todo remove last space - foreach (var name in _result.JoinedChannelName) - { - channelNames += $"@{name} "; - } - - SendingBuffer += $":{ServerDomain} {ResponseName.WhoIsChannels} {_result.NickName} {_result.Name} :{channelNames}\r\n"; - - SendingBuffer += $":{ServerDomain} {ResponseName.EndOfWhoIs} {_result.NickName} {_result.Name} :End of WHOIS list.\r\n"; - } - } - } -} diff --git a/src/Servers/Chat/src/Contract/Response/General/WhoResponse.cs b/src/Servers/Chat/src/Contract/Response/General/WhoResponse.cs deleted file mode 100755 index 7f9ac50a8..000000000 --- a/src/Servers/Chat/src/Contract/Response/General/WhoResponse.cs +++ /dev/null @@ -1,38 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Request.General; -using UniSpy.Server.Chat.Contract.Result.General; - -namespace UniSpy.Server.Chat.Contract.Response.General -{ - public sealed class WhoResponse : ResponseBase - { - private new WhoRequest _request => (WhoRequest)base._request; - private new WhoResult _result => (WhoResult)base._result; - public WhoResponse(RequestBase request, ResultBase result) : base(request, result) { } - public override void Build() - { - SendingBuffer = ""; - foreach (var data in _result.DataModels) - { - SendingBuffer += $":{ServerDomain} {ResponseName.WhoReply} * {data.ChannelName} {data.UserName} {data.PublicIPAddress} * {data.NickName} {data.Modes} *\r\n"; - } - switch (_request.RequestType) - { - case WhoRequestType.GetChannelUsersInfo: - if (_result.DataModels.Count > 0) - { - SendingBuffer += $":{ServerDomain} {ResponseName.EndOfWho} * {_request.ChannelName} * :End of WHO.\r\n"; - } - break; - case WhoRequestType.GetUserInfo: - if (_result.DataModels.Count > 0) - { - SendingBuffer += $":{ServerDomain} {ResponseName.EndOfWho} * {_request.NickName} * :End of WHO.\r\n"; - } - break; - } - } - } -} - diff --git a/src/Servers/Chat/src/Contract/Response/Message/AtmResponse.cs b/src/Servers/Chat/src/Contract/Response/Message/AtmResponse.cs deleted file mode 100755 index 914b451a0..000000000 --- a/src/Servers/Chat/src/Contract/Response/Message/AtmResponse.cs +++ /dev/null @@ -1,18 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Result.Message; - -namespace UniSpy.Server.Chat.Contract.Response.Message -{ - public sealed class AtmResponse : ResponseBase - { - private new MessageRequestBase _request => (MessageRequestBase)base._request; - private new AtmResult _result => (AtmResult)base._result; - public AtmResponse(RequestBase request, ResultBase result) : base(request, result) { } - - public override void Build() - { - SendingBuffer = $":{_result.UserIRCPrefix} {ResponseName.AboveTheTableMsg} {_result.TargetName} :{_request.Message}\r\n"; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Response/Message/NoticeResponse.cs b/src/Servers/Chat/src/Contract/Response/Message/NoticeResponse.cs deleted file mode 100755 index 27e540ef9..000000000 --- a/src/Servers/Chat/src/Contract/Response/Message/NoticeResponse.cs +++ /dev/null @@ -1,18 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Request.Message; -using UniSpy.Server.Chat.Contract.Result.Message; - -namespace UniSpy.Server.Chat.Contract.Response.Message -{ - public sealed class NoticeResponse : ResponseBase - { - private new NoticeResult _result => (NoticeResult)base._result; - private new NoticeRequest _request => (NoticeRequest)base._request; - public NoticeResponse(RequestBase request, ResultBase result) : base(request, result){ } - public override void Build() - { - SendingBuffer = $":{_result.UserIRCPrefix} {ResponseName.Notice} {_result.TargetName} :{_request.Message}\r\n"; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Response/Message/PrivateResponse.cs b/src/Servers/Chat/src/Contract/Response/Message/PrivateResponse.cs deleted file mode 100755 index b11507774..000000000 --- a/src/Servers/Chat/src/Contract/Response/Message/PrivateResponse.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Request.Message; -using UniSpy.Server.Chat.Contract.Result.Message; - -namespace UniSpy.Server.Chat.Contract.Response.Message -{ - public sealed class PrivateResponse : ResponseBase - { - private new PrivateResult _result => (PrivateResult)base._result; - private new PrivateRequest _request => (PrivateRequest)base._request; - public PrivateResponse(RequestBase request, ResultBase result) : base(request, result) { } - - public override void Build() - { - SendingBuffer = $":{_result.UserIRCPrefix} {ResponseName.PrivateMsg} {_result.TargetName} :{_request.Message}\r\n"; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Response/Message/UtmResponse.cs b/src/Servers/Chat/src/Contract/Response/Message/UtmResponse.cs deleted file mode 100755 index 3ce159fc8..000000000 --- a/src/Servers/Chat/src/Contract/Response/Message/UtmResponse.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Request.Message; -using UniSpy.Server.Chat.Contract.Result.Message; - -namespace UniSpy.Server.Chat.Contract.Response.Message -{ - public sealed class UtmResponse : ResponseBase - { - private new UtmResult _result => (UtmResult)base._result; - private new UtmRequest _request => (UtmRequest)base._request; - public UtmResponse(RequestBase request, ResultBase result) : base(request, result) { } - - public override void Build() - { - SendingBuffer = $":{_result.UserIRCPrefix} {ResponseName.UnderTheTableMsg} {_result.TargetName} :{_request.Message}\r\n"; - } - } -} diff --git a/src/Servers/Chat/src/Contract/Result/Channel/GetCKeyResult.cs b/src/Servers/Chat/src/Contract/Result/Channel/GetCKeyResult.cs deleted file mode 100755 index 390a0dd03..000000000 --- a/src/Servers/Chat/src/Contract/Result/Channel/GetCKeyResult.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using System.Collections.Generic; - -namespace UniSpy.Server.Chat.Contract.Result.Channel -{ - public sealed class GetCKeyDataModel - { - public string NickName { get; set; } - public string UserValues { get; set; } - } - public sealed class GetCKeyResult : ResultBase - { - public List DataResults { get; } - public string ChannelName { get; set; } - public GetCKeyResult() - { - DataResults = new List(); - } - } -} diff --git a/src/Servers/Chat/src/Contract/Result/Channel/GetChannelKeyResult.cs b/src/Servers/Chat/src/Contract/Result/Channel/GetChannelKeyResult.cs deleted file mode 100755 index 4d0f25909..000000000 --- a/src/Servers/Chat/src/Contract/Result/Channel/GetChannelKeyResult.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - -namespace UniSpy.Server.Chat.Contract.Result.Channel -{ - public sealed class GetChannelKeyResult : ResultBase - { - public string ChannelUserIRCPrefix { get; set; } - public string ChannelName { get; set; } - public string Values { get; set; } - public GetChannelKeyResult(){ } - } -} diff --git a/src/Servers/Chat/src/Contract/Result/Channel/JoinResult.cs b/src/Servers/Chat/src/Contract/Result/Channel/JoinResult.cs deleted file mode 100755 index 4d493d630..000000000 --- a/src/Servers/Chat/src/Contract/Result/Channel/JoinResult.cs +++ /dev/null @@ -1,16 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - -namespace UniSpy.Server.Chat.Contract.Result.Channel -{ - public sealed class JoinResult : ResultBase - { - public string JoinerPrefix { get; set; } - public string JoinerNickName { get; set; } - public string AllChannelUserNicks { get; set; } - public string ChannelModes { get; set; } - - // public string ChannelModes { get; set; } - // public List NickNames { get; set; } - public JoinResult(){ } - } -} diff --git a/src/Servers/Chat/src/Contract/Result/Channel/KickResult.cs b/src/Servers/Chat/src/Contract/Result/Channel/KickResult.cs deleted file mode 100755 index 999ddf37e..000000000 --- a/src/Servers/Chat/src/Contract/Result/Channel/KickResult.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - -namespace UniSpy.Server.Chat.Contract.Result.Channel -{ - public sealed class KickResult : ResultBase - { - public string ChannelName { get; set; } - public string KickerNickName { get; set; } - public string KickeeNickName { get; set; } - public string KickerIRCPrefix { get; set; } - public KickResult(){ } - } -} diff --git a/src/Servers/Chat/src/Contract/Result/Channel/ModeResult.cs b/src/Servers/Chat/src/Contract/Result/Channel/ModeResult.cs deleted file mode 100755 index 944ab0de1..000000000 --- a/src/Servers/Chat/src/Contract/Result/Channel/ModeResult.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - -namespace UniSpy.Server.Chat.Contract.Result.Channel -{ - public sealed class ModeResult : ResultBase - { - public string ChannelModes { get; set; } - public string ChannelName { get; set; } - public string JoinerNickName { get; set; } - public ModeResult(){ } - } -} diff --git a/src/Servers/Chat/src/Contract/Result/Channel/NamesResult.cs b/src/Servers/Chat/src/Contract/Result/Channel/NamesResult.cs deleted file mode 100755 index 72e7356dc..000000000 --- a/src/Servers/Chat/src/Contract/Result/Channel/NamesResult.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - -namespace UniSpy.Server.Chat.Contract.Result.Channel -{ - public sealed class NamesResult : ResultBase - { - public string AllChannelUserNicks { get; set; } - public string ChannelName { get; set; } - public string RequesterNickName { get; set; } - public NamesResult(){ } - } -} diff --git a/src/Servers/Chat/src/Contract/Result/Channel/PartResult.cs b/src/Servers/Chat/src/Contract/Result/Channel/PartResult.cs deleted file mode 100755 index 70bdf1449..000000000 --- a/src/Servers/Chat/src/Contract/Result/Channel/PartResult.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - -namespace UniSpy.Server.Chat.Contract.Result.Channel -{ - public sealed class PartResult : ResultBase - { - public string LeaverIRCPrefix { get; set; } - public bool IsChannelCreator { get; set; } - public string ChannelName { get; set; } - public PartResult() { } - } -} diff --git a/src/Servers/Chat/src/Contract/Result/Channel/SetChannelKeyResult.cs b/src/Servers/Chat/src/Contract/Result/Channel/SetChannelKeyResult.cs deleted file mode 100755 index e0388c398..000000000 --- a/src/Servers/Chat/src/Contract/Result/Channel/SetChannelKeyResult.cs +++ /dev/null @@ -1,11 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - -namespace UniSpy.Server.Chat.Contract.Result.Channel -{ - public sealed class SetChannelKeyResult : ResultBase - { - public string ChannelUserIRCPrefix { get; set; } - public string ChannelName { get; set; } - public SetChannelKeyResult(){ } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Contract/Result/Channel/TopicResult.cs b/src/Servers/Chat/src/Contract/Result/Channel/TopicResult.cs deleted file mode 100755 index 2b15af961..000000000 --- a/src/Servers/Chat/src/Contract/Result/Channel/TopicResult.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - -namespace UniSpy.Server.Chat.Contract.Result.Channel -{ - public sealed class TopicResult : ResultBase - { - public string ChannelName { get; set; } - public string ChannelTopic { get; set; } - - public TopicResult(){ } - } -} diff --git a/src/Servers/Chat/src/Contract/Result/General/CryptResult.cs b/src/Servers/Chat/src/Contract/Result/General/CryptResult.cs deleted file mode 100755 index 3d2556fca..000000000 --- a/src/Servers/Chat/src/Contract/Result/General/CryptResult.cs +++ /dev/null @@ -1,9 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - -namespace UniSpy.Server.Chat.Contract.Result.General -{ - public sealed class CryptResult : ResultBase - { - public CryptResult(){ } - } -} diff --git a/src/Servers/Chat/src/Contract/Result/General/GetKeyResult.cs b/src/Servers/Chat/src/Contract/Result/General/GetKeyResult.cs deleted file mode 100755 index 87b4faad3..000000000 --- a/src/Servers/Chat/src/Contract/Result/General/GetKeyResult.cs +++ /dev/null @@ -1,18 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using System.Collections.Generic; - -namespace UniSpy.Server.Chat.Contract.Result.General -{ - public sealed class GetKeyResult : ResultBase - { - public List Values { get; } - /// - /// The reciever's nick name - /// - public string NickName { get; set; } - public GetKeyResult() - { - Values = new List(); - } - } -} diff --git a/src/Servers/Chat/src/Contract/Result/General/ListResult.cs b/src/Servers/Chat/src/Contract/Result/General/ListResult.cs deleted file mode 100755 index ac50acd5b..000000000 --- a/src/Servers/Chat/src/Contract/Result/General/ListResult.cs +++ /dev/null @@ -1,22 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using System.Collections.Generic; - -namespace UniSpy.Server.Chat.Contract.Result.General -{ - public sealed class ListDataModel - { - public string ChannelName { get; set; } - public int TotalChannelUsers { get; set; } - public string ChannelTopic { get; set; } - } - - public sealed class ListResult : ResultBase - { - public string UserIRCPrefix { get; set; } - public List ChannelInfoList { get; } - public ListResult() - { - ChannelInfoList = new List(); - } - } -} diff --git a/src/Servers/Chat/src/Contract/Result/General/LoginResult.cs b/src/Servers/Chat/src/Contract/Result/General/LoginResult.cs deleted file mode 100755 index c5649c8ad..000000000 --- a/src/Servers/Chat/src/Contract/Result/General/LoginResult.cs +++ /dev/null @@ -1,11 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - -namespace UniSpy.Server.Chat.Contract.Result.General -{ - public sealed class LoginResult : ResultBase - { - public int ProfileId { get; set; } - public int UserID { get; set; } - public LoginResult() { } - } -} diff --git a/src/Servers/Chat/src/Contract/Result/General/PingResult.cs b/src/Servers/Chat/src/Contract/Result/General/PingResult.cs deleted file mode 100755 index b37b798cb..000000000 --- a/src/Servers/Chat/src/Contract/Result/General/PingResult.cs +++ /dev/null @@ -1,11 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; - -namespace UniSpy.Server.Chat.Contract.Result.General -{ - public sealed class PingResult : ResultBase - { - public string RequesterIRCPrefix { get; set; } - public PingResult() - { } - } -} diff --git a/src/Servers/Chat/src/Contract/Result/General/QuitResult.cs b/src/Servers/Chat/src/Contract/Result/General/QuitResult.cs deleted file mode 100755 index 74a235489..000000000 --- a/src/Servers/Chat/src/Contract/Result/General/QuitResult.cs +++ /dev/null @@ -1,26 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using System.Collections.Generic; - -namespace UniSpy.Server.Chat.Contract.Result.General -{ - public sealed record QuitDataModel - { - public string ChannelName { get; set; } - public bool IsPeerServer { get; set; } - public bool IsChannelCreator { get; set; } - public string LeaveReplySendingBuffer { get; set; } - public string KickReplySendingBuffer { get; set; } - } - - public sealed class QuitResult : ResultBase - { - public string QuiterPrefix { get; set; } - public List ChannelInfos { get; } - public string Message { get; set; } - - public QuitResult() - { - ChannelInfos = new List(); - } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Contract/Result/General/UserIPResult.cs b/src/Servers/Chat/src/Contract/Result/General/UserIPResult.cs deleted file mode 100755 index e041b84af..000000000 --- a/src/Servers/Chat/src/Contract/Result/General/UserIPResult.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Net; -using UniSpy.Server.Chat.Abstraction.BaseClass; - -namespace UniSpy.Server.Chat.Contract.Result.General -{ - public sealed class UserIPResult : ResultBase - { - public IPAddress RemoteIPAddress { get; set; } - public UserIPResult(){ } - } -} diff --git a/src/Servers/Chat/src/Contract/Result/General/WhoIsResult.cs b/src/Servers/Chat/src/Contract/Result/General/WhoIsResult.cs deleted file mode 100755 index fa67a6eba..000000000 --- a/src/Servers/Chat/src/Contract/Result/General/WhoIsResult.cs +++ /dev/null @@ -1,18 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using System.Collections.Generic; - -namespace UniSpy.Server.Chat.Contract.Result.General -{ - public sealed class WhoIsResult : ResultBase - { - public List JoinedChannelName { get; } - public string NickName { get; set; } - public string UserName { get; set; } - public string Name { get; set; } - public string PublicIPAddress { get; set; } - public WhoIsResult() - { - JoinedChannelName = new List(); - } - } -} diff --git a/src/Servers/Chat/src/Contract/Result/General/WhoResult.cs b/src/Servers/Chat/src/Contract/Result/General/WhoResult.cs deleted file mode 100755 index 926d0acae..000000000 --- a/src/Servers/Chat/src/Contract/Result/General/WhoResult.cs +++ /dev/null @@ -1,22 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using System.Collections.Generic; - -namespace UniSpy.Server.Chat.Contract.Result.General -{ - public sealed class WhoDataModel - { - public string ChannelName { get; set; } - public string UserName { get; set; } - public string PublicIPAddress { get; set; } - public string NickName { get; set; } - public string Modes { get; set; } - } - public sealed class WhoResult : ResultBase - { - public List DataModels { get; } - public WhoResult() - { - DataModels = new List(); - } - } -} diff --git a/src/Servers/Chat/src/Contract/Result/Message/AtmResult.cs b/src/Servers/Chat/src/Contract/Result/Message/AtmResult.cs deleted file mode 100755 index 5e18158e2..000000000 --- a/src/Servers/Chat/src/Contract/Result/Message/AtmResult.cs +++ /dev/null @@ -1,9 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass.Message; - -namespace UniSpy.Server.Chat.Contract.Result.Message -{ - public sealed class AtmResult : MessageResultBase - { - public AtmResult(){ } - } -} diff --git a/src/Servers/Chat/src/Contract/Result/Message/NoticeResult.cs b/src/Servers/Chat/src/Contract/Result/Message/NoticeResult.cs deleted file mode 100755 index e20cab2c1..000000000 --- a/src/Servers/Chat/src/Contract/Result/Message/NoticeResult.cs +++ /dev/null @@ -1,9 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass.Message; - -namespace UniSpy.Server.Chat.Contract.Result.Message -{ - public sealed class NoticeResult : MessageResultBase - { - public NoticeResult(){ } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Contract/Result/Message/PrivateResult.cs b/src/Servers/Chat/src/Contract/Result/Message/PrivateResult.cs deleted file mode 100755 index f6432330d..000000000 --- a/src/Servers/Chat/src/Contract/Result/Message/PrivateResult.cs +++ /dev/null @@ -1,10 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass.Message; - -namespace UniSpy.Server.Chat.Contract.Result.Message -{ - public sealed class PrivateResult : MessageResultBase - { - public bool IsBroadcastMessage { get; set; } - public PrivateResult(){ } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Contract/Result/Message/UtmResult.cs b/src/Servers/Chat/src/Contract/Result/Message/UtmResult.cs deleted file mode 100755 index 3a0df9044..000000000 --- a/src/Servers/Chat/src/Contract/Result/Message/UtmResult.cs +++ /dev/null @@ -1,9 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass.Message; - -namespace UniSpy.Server.Chat.Contract.Result.Message -{ - public sealed class UtmResult : MessageResultBase - { - public UtmResult(){ } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Dockerfile b/src/Servers/Chat/src/Dockerfile deleted file mode 100755 index 311578d34..000000000 --- a/src/Servers/Chat/src/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM mcr.microsoft.com/dotnet/runtime:6.0 AS base -WORKDIR /app -EXPOSE 6667 - -FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build -WORKDIR /src -COPY ["src/Servers/Chat/src/UniSpy.Server.Chat.csproj", "src/Servers/Chat/src/"] -COPY ["src/Libraries/Core/src/UniSpy.Server.Core.csproj", "src/Libraries/Core/src/"] -COPY ["src/Servers/QueryReport/src/UniSpy.Server.QueryReport.csproj", "src/Servers/QueryReport/src/"] -RUN dotnet restore "src/Servers/Chat/src/UniSpy.Server.Chat.csproj" -COPY . . -WORKDIR "/src/src/Servers/Chat/src" -RUN dotnet build "UniSpy.Server.Chat.csproj" -c Release -o /app/build - -FROM build AS publish -RUN dotnet publish "UniSpy.Server.Chat.csproj" -c Release -o /app/publish - -FROM base AS final -WORKDIR /app -COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "UniSpy.Server.Chat.dll"] \ No newline at end of file diff --git a/src/Servers/Chat/src/Enumerate/ChatChannelMode.cs b/src/Servers/Chat/src/Enumerate/ChatChannelMode.cs deleted file mode 100755 index 0ea13a575..000000000 --- a/src/Servers/Chat/src/Enumerate/ChatChannelMode.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace UniSpy.Server.Chat.Enumerate -{ - public enum ChatChannelMode - { - InviteOnly, - Private, - Secret, - Moderated, - NoExternalMessages, - OnlyOpsChangeTopic, - OpsObeyChannelLimit, - } -} diff --git a/src/Servers/Chat/src/Enumerate/ChatMode.cs b/src/Servers/Chat/src/Enumerate/ChatMode.cs deleted file mode 100755 index fafb1073b..000000000 --- a/src/Servers/Chat/src/Enumerate/ChatMode.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace UniSpy.Server.Chat.Enumerate -{ - public enum ChatMode : int - { - End = 0, - Ban = 1, - InviteOnly = 2, - Limit = 3, - Private = 4, - Secret = 5, - Key = 6, - ModeRated = 7, - NoExternalMessages = 8, - OlnyOPSChangeTopic = 9, - OP = 10, - Voice = 11, - UsersHidden = 12, - ReceiveWallOPS = 13, - OPSObeyChannelLimit = 14, - } -} diff --git a/src/Servers/Chat/src/Enumerate/Request/ChatRequest.cs b/src/Servers/Chat/src/Enumerate/Request/ChatRequest.cs deleted file mode 100755 index e9e3b3266..000000000 --- a/src/Servers/Chat/src/Enumerate/Request/ChatRequest.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace UniSpy.Server.Chat.Enumerate.Request -{ - public enum ChatRequestType - { - CRYPT, - USRIP, - NICK, - USER, - LOGINPREAUTH, - LOGIN, - REGISTERNICK, - QUIT, - MODE, - CDKEY, - LIST, - LISTLIMIT, - JOIN, - PART, - PRIVMSG, - NOTICE, - UTM, - ATM, - TOPIC, - SETGROUP, - NAMES, - WHOIS, - WHO, - INVITE, - KICK, - GETUDPRELAY, - SETCHANKEY, - SETCKEY, - SETKEY, - PONG, - } -} diff --git a/src/Servers/Chat/src/Enumerate/Request/ChatServerMessage.cs b/src/Servers/Chat/src/Enumerate/Request/ChatServerMessage.cs deleted file mode 100755 index bb5569cac..000000000 --- a/src/Servers/Chat/src/Enumerate/Request/ChatServerMessage.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace UniSpy.Server.Chat.Enumerate -{ - public enum ChatServerMessage - { - PRIVMSG, - NOTICE, - UTM, - ATM, - PING, - NICK, - JOIN, - PART, - KICK, - QUIT, - KILL, - TOPIC, - MODE, - ERROR, - INVITE - } -} diff --git a/src/Servers/Chat/src/Enumerate/Response/ChatErrorCode.cs b/src/Servers/Chat/src/Enumerate/Response/ChatErrorCode.cs deleted file mode 100755 index fc2583860..000000000 --- a/src/Servers/Chat/src/Enumerate/Response/ChatErrorCode.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace UniSpy.Server.Chat.Enumerate -{ - public enum ChatErrorCode - { - Parse, - DataOperation, - ConstructResponse, - NotChannelOperator, - UserAlreadyInChannel, - UnSupportedGame, - NoError, - IRCError, - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Exception/Exception.cs b/src/Servers/Chat/src/Exception/Exception.cs deleted file mode 100755 index e7cfc0cda..000000000 --- a/src/Servers/Chat/src/Exception/Exception.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace UniSpy.Server.Chat -{ - public class Exception : UniSpy.Exception - { - public Exception() { } - - public Exception(string message) : base(message) { } - - public Exception(string message, System.Exception innerException) : base(message, innerException) { } - } - - public class HandleLaterException : Exception - { - public HandleLaterException(string message) : base(message) { } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Exception/IRC/Channel/BadChanMaskException.cs b/src/Servers/Chat/src/Exception/IRC/Channel/BadChanMaskException.cs deleted file mode 100755 index 9e9037153..000000000 --- a/src/Servers/Chat/src/Exception/IRC/Channel/BadChanMaskException.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.Chat.Aggregate.Misc; - -namespace UniSpy.Server.Chat.Error.IRC.Channel -{ - public sealed class BadChanMaskException : IRCChannelException - { - public BadChanMaskException(){ } - - public BadChanMaskException(string message, string channelName) : base(message, IRCErrorCode.BadChanMask, channelName){ } - - public BadChanMaskException(string message, string channelName, System.Exception innerException) : base(message, IRCErrorCode.BadChanMask, channelName, innerException){ } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Exception/IRC/Channel/BadChannelKeyException.cs b/src/Servers/Chat/src/Exception/IRC/Channel/BadChannelKeyException.cs deleted file mode 100755 index 7864eaf87..000000000 --- a/src/Servers/Chat/src/Exception/IRC/Channel/BadChannelKeyException.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.Chat.Aggregate.Misc; - -namespace UniSpy.Server.Chat.Error.IRC.Channel -{ - public sealed class BadChannelKeyException : IRCChannelException - { - public BadChannelKeyException(){ } - - public BadChannelKeyException(string message, string channelName) : base(message, IRCErrorCode.BadChannelKey, channelName){ } - - public BadChannelKeyException(string message, string channelName, System.Exception innerException) : base(message, IRCErrorCode.BadChannelKey, channelName, innerException){ } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Exception/IRC/Channel/BannedFromChanException.cs b/src/Servers/Chat/src/Exception/IRC/Channel/BannedFromChanException.cs deleted file mode 100755 index dd56eca63..000000000 --- a/src/Servers/Chat/src/Exception/IRC/Channel/BannedFromChanException.cs +++ /dev/null @@ -1,11 +0,0 @@ -using UniSpy.Server.Chat.Aggregate.Misc; - -namespace UniSpy.Server.Chat.Error.IRC.Channel -{ - public sealed class BannedFromChanException : IRCChannelException - { - public BannedFromChanException(string message, string channelName) : base(message, IRCErrorCode.BannedFromChan, channelName){ } - - public BannedFromChanException(string message, string channelName, System.Exception innerException) : base(message, IRCErrorCode.BannedFromChan, channelName, innerException){ } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Exception/IRC/Channel/ChannelIsFullException.cs b/src/Servers/Chat/src/Exception/IRC/Channel/ChannelIsFullException.cs deleted file mode 100755 index d7a6eaf6f..000000000 --- a/src/Servers/Chat/src/Exception/IRC/Channel/ChannelIsFullException.cs +++ /dev/null @@ -1,11 +0,0 @@ -using UniSpy.Server.Chat.Aggregate.Misc; - -namespace UniSpy.Server.Chat.Error.IRC.Channel -{ - public sealed class ChannelIsFullException : IRCChannelException - { - public ChannelIsFullException(string message, string channelName) : base(message, IRCErrorCode.ChannelIsFull, channelName){ } - - public ChannelIsFullException(string message, string channelName, System.Exception innerException) : base(message, IRCErrorCode.ChannelIsFull, channelName, innerException){ } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Exception/IRC/Channel/InviteOnlyChanException.cs b/src/Servers/Chat/src/Exception/IRC/Channel/InviteOnlyChanException.cs deleted file mode 100755 index 7dec4bcce..000000000 --- a/src/Servers/Chat/src/Exception/IRC/Channel/InviteOnlyChanException.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.Chat.Aggregate.Misc; - -namespace UniSpy.Server.Chat.Error.IRC.Channel -{ - public sealed class InviteOnlyChanException : IRCChannelException - { - public InviteOnlyChanException(){ } - - public InviteOnlyChanException(string message, string channelName) : base(message, IRCErrorCode.InviteOnlyChan, channelName){ } - - public InviteOnlyChanException(string message, string channelName, System.Exception innerException) : base(message, IRCErrorCode.InviteOnlyChan, channelName, innerException){ } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Exception/IRC/Channel/NoSuchChannelException.cs b/src/Servers/Chat/src/Exception/IRC/Channel/NoSuchChannelException.cs deleted file mode 100755 index 8a65b203d..000000000 --- a/src/Servers/Chat/src/Exception/IRC/Channel/NoSuchChannelException.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.Chat.Aggregate.Misc; - -namespace UniSpy.Server.Chat.Error.IRC.Channel -{ - public sealed class NoSuchChannelException : IRCChannelException - { - public NoSuchChannelException(){ } - - public NoSuchChannelException(string message, string channelName) : base(message, IRCErrorCode.NoSuchChannel, channelName){ } - - public NoSuchChannelException(string message, string channelName, System.Exception innerException) : base(message, IRCErrorCode.NoSuchChannel, channelName, innerException){ } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Exception/IRC/General/ErrOneUSNickNameException.cs b/src/Servers/Chat/src/Exception/IRC/General/ErrOneUSNickNameException.cs deleted file mode 100755 index 70367b383..000000000 --- a/src/Servers/Chat/src/Exception/IRC/General/ErrOneUSNickNameException.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.Chat.Aggregate.Misc; - -namespace UniSpy.Server.Chat.Error.IRC.General -{ - public sealed class ErrOneUSNickNameException : IRCException - { - public ErrOneUSNickNameException(){ } - - public ErrOneUSNickNameException(string message) : base(message, IRCErrorCode.ErrOneUSNickName){ } - - public ErrOneUSNickNameException(string message, System.Exception innerException) : base(message, IRCErrorCode.ErrOneUSNickName, innerException){ } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Exception/IRC/General/LoginFailedException.cs b/src/Servers/Chat/src/Exception/IRC/General/LoginFailedException.cs deleted file mode 100755 index a38a4f98c..000000000 --- a/src/Servers/Chat/src/Exception/IRC/General/LoginFailedException.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.Chat.Aggregate.Misc; - -namespace UniSpy.Server.Chat.Error.IRC.General -{ - public sealed class LoginFailedException : IRCException - { - public LoginFailedException(){ } - - public LoginFailedException(string message) : base(message, IRCErrorCode.LoginFailed){ } - - public LoginFailedException(string message, System.Exception innerException) : base(message, IRCErrorCode.LoginFailed, innerException){ } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Exception/IRC/General/MoreParametersException.cs b/src/Servers/Chat/src/Exception/IRC/General/MoreParametersException.cs deleted file mode 100755 index f7eb151a0..000000000 --- a/src/Servers/Chat/src/Exception/IRC/General/MoreParametersException.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.Chat.Aggregate.Misc; - -namespace UniSpy.Server.Chat.Error.IRC.General -{ - public sealed class MoreParametersException : IRCException - { - public MoreParametersException(){ } - - public MoreParametersException(string message) : base(message, IRCErrorCode.MoreParameters){ } - - public MoreParametersException(string message, System.Exception innerException) : base(message, IRCErrorCode.MoreParameters, innerException){ } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Exception/IRC/General/NickNameInUseException.cs b/src/Servers/Chat/src/Exception/IRC/General/NickNameInUseException.cs deleted file mode 100755 index 2a0315443..000000000 --- a/src/Servers/Chat/src/Exception/IRC/General/NickNameInUseException.cs +++ /dev/null @@ -1,28 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; - -namespace UniSpy.Server.Chat.Error.IRC.General -{ - public sealed class NickNameInUseException : IRCException - { - private string _oldNickName; - private string _newNickName; - public NickNameInUseException() { } - - public NickNameInUseException(string message, string oldNick, string newNick) : base(message, IRCErrorCode.NickNameInUse) - { - _oldNickName = oldNick; - _newNickName = newNick; - } - - public NickNameInUseException(string message, string oldNick, string newNick, System.Exception innerException) : base(message, IRCErrorCode.NickNameInUse, innerException) - { - _oldNickName = oldNick; - _newNickName = newNick; - } - public override void Build() - { - SendingBuffer = $":{ResponseBase.ServerDomain} {IRCErrorCode.NickNameInUse} {_oldNickName} {_newNickName} *\r\n"; - } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Exception/IRC/General/NoSuchNickException.cs b/src/Servers/Chat/src/Exception/IRC/General/NoSuchNickException.cs deleted file mode 100755 index dc17ce106..000000000 --- a/src/Servers/Chat/src/Exception/IRC/General/NoSuchNickException.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.Chat.Aggregate.Misc; - -namespace UniSpy.Server.Chat.Error.IRC.General -{ - public sealed class NoSuchNickException : IRCException - { - public NoSuchNickException(){ } - - public NoSuchNickException(string message) : base(message, IRCErrorCode.NoSuchNick){ } - - public NoSuchNickException(string message, System.Exception innerException) : base(message, IRCErrorCode.NoSuchNick, innerException){ } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Exception/IRC/General/NoUniqueNickException.cs b/src/Servers/Chat/src/Exception/IRC/General/NoUniqueNickException.cs deleted file mode 100755 index 05f5c705f..000000000 --- a/src/Servers/Chat/src/Exception/IRC/General/NoUniqueNickException.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.Chat.Aggregate.Misc; - -namespace UniSpy.Server.Chat.Error.IRC.General -{ - public sealed class NoUniqueNickException : IRCException - { - public NoUniqueNickException(){ } - - public NoUniqueNickException(string message) : base(message, IRCErrorCode.NoUniqueNick){ } - - public NoUniqueNickException(string message, System.Exception innerException) : base(message, IRCErrorCode.NoUniqueNick, innerException){ } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Exception/IRC/General/RegisterNickFaildException.cs b/src/Servers/Chat/src/Exception/IRC/General/RegisterNickFaildException.cs deleted file mode 100755 index f4b101960..000000000 --- a/src/Servers/Chat/src/Exception/IRC/General/RegisterNickFaildException.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.Chat.Aggregate.Misc; - -namespace UniSpy.Server.Chat.Error.IRC.General -{ - public sealed class RegisterNickFaildException : IRCException - { - public RegisterNickFaildException(){ } - - public RegisterNickFaildException(string message) : base(message, IRCErrorCode.RegisterNickFailed){ } - - public RegisterNickFaildException(string message, System.Exception innerException) : base(message, IRCErrorCode.RegisterNickFailed, innerException){ } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Exception/IRC/General/TooManyChannels.cs b/src/Servers/Chat/src/Exception/IRC/General/TooManyChannels.cs deleted file mode 100755 index 389e49c2c..000000000 --- a/src/Servers/Chat/src/Exception/IRC/General/TooManyChannels.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.Chat.Aggregate.Misc; -namespace UniSpy.Server.Chat.Error.IRC.General -{ - public sealed class TooManyChannels : IRCException - { - public TooManyChannels(){ } - - public TooManyChannels(string message) : base(message, IRCErrorCode.TooManyChannels){ } - - public TooManyChannels(string message, System.Exception innerException) : base(message, IRCErrorCode.TooManyChannels, innerException){ } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Exception/IRC/General/UniqueNickExpiredException.cs b/src/Servers/Chat/src/Exception/IRC/General/UniqueNickExpiredException.cs deleted file mode 100755 index 50db8524e..000000000 --- a/src/Servers/Chat/src/Exception/IRC/General/UniqueNickExpiredException.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.Chat.Aggregate.Misc; - -namespace UniSpy.Server.Chat.Error.IRC.General -{ - public sealed class UniqueNickExpiredException : IRCException - { - public UniqueNickExpiredException(){ } - - public UniqueNickExpiredException(string message) : base(message, IRCErrorCode.UniqueNIickExpired){ } - - public UniqueNickExpiredException(string message, System.Exception innerException) : base(message, IRCErrorCode.UniqueNIickExpired, innerException){ } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Exception/IRCChannelException.cs b/src/Servers/Chat/src/Exception/IRCChannelException.cs deleted file mode 100755 index d1cc9bb00..000000000 --- a/src/Servers/Chat/src/Exception/IRCChannelException.cs +++ /dev/null @@ -1,23 +0,0 @@ -using UniSpy.Server.Chat.Error.IRC.General; -using UniSpy.Server.Chat.Abstraction.BaseClass; - -namespace UniSpy.Server.Chat -{ - public class IRCChannelException : IRCException - { - public string ChannelName { get; private set; } - public IRCChannelException() { } - public IRCChannelException(string message, string errorCode, string channelName) : base(message, errorCode) - { - ChannelName = channelName; - } - public IRCChannelException(string message, string errorCode, string channelName, System.Exception innerException) : base(message, errorCode, innerException) - { - ChannelName = channelName; - } - public override void Build() - { - SendingBuffer = $":{ResponseBase.ServerDomain} {ErrorCode} * {ChannelName} :{Message}\r\n"; - } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Exception/IRCException.cs b/src/Servers/Chat/src/Exception/IRCException.cs deleted file mode 100755 index efdd20da9..000000000 --- a/src/Servers/Chat/src/Exception/IRCException.cs +++ /dev/null @@ -1,27 +0,0 @@ -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.Chat.Error.IRC.General -{ - public class IRCException : UniSpy.Exception, IResponse - { - public string ErrorCode { get; private set; } - public object SendingBuffer { get; protected set; } - - public IRCException() { } - - public IRCException(string message, string errorCode) : base(message) - { - ErrorCode = errorCode; - } - - public IRCException(string message, string errorCode, System.Exception innerException) : base(message, innerException) - { - ErrorCode = errorCode; - } - - public virtual void Build() - { - SendingBuffer = $":{Abstraction.BaseClass.ResponseBase.ServerDomain} {ErrorCode}\r\n"; - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/Channel/GetCKeyHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/Channel/GetCKeyHandler.cs deleted file mode 100755 index abe454d03..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/Channel/GetCKeyHandler.cs +++ /dev/null @@ -1,100 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Error.IRC.General; -using UniSpy.Server.Chat.Aggregate; -using UniSpy.Server.Chat.Contract.Request.Channel; -using UniSpy.Server.Chat.Contract.Response.Channel; -using UniSpy.Server.Chat.Contract.Result.Channel; -using System; -using UniSpy.Server.Chat.Abstraction.Interface; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.Channel -{ - - public sealed class GetCKeyHandler : ChannelHandlerBase - { - private new GetCKeyRequest _request => (GetCKeyRequest)base._request; - private new GetCKeyResult _result { get => (GetCKeyResult)base._result; set => base._result = value; } - private TimeSpan _waitingTime = TimeSpan.FromSeconds(10); - public GetCKeyHandler(IChatClient client, GetCKeyRequest request) : base(client, request) - { - _result = new GetCKeyResult(); - } - - - protected override void DataOperation() - { - switch (_request.RequestType) - { - case GetKeyReqeustType.GetChannelAllUserKeyValue: - GetChannelAllUserKeyValue(); - break; - case GetKeyReqeustType.GetChannelSpecificUserKeyValue: - GetChannelSpecificUserKeyValue(); - break; - } - } - - private void GetChannelAllUserKeyValue() - { - foreach (var user in _channel.Users.Values) - { - GetUserKeyValue(user); - } - } - - private void GetChannelSpecificUserKeyValue() - { - var user = _channel.GetUser(_request.NickName); - if (user is null) - { - throw new NoSuchNickException($"Can not find user with nickname:{_request.NickName} in channels."); - } - GetUserKeyValue(user); - } - - private void GetUserKeyValue(ChannelUser user) - { - // if (user.BelongedChannel.RoomType == Aggregate.PeerRoomType.Staging) - // { - // WaittingForKey(user); - // } - // we get user's values - string userValues = user.KeyValues.GetValueString(_request.Keys); - var model = new GetCKeyDataModel - { - NickName = user.Info.NickName, - UserValues = userValues - }; - _result.DataResults.Add(model); - } - - protected override void ResponseConstruct() - { - _response = new GetCKeyResponse(_request, _result); - } - - private void WaittingForKey(ChannelUser user) - { - // if user did not contains all key and value we wait for it - var startTime = DateTime.Now; - var elapsed = DateTime.Now - startTime; - while (elapsed < _waitingTime) - { - if (!user.KeyValues.IsContainAllKey(_request.Keys)) - { - elapsed = DateTime.Now - startTime; - // each detection we wait for 5 seconds. - System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(5)); - } - else - { - break; - } - } - if (elapsed > _waitingTime) - { - throw new Chat.Exception($"No key value presents after waitting for user:{_request.NickName} channel:{_request.ChannelName}"); - } - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/Channel/GetChannelKeyHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/Channel/GetChannelKeyHandler.cs deleted file mode 100755 index 3eeb4ed4d..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/Channel/GetChannelKeyHandler.cs +++ /dev/null @@ -1,36 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Contract.Request.Channel; -using UniSpy.Server.Chat.Contract.Response.Channel; -using UniSpy.Server.Chat.Contract.Result.Channel; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.Channel -{ - // Sets channel key/values. - // If user is NULL or "", the keys will be set on the channel. - // Otherwise, they will be set on the user, - // Only ops can set channel keys on other users. - // Set a value to NULL or "" to clear that key. - - public sealed class GetChannelKeyHandler : ChannelHandlerBase - { - private new GetChannelKeyRequest _request => (GetChannelKeyRequest)base._request; - private new GetChannelKeyResult _result { get => (GetChannelKeyResult)base._result; set => base._result = value; } - public GetChannelKeyHandler(IChatClient client, GetChannelKeyRequest request) : base(client, request) - { - _result = new GetChannelKeyResult(); - } - - protected override void DataOperation() - { - _result.ChannelUserIRCPrefix = _user.Info.IRCPrefix; - _result.Values = _channel.KeyValues.GetValueString(_request.Keys); - _result.ChannelName = _channel.Name; - } - - protected override void ResponseConstruct() - { - _response = new GetChannelKeyResponse(_request, _result); - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/Channel/JoinHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/Channel/JoinHandler.cs deleted file mode 100755 index 811877f6d..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/Channel/JoinHandler.cs +++ /dev/null @@ -1,132 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Error.IRC.General; -using UniSpy.Server.Chat.Aggregate; -using UniSpy.Server.Chat.Contract.Request.Channel; -using UniSpy.Server.Chat.Contract.Request.General; -using UniSpy.Server.Chat.Contract.Response.Channel; -using UniSpy.Server.Chat.Contract.Result.Channel; -using UniSpy.Server.Chat.Aggregate.Redis; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Error.IRC.Channel; -using UniSpy.Server.QueryReport.Aggregate.Redis.Channel; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.Channel -{ - /// - /// Game will only join one channel at one time - /// - - public sealed class JoinHandler : LogedInHandlerBase - { - private new JoinRequest _request => (JoinRequest)base._request; - private new JoinResult _result { get => (JoinResult)base._result; set => base._result = value; } - private new JoinResponse _response { get => (JoinResponse)base._response; set => base._response = value; } - private static readonly GeneralMessageChannel GeneralMessageChannel = new GeneralMessageChannel(); - private Aggregate.Channel _channel; - private ChannelUser _user; - public JoinHandler(IChatClient client, JoinRequest request) : base(client, request) - { - _result = new JoinResult(); - } - - //1.筛选出所要加入的频道,如果不存在则创建(select the channel that user want to join, if channel does not exist creating it) - //2.检查用户名nickname是否已经在频道中存在(check if user's nickname existed in channel) - //若存在则提醒用户名字冲突 - //不存在则加入频道 - //广播加入信息 - //发送频道模式给此用户 - //发送频道用户列表给此用户 - protected override void RequestCheck() - { - // we handle this when get user nickname - if (!_client.Info.IsNickNameSet) - { - lock (_client.Info.HandlerStack) - { - _client.Info.HandlerStack.Add(this); - } - throw new Chat.HandleLaterException($"{this.GetType().Name} is saved until nickname is set."); - } - base.RequestCheck(); - //some GameSpy game only allow one player join one chat room - //but GameSpy Arcade can join more than one channel - if (_client.Info.JoinedChannels.Count > 3) - { - throw new TooManyChannels($"{_client.Info.NickName} is join too many channels"); - } - if (_client.Info.GameName == null) - { - throw new NoSuchChannelException("Game name is required for join a channel", _request.ChannelName); - } - } - - protected override void DataOperation() - { - lock (ChannelManager.Channels) - { - var isChannelExistOnLocal = ChannelManager.IsChannelExist(_request.ChannelName); - if (isChannelExistOnLocal) - { - _channel = ChannelManager.GetChannel(_request.ChannelName); - _user = _channel.AddUser(_client, _request.Password ?? null); - } - else - { - // create channel - _channel = ChannelManager.CreateChannel(_request.ChannelName, _request.Password ?? null, _client); - // we need to check whether this channel is gamespy official channel - switch (_channel.RoomType) - { - case PeerRoomType.Title: - case PeerRoomType.Staging: - case PeerRoomType.Group: - _user = _channel.AddUser(_client, _request.Password ?? null); - break; - case PeerRoomType.Normal: - _user = _channel.AddUser(_client, _request.Password ?? null, true, true); - break; - } - } - Aggregate.Channel.UpdateChannelCache(_user); - // Aggregate.Channel.UpdatePeerRoomInfo(_user); - } - _result.AllChannelUserNicks = _channel.GetAllUsersNickString(); - _result.JoinerNickName = _client.Info.NickName; - _result.ChannelModes = _channel.Mode.ToString(); - _result.JoinerPrefix = _client.Info.IRCPrefix; - } - - protected override void ResponseConstruct() - { - _response = new JoinResponse(_request, _result); - } - - protected override void Response() - { - // base.Response(); - if (_response is null) - { - return; - } - - //first we send join information to all user in this channel - _channel.MultiCast(_client, _response); - - var namesRequest = new NamesRequest - { - ChannelName = _request.ChannelName - }; - new NamesHandler(_client, namesRequest).Handle(); - - var userModeRequest = new ModeRequest - { - RequestType = ModeRequestType.GetChannelAndUserModes, - ChannelName = _request.ChannelName, - NickName = _user.Info.NickName, - UserName = _user.Info.UserName, - Password = _request.Password is null ? null : _request.Password - }; - new ModeHandler(_client, userModeRequest).Handle(); - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/Channel/KickHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/Channel/KickHandler.cs deleted file mode 100755 index d7576c003..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/Channel/KickHandler.cs +++ /dev/null @@ -1,56 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Aggregate; -using UniSpy.Server.Chat.Contract.Request.Channel; -using UniSpy.Server.Chat.Contract.Response.Channel; -using UniSpy.Server.Chat.Contract.Result.Channel; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.Channel -{ - - public sealed class KickHandler : ChannelHandlerBase - { - private new KickRequest _request => (KickRequest)base._request; - private new KickResponse _response { get => (KickResponse)base._response; set => base._response = value; } - private new KickResult _result { get => (KickResult)base._result; set => base._result = value; } - private ChannelUser _kickee; - public KickHandler(IChatClient client, KickRequest request) : base(client, request) - { - _result = new KickResult(); - } - - protected override void RequestCheck() - { - base.RequestCheck(); - - if (!_user.IsChannelOperator) - { - throw new Chat.Exception("The Kick operation failed, because you are not channel operator."); - } - _kickee = _channel.GetUser(_request.KickeeNickName); - if (_kickee is null) - { - throw new Chat.Exception($"Can not find kickee:{_request.KickeeNickName} in channel."); - } - } - protected override void DataOperation() - { - _result.ChannelName = _channel.Name; - _result.KickerNickName = _client.Info.NickName; - _result.KickerIRCPrefix = _client.Info.IRCPrefix; - _result.KickeeNickName = _kickee.Info.NickName; - } - protected override void ResponseConstruct() - { - _response = new KickResponse(_request, _result); - } - - protected override void Response() - { - _channel.MultiCast(_client, _response); - _channel.RemoveUser(_kickee); - Aggregate.Channel.UpdateChannelCache(_user); - // Aggregate.Channel.UpdatePeerRoomInfo(_user); - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/Channel/ModeHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/Channel/ModeHandler.cs deleted file mode 100755 index bde72edfd..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/Channel/ModeHandler.cs +++ /dev/null @@ -1,51 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Contract.Request.Channel; -using UniSpy.Server.Chat.Contract.Response.Channel; -using UniSpy.Server.Chat.Contract.Result.Channel; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.Channel -{ - /// - /// Get or set channel or user mode - /// - - public sealed class ModeHandler : ChannelHandlerBase - { - private new ModeRequest _request => (ModeRequest)base._request; - private new ModeResult _result { get => (ModeResult)base._result; set => base._result = value; } - public ModeHandler(IChatClient client, ModeRequest request) : base(client, request) { } - protected override void DataOperation() - { - _result = new ModeResult(); - switch (_request.RequestType) - { - // We get user nick name then get channel modes - case ModeRequestType.GetChannelAndUserModes: - _result.JoinerNickName = _request.NickName; - goto case ModeRequestType.GetChannelModes; - case ModeRequestType.GetChannelModes: - _result.ChannelModes = _channel.Mode.ToString(); - _result.ChannelName = _channel.Name; - break; - case ModeRequestType.SetChannelModes: - _channel.SetProperties(_user, _request); - break; - } - } - - protected override void ResponseConstruct() - { - // we only response to get channel modes - switch (_request.RequestType) - { - case ModeRequestType.GetChannelAndUserModes: - case ModeRequestType.GetChannelModes: - _response = new ModeResponse(_request, _result); - break; - case ModeRequestType.SetChannelModes: - break; - } - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/Channel/NamesHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/Channel/NamesHandler.cs deleted file mode 100755 index df9410bdc..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/Channel/NamesHandler.cs +++ /dev/null @@ -1,47 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Error.IRC.Channel; -using UniSpy.Server.Chat.Error.IRC.General; -using UniSpy.Server.Chat.Contract.Request.General; -using UniSpy.Server.Chat.Contract.Response.Channel; -using UniSpy.Server.Chat.Contract.Result.Channel; -using UniSpy.Server.Chat.Abstraction.Interface; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.Channel -{ - - public sealed class NamesHandler : ChannelHandlerBase - { - private new NamesRequest _request => (NamesRequest)base._request; - private new NamesResult _result { get => (NamesResult)base._result; set => base._result = value; } - public NamesHandler(IChatClient client, NamesRequest request) : base(client, request) { } - protected override void RequestCheck() - { - if (_request.RawRequest is null) - { - _channel = _client.Info.GetJoinedChannel(_request.ChannelName); - if (_channel is null) - { - throw new NoSuchChannelException($"No such channel {_request.ChannelName}", _request.ChannelName); - } - _user = _channel.GetUser(_client); - if (_user is null) - { - throw new NoSuchNickException($"Can not find user with nickname: {_client.Info.NickName} username: {_client.Info.UserName}"); - } - return; - } - base.RequestCheck(); - } - protected override void DataOperation() - { - _result = new NamesResult(); - _result.AllChannelUserNicks = _channel.GetAllUsersNickString(); - _result.ChannelName = _channel.Name; - _result.RequesterNickName = _user.Info.NickName; - } - protected override void ResponseConstruct() - { - _response = new NamesResponse(_request, _result); - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/Channel/PartHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/Channel/PartHandler.cs deleted file mode 100755 index 1438af0e7..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/Channel/PartHandler.cs +++ /dev/null @@ -1,103 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Error.IRC.Channel; -using UniSpy.Server.Chat.Error.IRC.General; -using UniSpy.Server.Chat.Aggregate; -using UniSpy.Server.Chat.Contract.Request.Channel; -using UniSpy.Server.Chat.Contract.Response.Channel; -using UniSpy.Server.Chat.Contract.Result.Channel; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.QueryReport.Aggregate.Redis.Channel; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.Channel -{ - - public sealed class PartHandler : ChannelHandlerBase - { - private new PartRequest _request => (PartRequest)base._request; - private new PartResponse _response { get => (PartResponse)base._response; set => base._response = value; } - private new PartResult _result { get => (PartResult)base._result; set => base._result = value; } - public PartHandler(IChatClient client, PartRequest request) : base(client, request) { } - static PartHandler() - { - } - protected override void RequestCheck() - { - if (_request.RawRequest is null) - { - _channel = _client.Info.GetJoinedChannel(_request.ChannelName); - if (_channel is null) - { - throw new NoSuchChannelException($"No such channel {_request.ChannelName}", _request.ChannelName); - } - _user = _channel.GetUser(_client); - if (_user is null) - { - throw new NoSuchNickException($"Can not find user with nickname: {_client.Info.NickName} username: {_client.Info.UserName}"); - } - } - else - { - base.RequestCheck(); - } - } - protected override void DataOperation() - { - _result = new PartResult(); - _result.LeaverIRCPrefix = _user.Info.IRCPrefix; - _result.ChannelName = _channel.Name; - switch (_channel.RoomType) - { - case PeerRoomType.Normal: - case PeerRoomType.Staging: - if (_user.IsChannelCreator) - { - foreach (var user in _channel.Users.Values) - { - // we do not need to send part message to leaver - if (user.Info.NickName == _user.Info.NickName) - { - continue; - } - // We create a new KICKHandler to handle KICK operation for us - var kickRequest = new KickRequest - { - KickeeNickName = user.Info.NickName, - ChannelName = _channel.Name, - Reason = _request.Reason, - }; - new KickHandler(_client, kickRequest).Handle(); - } - ChannelManager.RemoveChannel(_channel.Name); - _channel.MessageBroker.Unsubscribe(); - switch (_channel.RoomType) - { - case PeerRoomType.Normal: - case PeerRoomType.Staging: - var chanInfo = _channel.GetChannelCache(); - QueryReport.Application.StorageOperation.RemoveChannel(chanInfo); - break; - } - } - goto default; - default: - // we need always remove the connection in leaver and channel - _channel.RemoveUser(_user); - Aggregate.Channel.UpdateChannelCache(_user); - // Aggregate.Channel.UpdatePeerRoomInfo(_user); - break; - } - } - - protected override void ResponseConstruct() - { - _response = new PartResponse(_request, _result); - } - - protected override void Response() - { - // when user leave channel we must broadcast leave message, whatever the room type is. - // otherwise the other client will not delete this user in his client list - _channel.MultiCast(_user.Client, _response, true); - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/Channel/SetCKeyHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/Channel/SetCKeyHandler.cs deleted file mode 100755 index c1b62650b..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/Channel/SetCKeyHandler.cs +++ /dev/null @@ -1,81 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Error.IRC.General; -using UniSpy.Server.Chat.Aggregate; -using UniSpy.Server.Chat.Contract.Request.Channel; -using UniSpy.Server.Chat.Contract.Response.Channel; -using UniSpy.Server.Chat.Abstraction.Interface; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.Channel -{ - // Sets channel key/values. - // If user is NULL or "", the keys will be set on the channel. - // Otherwise, they will be set on the user, - // Only ops can set channel keys on other users. - // Set a value to NULL or "" to clear that key. - - public sealed class SetCKeyHandler : ChannelHandlerBase - { - private new SetCKeyRequest _request => (SetCKeyRequest)base._request; - private ChannelUser _otherUser; - public SetCKeyHandler(IChatClient client, SetCKeyRequest request) : base(client, request) - { - } - - protected override void RequestCheck() - { - _request.Parse(); - // if client nickname is *, we set the name and execute the stored handlers - if (!_client.Info.IsNickNameSet) - { - _client.Info.NickName = _request.NickName; - lock (_client.Info.HandlerStack) - { - foreach (var handler in _client.Info.HandlerStack) - { - handler.Handle(); - } - _client.Info.HandlerStack.Clear(); - } - } - - base.RequestCheck(); - if (_request.NickName != _client.Info.NickName) - { - if (!_user.IsChannelOperator) - { - throw new Chat.Exception("SETCKEY failed because you are not channel operator."); - } - _otherUser = _channel.GetUser(_request.NickName); - if (_otherUser is null) - { - throw new NoSuchNickException($"Can not find user:{_request.NickName} in channel {_request.ChannelName}"); - } - } - } - - protected override void DataOperation() - { - if (_otherUser is not null) - { - _otherUser.KeyValues.Update(_request.KeyValues); - } - else - { - _user.KeyValues.Update(_request.KeyValues); - } - } - - protected override void ResponseConstruct() - { - if (_request.IsBroadCast) - { - _response = new SetCKeyResponse(_request); - } - } - //! if there are key start with b_ we must broadcast to everyone - protected override void Response() - { - _channel.MultiCast(_client, _response); - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/Channel/SetChannelKeyHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/Channel/SetChannelKeyHandler.cs deleted file mode 100755 index eb9b771a0..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/Channel/SetChannelKeyHandler.cs +++ /dev/null @@ -1,43 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Contract.Request.Channel; -using UniSpy.Server.Chat.Contract.Response.Channel; -using UniSpy.Server.Chat.Contract.Result.Channel; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.Channel -{ - // Sets channel key/values. - // If user is NULL or "", the keys will be set on the channel. - // Otherwise, they will be set on the user, - // Only ops can set channel keys on other users. - // Set a value to NULL or "" to clear that key. - public sealed class SetChannelKeyHandler : ChannelHandlerBase - { - private new SetChannelKeyRequest _request => (SetChannelKeyRequest)base._request; - private new SetChannelKeyResult _result { get => (SetChannelKeyResult)base._result; set => base._result = value; } - public SetChannelKeyHandler(IChatClient client, SetChannelKeyRequest request) : base(client, request) - { - _result = new SetChannelKeyResult(); - } - protected override void DataOperation() - { - if (!_user.IsChannelOperator) - { - throw new Chat.Exception("SETCHANKEY failed because you are not channel operator."); - } - _channel.KeyValues.Update(_request.KeyValues); - - _result.ChannelName = _result.ChannelName; - _result.ChannelUserIRCPrefix = _user.Info.IRCPrefix; - } - protected override void ResponseConstruct() - { - _response = new SetChannelKeyResponse(_request, _result); - } - //! setchankey must be broadcast to every one in this channel except sender - protected override void Response() - { - _channel.MultiCast(_client, _response, true); - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/Channel/TopicHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/Channel/TopicHandler.cs deleted file mode 100755 index 177cabee6..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/Channel/TopicHandler.cs +++ /dev/null @@ -1,53 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Contract.Request.Channel; -using UniSpy.Server.Chat.Contract.Response.Channel; -using UniSpy.Server.Chat.Contract.Result.Channel; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.Channel -{ - - public sealed class TopicHandler : ChannelHandlerBase - { - private new TopicRequest _request => (TopicRequest)base._request; - private new TopicResult _result { get => (TopicResult)base._result; set => base._result = value; } - public TopicHandler(IChatClient client, TopicRequest request) : base(client, request) - { - _result = new TopicResult(); - } - - protected override void DataOperation() - { - if (!_user.IsChannelOperator) - { - throw new Chat.Exception("Edit topic failed because you are not channel operator."); - } - switch (_request.RequestType) - { - case TopicRequestType.GetChannelTopic: - break; - case TopicRequestType.SetChannelTopic: - _channel.Topic = _request.ChannelTopic; - break; - } - _result.ChannelName = _channel.Name; - _result.ChannelTopic = _channel.Topic; - } - protected override void ResponseConstruct() - { - _response = new TopicResponse(_request, _result); - } - protected override void Response() - { - switch (_request.RequestType) - { - case TopicRequestType.GetChannelTopic: - _client.Send(_response); - break; - case TopicRequestType.SetChannelTopic: - _channel.MultiCast(_client, _response); - break; - } - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/General/CdKeyHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/General/CdKeyHandler.cs deleted file mode 100755 index 7e25688d1..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/General/CdKeyHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Contract.Request.General; -using UniSpy.Server.Chat.Contract.Response.General; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.General -{ - - public sealed class CdKeyHandler : CmdHandlerBase - { - private new CdKeyRequest _request => (CdKeyRequest)base._request; - - public CdKeyHandler(IChatClient client, CdKeyRequest request) : base(client, request){ } - - protected override void ResponseConstruct() - { - _response = new CdKeyResponse(_request, _result); - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/General/CryptHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/General/CryptHandler.cs deleted file mode 100755 index 8e1f49f55..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/General/CryptHandler.cs +++ /dev/null @@ -1,55 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Request.General; -using UniSpy.Server.Chat.Contract.Response.General; -using UniSpy.Server.Chat.Contract.Result.General; -using UniSpy.Server.Core.Extension; -using UniSpy.Server.Chat.Application; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.General -{ - - public sealed class CryptHandler : CmdHandlerBase - { - private new CryptRequest _request => (CryptRequest)base._request; - private new CryptResult _result { get => (CryptResult)base._result; set => base._result = value; } - private ICryptography _crypto; - // CRYPT des 1 gamename - public CryptHandler(IChatClient client, CryptRequest request) : base(client, request) - { - _result = new CryptResult(); - } - protected override void DataOperation() - { - // we do not use crypto for remote client - if (!_client.Info.IsRemoteClient) - { - string secretKey = DataOperationExtensions.GetSecretKey(_request.GameName); - if (secretKey is null) - { - (_client as Client)?.Connection.Disconnect(); - throw new Chat.Exception("secret key not found."); - } - _client.Info.GameSecretKey = secretKey; - // 2. Prepare two keys - _crypto = new ChatCrypt(_client.Info.GameSecretKey); - } - _client.Info.GameName = _request.GameName; - } - protected override void ResponseConstruct() - { - _response = new CryptResponse(_request, _result); - } - - protected override void Response() - { - base.Response(); - if (!_client.Info.IsRemoteClient) - { - ((Client)_client).Crypto = _crypto; - } - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/General/GetKeyHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/General/GetKeyHandler.cs deleted file mode 100755 index 2ace55763..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/General/GetKeyHandler.cs +++ /dev/null @@ -1,46 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Contract.Request.General; -using UniSpy.Server.Chat.Contract.Response.General; -using UniSpy.Server.Chat.Contract.Result.General; -using UniSpy.Server.Chat.Application; -using UniSpy.Server.Chat.Abstraction.Interface; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.General -{ - /// - /// Get key value of the one user or all user - /// - public sealed class GetKeyHandler : LogedInHandlerBase - { - private new GetKeyRequest _request => (GetKeyRequest)base._request; - private new GetKeyResult _result { get => (GetKeyResult)base._result; set => base._result = value; } - public GetKeyHandler(IChatClient client, GetKeyRequest request) : base(client, request) - { - _result = new GetKeyResult(); - } - - protected override void DataOperation() - { - if (_request.IsGetAllUser) - { - var matchedClients = ClientManager.GetAllClientInfo(); - foreach (ClientInfo info in matchedClients) - { - var values = info.KeyValues.GetValueString(_request.Keys); - _result.Values.Add(values); - } - } - else - { - _result.NickName = _request.NickName; - var target = ClientManager.GetClientByNickName(_request.NickName); - _result.Values.Add(_client.Info.KeyValues.GetValueString(_request.Keys)); - } - } - - protected override void ResponseConstruct() - { - _response = new GetKeyResponse(_request, _result); - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/General/GetUdpRelayHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/General/GetUdpRelayHandler.cs deleted file mode 100755 index 08a972601..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/General/GetUdpRelayHandler.cs +++ /dev/null @@ -1,17 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Contract.Request.General; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.General -{ - /// - /// currently we do not know how this work - /// so we do not implement it - /// - - public sealed class GetUdpRelayHandler : CmdHandlerBase - { - new GetUdpRelayRequest _request => (GetUdpRelayRequest)base._request; - public GetUdpRelayHandler(IChatClient client, GetUdpRelayRequest request) : base(client, request) { } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/General/InviteHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/General/InviteHandler.cs deleted file mode 100644 index d759f8f7b..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/General/InviteHandler.cs +++ /dev/null @@ -1,25 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Aggregate; -using UniSpy.Server.Chat.Contract.Request.General; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.General -{ - public sealed class InviteHandler : CmdHandlerBase - { - private new InviteRequest _request => (InviteRequest)base._request; - public InviteHandler(IChatClient client, InviteRequest request) : base(client, request) - { - } - protected override void RequestCheck() - { - base.RequestCheck(); - if (!_client.Info.JoinedChannels.ContainsKey(_request.ChannelName)) - { - throw new Chat.Exception("To invite user, you must in the channel."); - } - var chan = ChannelManager.GetChannel(_request.ChannelName); - chan.Mode.InviteNickNames.Add(_request.NickName); - } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Handler/CmdHandler/General/ListHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/General/ListHandler.cs deleted file mode 100755 index d09a47edd..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/General/ListHandler.cs +++ /dev/null @@ -1,43 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Aggregate; -using UniSpy.Server.Chat.Contract.Request.General; -using UniSpy.Server.Chat.Contract.Response.General; -using UniSpy.Server.Chat.Contract.Result.General; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.General -{ - //todo unfinished - - public sealed class ListHandler : LogedInHandlerBase - { - private new ListRequest _request => (ListRequest)base._request; - private new ListResult _result { get => (ListResult)base._result; set => base._result = value; } - //:irc.foonet.com 321 Pants Channel :Users Name\r\n:irc.foonet.com 323 Pants :End of /LIST\r\n - public ListHandler(IChatClient client, ListRequest request) : base(client, request) - { - _result = new ListResult(); - } - protected override void DataOperation() - { - //add list response header - foreach (var channel in ChannelManager.Channels.Values) - { - //TODO - //add channel information here - ListDataModel channelInfo = new ListDataModel - { - ChannelName = channel.Name, - TotalChannelUsers = channel.Users.Count, - ChannelTopic = channel.Topic - }; - _result.ChannelInfoList.Add(channelInfo); - } - } - - protected override void ResponseConstruct() - { - _response = new ListResponse(_request, _result); - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/General/LoginHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/General/LoginHandler.cs deleted file mode 100755 index 9406a46ab..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/General/LoginHandler.cs +++ /dev/null @@ -1,49 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Contract.Request.General; -using UniSpy.Server.Chat.Contract.Response.General; -using UniSpy.Server.Chat.Contract.Result.General; -using UniSpy.Server.Chat.Application; -using UniSpy.Server.Chat.Abstraction.Interface; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.General -{ - - public sealed class LoginHandler : CmdHandlerBase - { - - private new LoginRequest _request => (LoginRequest)base._request; - private new LoginResult _result { get => (LoginResult)base._result; set => base._result = value; } - public LoginHandler(IChatClient client, LoginRequest request) : base(client, request) - { - _result = new LoginResult(); - } - - protected override void RequestCheck() - { - /// TODO: Verify which games does send a GS encoded password and not md5 - //we decoded gamespy encoded password then get md5 of it - //_password = GameSpyUtils.DecodePassword(_request.PasswordHash); - //_password = StringExtensions.GetMD5Hash(_password); - base.RequestCheck(); - } - - protected override void DataOperation() - { - switch (_request.ReqeustType) - { - case LoginReqeustType.NickAndEmailLogin: - // the ignored variables _ will used in future - (_result.ProfileId, _result.UserID, _, _) = StorageOperation.Persistance.NickAndEmailLogin(_request.NickName, _request.Email, _request.PasswordHash); - break; - case LoginReqeustType.UniqueNickLogin: - (_result.ProfileId, _result.UserID, _, _) = StorageOperation.Persistance.UniqueNickLogin(_request.UniqueNick, _request.NamespaceId); - break; - } - } - - protected override void ResponseConstruct() - { - _response = new LoginResponse(_request, _result); - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/General/NickHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/General/NickHandler.cs deleted file mode 100755 index b237b4ce3..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/General/NickHandler.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System.Linq; -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Application; -using UniSpy.Server.Chat.Error.IRC.General; -using UniSpy.Server.Chat.Contract.Request.General; -using UniSpy.Server.Chat.Contract.Response.General; -using UniSpy.Server.Chat.Abstraction.Interface; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.General -{ - - public sealed class NickHandler : CmdHandlerBase - { - private new NickRequest _request => (NickRequest)base._request; - public NickHandler(IChatClient client, NickRequest request) : base(client, request) { } - - protected override void RequestCheck() - { - base.RequestCheck(); - int number = 0; - string validNickName; - var clientInfos = ClientManager.GetAllClientInfo(); - - - if (_request.NickName == "*") - { - //client is only authenticating with chat, we just sign a valid name to it. - _client.Info.NickName = System.Guid.NewGuid().ToString(); - return; - } - - if (ClientManager.GetAllClientInfo().Where(i => i.NickName == _request.NickName).Count() == 0) - { - _client.Info.NickName = _request.NickName; - } - else - { - while (true) - { - string newNickName = _request.NickName + number; - if (ClientManager.GetAllClientInfo().Where(i => i.NickName == _request.NickName).Count() == 0) - { - validNickName = newNickName; - break; - } - } - throw new NickNameInUseException( - $"The nick name: {_request.NickName} is already in use", - _request.NickName, - validNickName); - } - } - - protected override void DataOperation() - { - _client.Info.NickName = _request.NickName; - } - protected override void ResponseConstruct() - { - _response = new NickResponse(_request, _result); - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/General/PingHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/General/PingHandler.cs deleted file mode 100755 index c43f77edf..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/General/PingHandler.cs +++ /dev/null @@ -1,25 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Contract.Request.General; -using UniSpy.Server.Chat.Contract.Response.General; -using UniSpy.Server.Chat.Contract.Result.General; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.General -{ - - public sealed class PingHandler : LogedInHandlerBase - { - private new PingRequest _request => (PingRequest)base._request; - private new PingResult _result { get => (PingResult)base._result; set => base._result = value; } - public PingHandler(IChatClient client, PingRequest request) : base(client, request){ } - protected override void DataOperation() - { - _result = new PingResult(); - _result.RequesterIRCPrefix = _client.Info.IRCPrefix; - } - protected override void ResponseConstruct() - { - _response = new PingResponse(_request, _result); - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/General/QuitHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/General/QuitHandler.cs deleted file mode 100755 index 44af14a2b..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/General/QuitHandler.cs +++ /dev/null @@ -1,46 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Aggregate; -using UniSpy.Server.Chat.Contract.Request.Channel; -using UniSpy.Server.Chat.Contract.Request.General; -using UniSpy.Server.Chat.Handler.CmdHandler.Channel; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.General -{ - - public sealed class QuitHandler : LogedInHandlerBase - { - private new QuitRequest _request => (QuitRequest)base._request; - // when a user disconnected with server we can call this function - public QuitHandler(IChatClient client, QuitRequest request) : base(client, request) { } - protected override void RequestCheck() - { - if (_request.RawRequest is null) - { - return; - } - base.RequestCheck(); - } - - protected override void DataOperation() - { - foreach (var channel in _client.Info.JoinedChannels.Values) - { - ChannelUser user = channel.GetUser(_client); - if (user is null) - { - continue; - } - // we create a PARTHandler to handle our quit request - var partRequest = new PartRequest() - { - ChannelName = channel.Name, - Reason = _request.Reason - }; - new PartHandler(_client, partRequest).Handle(); - // client is loged out - _client.Info.IsLoggedIn = false; - } - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/General/SetKeyHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/General/SetKeyHandler.cs deleted file mode 100755 index 40bcdd53c..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/General/SetKeyHandler.cs +++ /dev/null @@ -1,29 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Contract.Request.General; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.General -{ - /// - /// set global key value on this client - /// - public sealed class SetKeyHandler : LogedInHandlerBase - { - private new SetKeyRequest _request => (SetKeyRequest)base._request; - public SetKeyHandler(IChatClient client, SetKeyRequest request) : base(client, request) { } - - protected override void DataOperation() - { - _client.Info.KeyValues.Update(_request.KeyValues); - // foreach (var channel in _client.Info.JoinedChannels.Values) - // { - // ChannelUser user = channel.GetChannelUser(_client); - // //if (user==null) - // //{ - // // continue; - // //} - // user.UpdateUserKeyValues(_request.KeyValues); - // } - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/General/UserHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/General/UserHandler.cs deleted file mode 100755 index ece6a44f3..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/General/UserHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Contract.Request.General; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.General -{ - - public sealed class UserHandler : CmdHandlerBase - { - private new UserRequest _request => (UserRequest)base._request; - public UserHandler(IChatClient client, UserRequest request) : base(client, request){ } - - protected override void DataOperation() - { - _client.Info.UserName = _request.UserName; - _client.Info.Name = _request.Name; - _client.Info.IsLoggedIn = true; - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/General/UserIPHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/General/UserIPHandler.cs deleted file mode 100755 index ca6aebcae..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/General/UserIPHandler.cs +++ /dev/null @@ -1,28 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Contract.Request.General; -using UniSpy.Server.Chat.Contract.Response.General; -using UniSpy.Server.Chat.Contract.Result.General; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.General -{ - - public sealed class UserIPHandler : CmdHandlerBase - { - - private new UserIPRequest _request => (UserIPRequest)base._request; - private new UserIPResult _result { get => (UserIPResult)base._result; set => base._result = value; } - public UserIPHandler(IChatClient client, UserIPRequest request) : base(client, request){ } - - protected override void DataOperation() - { - _result = new UserIPResult(); - _result.RemoteIPAddress = _client.Connection.RemoteIPEndPoint.Address; - - } - protected override void ResponseConstruct() - { - _response = new UserIPResponse(_request, _result); - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/General/WhoHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/General/WhoHandler.cs deleted file mode 100755 index 01eaccc77..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/General/WhoHandler.cs +++ /dev/null @@ -1,84 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Application; -using UniSpy.Server.Chat.Aggregate.Misc; -using UniSpy.Server.Chat.Contract.Request.General; -using UniSpy.Server.Chat.Contract.Response.General; -using UniSpy.Server.Chat.Contract.Result.General; -using UniSpy.Server.Chat.Aggregate; -using UniSpy.Server.Chat.Abstraction.Interface; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.General -{ - /// - /// Get a channel user's basic information - /// same as WHOIS - /// - - public sealed class WhoHandler : LogedInHandlerBase - { - private new WhoRequest _request => (WhoRequest)base._request; - private new WhoResult _result { get => (WhoResult)base._result; set => base._result = value; } - public WhoHandler(IChatClient client, WhoRequest request) : base(client, request) { } - - protected override void DataOperation() - { - _result = new WhoResult(); - - switch (_request.RequestType) - { - case WhoRequestType.GetChannelUsersInfo: - GetChannelUsersInfo(); - break; - case WhoRequestType.GetUserInfo: - GetUserInfo(); - break; - } - } - - private void GetChannelUsersInfo() - { - if (!ChannelManager.IsChannelExist(_request.ChannelName)) - { - throw new IRCChannelException($"The channel is not exist.", IRCErrorCode.NoSuchChannel, _request.ChannelName); - } - var channel = ChannelManager.GetChannel(_request.ChannelName); - foreach (var user in channel.Users.Values) - { - var data = new WhoDataModel - { - ChannelName = channel.Name, - UserName = user.Info.UserName, - NickName = user.Info.NickName, - PublicIPAddress = user.Connection.RemoteIPEndPoint.Address.ToString(), - Modes = user.Modes - }; - _result.DataModels.Add(data); - } - } - /// - /// Send all channel user information - /// - private void GetUserInfo() - { - var client = ClientManager.GetClientByNickName(_request.NickName); - - foreach (var channel in client.Info.JoinedChannels.Values) - { - var user = channel.GetUser(client); - var data = new WhoDataModel - { - ChannelName = channel.Name, - NickName = client.Info.NickName, - UserName = client.Info.UserName, - PublicIPAddress = client.Connection.RemoteIPEndPoint.Address.ToString(), - Modes = user.Modes - }; - _result.DataModels.Add(data); - } - } - protected override void ResponseConstruct() - { - _response = new WhoResponse(_request, _result); - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/General/WhoIsHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/General/WhoIsHandler.cs deleted file mode 100755 index 147ab7ad2..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/General/WhoIsHandler.cs +++ /dev/null @@ -1,45 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Application; -using UniSpy.Server.Chat.Contract.Request.General; -using UniSpy.Server.Chat.Contract.Response.General; -using UniSpy.Server.Chat.Contract.Result.General; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.General -{ - - public sealed class WhoIsHandler : CmdHandlerBase - { - private new WhoIsRequest _request => (WhoIsRequest)base._request; - private new WhoIsResult _result { get => (WhoIsResult)base._result; set => base._result = value; } - private ClientInfo _clientInfo; - public WhoIsHandler(IChatClient client, WhoIsRequest request) : base(client, request) { } - - protected override void RequestCheck() - { - _result = new WhoIsResult(); - - // there only existed one nick name - base.RequestCheck(); - var client = ClientManager.GetClientByNickName(_request.NickName); - _clientInfo = client.Info; - } - protected override void DataOperation() - { - _result.NickName = _clientInfo.NickName; - _result.Name = _clientInfo.Name; - _result.UserName = _clientInfo.UserName; - _result.PublicIPAddress = _client.Connection.RemoteIPEndPoint.Address.ToString(); - foreach (var channel in _clientInfo.JoinedChannels.Values) - { - _result.JoinedChannelName.Add(channel.Name); - } - } - protected override void ResponseConstruct() - { - _response = new WhoIsResponse(_request, _result); - } - - - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/Message/AtmHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/Message/AtmHandler.cs deleted file mode 100755 index dff5cceb5..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/Message/AtmHandler.cs +++ /dev/null @@ -1,25 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Contract.Request.Message; -using UniSpy.Server.Chat.Contract.Response.Message; -using UniSpy.Server.Chat.Contract.Result.Message; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.Message -{ - /// - /// Above the table message handler - /// - public sealed class AtmHandler : MessageHandlerBase - { - new AtmRequest _request => (AtmRequest)base._request; - new AtmResult _result{ get => (AtmResult)base._result; set => base._result = value; } - public AtmHandler(IChatClient client, AtmRequest request) : base(client, request) - { - _result = new AtmResult(); - } - protected override void ResponseConstruct() - { - _response = new AtmResponse(_request, _result); - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/Message/NoticeHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/Message/NoticeHandler.cs deleted file mode 100755 index 774488a80..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/Message/NoticeHandler.cs +++ /dev/null @@ -1,27 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Contract.Request.Message; -using UniSpy.Server.Chat.Contract.Response.Message; -using UniSpy.Server.Chat.Contract.Result.Message; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.Message -{ - - public sealed class NoticeHandler : MessageHandlerBase - { - private new NoticeRequest _request => (NoticeRequest)base._request; - private new NoticeResult _result{ get => (NoticeResult)base._result; set => base._result = value; } - public NoticeHandler(IChatClient client, NoticeRequest request) : base(client, request) - { - _result = new NoticeResult(); - } - - protected override void ResponseConstruct() - { - _response = new NoticeResponse(_request, _result); - } - } -} - - - diff --git a/src/Servers/Chat/src/Handler/CmdHandler/Message/PrivateHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/Message/PrivateHandler.cs deleted file mode 100755 index 494ab3ffd..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/Message/PrivateHandler.cs +++ /dev/null @@ -1,46 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Contract.Request.Message; -using UniSpy.Server.Chat.Contract.Response.Message; -using UniSpy.Server.Chat.Contract.Result.Message; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.Message -{ - - public sealed class PrivateHandler : MessageHandlerBase - { - private new PrivateRequest _request => (PrivateRequest)base._request; - private new PrivateResult _result { get => (PrivateResult)base._result; set => base._result = value; } - public PrivateHandler(IChatClient client, PrivateRequest request) : base(client, request) - { - _result = new PrivateResult(); - } - protected override void ChannelMessageDataOpration() - { - - if (_channel.Mode.IsModeratedChannel) - { - return; - } - - if (_channel.IsUserBanned(_user)) - { - return; - } - - if (!_user.IsVoiceable) - { - return; - } - // if (_user.Info.IsQuietMode) - // { - // return; - // } - _result.IsBroadcastMessage = true; - } - protected override void ResponseConstruct() - { - _response = new PrivateResponse(_request, _result); - } - } -} diff --git a/src/Servers/Chat/src/Handler/CmdHandler/Message/UtmHandler.cs b/src/Servers/Chat/src/Handler/CmdHandler/Message/UtmHandler.cs deleted file mode 100755 index cbf9026f1..000000000 --- a/src/Servers/Chat/src/Handler/CmdHandler/Message/UtmHandler.cs +++ /dev/null @@ -1,27 +0,0 @@ -using UniSpy.Server.Chat.Abstraction.BaseClass; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Contract.Request.Message; -using UniSpy.Server.Chat.Contract.Response.Message; -using UniSpy.Server.Chat.Contract.Result.Message; - -namespace UniSpy.Server.Chat.Handler.CmdHandler.Message -{ - /// - /// Under the table message, this message will not display in regular chat - /// - public sealed class UtmHandler : MessageHandlerBase - { - private new UtmRequest _request => (UtmRequest)base._request; - private new UtmResult _result { get => (UtmResult)base._result; set => base._result = value; } - public UtmHandler(IChatClient client, UtmRequest request) : base(client, request) - { - _result = new UtmResult(); - } - - protected override void ResponseConstruct() - { - _response = new UtmResponse(_request, _result); - } - - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/Handler/CmdSwitcher.cs b/src/Servers/Chat/src/Handler/CmdSwitcher.cs deleted file mode 100755 index 6f590a1b2..000000000 --- a/src/Servers/Chat/src/Handler/CmdSwitcher.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using UniSpy.Server.Chat.Abstraction.Interface; -using UniSpy.Server.Chat.Contract.Request.Channel; -using UniSpy.Server.Chat.Contract.Request.General; -using UniSpy.Server.Chat.Contract.Request.Message; -using UniSpy.Server.Chat.Handler.CmdHandler.Channel; -using UniSpy.Server.Chat.Handler.CmdHandler.General; -using UniSpy.Server.Chat.Handler.CmdHandler.Message; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.Chat.Handler -{ - /// - /// Process request to Commands - /// - public sealed class CmdSwitcher : CmdSwitcherBase - { - private new string _rawRequest => (string)base._rawRequest; - private new IChatClient _client => (IChatClient)base._client; - public CmdSwitcher(IChatClient client, string rawRequest) : base(client, rawRequest) { } - - protected override void ProcessRawRequest() - { - string[] splitedRawRequests = _rawRequest.Replace("\r", "") - .Split("\n", StringSplitOptions.RemoveEmptyEntries); - foreach (var rawRequest in splitedRawRequests) - { - var name = rawRequest.Trim(' ').Split(' ', StringSplitOptions.RemoveEmptyEntries).ToList().First(); - _requests.Add(new KeyValuePair(name, rawRequest)); - } - } - - protected override IHandler CreateCmdHandlers(object name, object rawRequest) - { - var request = (string)rawRequest; - switch ((string)name) - { - # region General - case "CRYPT": - return new CryptHandler(_client, new CryptRequest(request)); - case "CDKEY": - return new CdKeyHandler(_client, new CdKeyRequest(request)); - case "GETKEY": - return new GetKeyHandler(_client, new GetKeyRequest(request)); - case "LIST": - return new ListHandler(_client, new ListRequest(request)); - case "LOGIN": - return new LoginHandler(_client, new LoginRequest(request)); - case "NICK": - return new NickHandler(_client, new NickRequest(request)); - case "PING": - return new PingHandler(_client, new PingRequest(request)); - case "QUIT": - return new QuitHandler(_client, new QuitRequest(request)); - case "SETKEY": - return new SetKeyHandler(_client, new SetKeyRequest(request)); - case "USER": - return new UserHandler(_client, new UserRequest(request)); - case "USRIP": - return new UserIPHandler(_client, new UserIPRequest(request)); - case "WHO": - return new WhoHandler(_client, new WhoRequest(request)); - case "WHOIS": - return new WhoIsHandler(_client, new WhoIsRequest(request)); - #endregion - - #region Channel - case "GETCHANKEY": - return new GetChannelKeyHandler(_client, new GetChannelKeyRequest(request)); - case "GETCKEY": - return new GetCKeyHandler(_client, new GetCKeyRequest(request)); - case "JOIN": - return new JoinHandler(_client, new JoinRequest(request)); - case "KICK": - return new KickHandler(_client, new KickRequest(request)); - case "MODE": - return new ModeHandler(_client, new ModeRequest(request)); - case "NAMES": - return new NamesHandler(_client, new NamesRequest(request)); - case "PART": - return new PartHandler(_client, new PartRequest(request)); - case "SETCHANKEY": - return new SetChannelKeyHandler(_client, new SetChannelKeyRequest(request)); - case "SETCKEY": - return new SetCKeyHandler(_client, new SetCKeyRequest(request)); - case "TOPIC": - return new TopicHandler(_client, new TopicRequest(request)); - #endregion - #region Message - case "ATM": - return new AtmHandler(_client, new AtmRequest(request)); - case "NOTICE": - return new NoticeHandler(_client, new NoticeRequest(request)); - case "PRIVMSG": - return new PrivateHandler(_client, new PrivateRequest(request)); - case "UTM": - return new UtmHandler(_client, new UtmRequest(request)); - default: - return null; - #endregion - } - } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/src/UniSpy.Server.Chat.csproj b/src/Servers/Chat/src/UniSpy.Server.Chat.csproj deleted file mode 100755 index d42e6c35f..000000000 --- a/src/Servers/Chat/src/UniSpy.Server.Chat.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - - Exe - net6.0 - ..\..\..\..\common\Icon\UniSpy_Logo.ico - Linux - ..\..\..\.. - - - ..\..\..\..\build\$(Configuration) - - - ..\..\..\..\build\$(Configuration) - - - - - - - - - \ No newline at end of file diff --git a/src/Servers/Chat/test/Channel/ChannelHandlerTest.cs b/src/Servers/Chat/test/Channel/ChannelHandlerTest.cs deleted file mode 100644 index 19d41d74a..000000000 --- a/src/Servers/Chat/test/Channel/ChannelHandlerTest.cs +++ /dev/null @@ -1,84 +0,0 @@ -using UniSpy.Server.Chat.Application; -using UniSpy.Server.Chat.Contract.Request.Channel; -using UniSpy.Server.Chat.Contract.Request.General; -using UniSpy.Server.Chat.Contract.Request.Message; -using UniSpy.Server.Chat.Handler.CmdHandler.Channel; -using UniSpy.Server.Chat.Handler.CmdHandler.General; -using UniSpy.Server.Chat.Handler.CmdHandler.Message; -using UniSpy.Server.QueryReport.Aggregate.Redis.Channel; -using Xunit; - -namespace UniSpy.Server.Chat.Test.Channel -{ - public class ChannelHandlerTest - { - [Fact] - public void RoomTypeTest() - { - Assert.True(PeerRoom.GetRoomType("#GPG!622") == QueryReport.Aggregate.Redis.Channel.PeerRoomType.Group); - Assert.True(PeerRoom.GetRoomType("#GSP!worms3!Ml4lz344lM") == QueryReport.Aggregate.Redis.Channel.PeerRoomType.Staging); - Assert.True(PeerRoom.GetRoomType("#islanbul") == QueryReport.Aggregate.Redis.Channel.PeerRoomType.Normal); - } - [Fact] - public void JoinHandleTest() - { - var client1 = (Client)MockObject.CreateClient(port: 1234); - client1.Info.GameName = "worm3"; - var client2 = (Client)MockObject.CreateClient(port: 1235); - client2.Info.GameName = "worm3"; - SingleJoinTest(client1, "unispy1", "unispy1", "#GSP!room!test1"); - SingleJoinTest(client2, "unispy2", "unispy2", "#GSP!room!test1"); - } - [Fact] - public void ChannelMsgTest() - { - var client1 = (Client)MockObject.CreateClient(port: 1236); - var client2 = (Client)MockObject.CreateClient(port: 1237); - SingleJoinTest(client1, "unispy3", "unispy3", "#GSP!room!test2"); - SingleJoinTest(client2, "unispy4", "unispy4", "#GSP!room!test2"); - var privMsgReq = new PrivateRequest("PRIVMSG #GSP!room!test2 :hello this is a test."); - var privMsgHandler = new PrivateHandler(client1, privMsgReq); - privMsgHandler.Handle(); - } - private void SingleLoginTest(Client client, string userName = "unispy", string nickName = "unispy") - { - var userReq = new UserRequest($"USER {userName} 127.0.0.1 peerchat.unispy.org :{userName}"); - var nickReq = new NickRequest($"NICK {nickName}"); - var userHandler = new UserHandler(client, userReq); - var nickHandler = new NickHandler(client, nickReq); - userHandler.Handle(); - nickHandler.Handle(); - } - private void SingleJoinTest(Client client, string userName = "unispy", string nickName = "unispy", string channelName = "#GSP!room!test") - { - SingleLoginTest(client, userName, nickName); - var joinReq = new JoinRequest($"JOIN {channelName}"); - var joinHandler = new JoinHandler(client, joinReq); - // we know the endpoint object is not set, so System.NullReferenceException will be thrown - joinHandler.Handle(); - Assert.Single(client.Info.JoinedChannels); - Assert.True(client.Info.JoinedChannels.ContainsKey(channelName)); - Assert.True(client.Info.IsJoinedChannel(channelName)); - } - [Fact] - public void SetCKeyTest() - { - var client = (Client)MockObject.CreateClient(port: 1238); - - SingleJoinTest(client, "spyguy6", "spyguy6", "#GSP!room!test14"); - var request = new SetCKeyRequest(ChannelRequests.SetCKey); - var handler = new SetCKeyHandler(client, request); - handler.Handle(); - } - [Fact] - public void ModeTest() - { - var client = (Client)MockObject.CreateClient(port: 1239); - - SingleJoinTest(client, "spyguy7", "spyguy7", "#GSP!gmtest!MlNK4q4l1M"); - var request = new ModeRequest("MODE #GSP!gmtest!MlNK4q4l1M -i-p-s+m-n+t+l+e 2"); - var handler = new ModeHandler(client, request); - handler.Handle(); - } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/test/Channel/ChannelRequestTest.cs b/src/Servers/Chat/test/Channel/ChannelRequestTest.cs deleted file mode 100644 index eb74ff753..000000000 --- a/src/Servers/Chat/test/Channel/ChannelRequestTest.cs +++ /dev/null @@ -1,131 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Chat.Contract.Request.Channel; -using Xunit; - -namespace UniSpy.Server.Chat.Test.Channel -{ - public class ChannelRequestTest - { - [Fact] - public void GetChannelKey() - { - var request = new GetChannelKeyRequest(ChannelRequests.GetChannelKey); - request.Parse(); - Assert.Equal("#GSP!room!test", request.ChannelName); - Assert.Equal("0000", request.Cookie); - Assert.Equal("username", request.Keys[0]); - Assert.Equal("nickname", request.Keys[1]); - } - - [Fact] - public void GetCKeyChannelSpecificUser() - { - var request = new GetCKeyRequest(ChannelRequests.GetCKeyChannelSpecificUser); - request.Parse(); - Assert.Equal(GetKeyReqeustType.GetChannelSpecificUserKeyValue, request.RequestType); - Assert.Equal("#GSP!room!test", request.ChannelName); - Assert.Equal("spyguy", request.NickName); - Assert.Equal("0000", request.Cookie); - Assert.Equal("username", request.Keys[0]); - Assert.Equal("nickname", request.Keys[1]); - } - - [Fact] - public void GetCKeyChannelAllUser() - { - var request = new GetCKeyRequest(ChannelRequests.GetCKeyChannelAllUser); - request.Parse(); - Assert.Equal(GetKeyReqeustType.GetChannelAllUserKeyValue, request.RequestType); - Assert.Equal("#GSP!room!test", request.ChannelName); - Assert.Equal("0000", request.Cookie); - Assert.Equal("username", request.Keys[0]); - Assert.Equal("nickname", request.Keys[1]); - } - - [Fact] - public void Join() - { - var request = new JoinRequest(ChannelRequests.Join); - request.Parse(); - Assert.Equal("#GSP!room!test", request.ChannelName); - - request = new JoinRequest(ChannelRequests.JoinWithPass); - request.Parse(); - Assert.Equal("#GSP!room!test", request.ChannelName); - Assert.Equal("pass123", request.Password); - } - - [Fact] - public void Kick() - { - var request = new KickRequest(ChannelRequests.Kick); - request.Parse(); - Assert.Equal("spyguy", request.KickeeNickName); - Assert.Equal("Spam", request.Reason); - } - - [Fact] - public void Mode() - { - var request = new ModeRequest(ChannelRequests.ModeChannel); - request.Parse(); - Assert.Equal(ModeOperationType.AddChannelUserLimits, request.ModeOperations[0]); - Assert.Equal("#GSP!room!test", request.ChannelName); - Assert.Equal("+l", request.ModeFlag); - Assert.Equal((int)2, request.LimitNumber); - - - request = new ModeRequest("MODE #GSP!gmtest!MlNK4q4l1M -i-p-s+m-n+t+l+e 2"); - request.Parse(); - - } - - [Fact] - public void Part() - { - var request = new PartRequest(ChannelRequests.Part); - request.Parse(); - Assert.Equal("test", request.Reason); - } - - [Fact(Skip = "TODO: add tests")] - public void SetChannelKey() - { - var request = new SetChannelKeyRequest(ChannelRequests.SetChannelKey); - request.Parse(); - } - - [Fact] - public void SetCKey() - { - var request = new SetCKeyRequest(ChannelRequests.SetCKey); - request.Parse(); - Dictionary dict1 = new Dictionary - { - { - "b_flags", "sh" - } - }; - Assert.Equal("#GSP!room!test", request.Channel); - Assert.Equal("spyguy", request.NickName); - Assert.Equal(dict1, request.KeyValues); - } - - [Fact] - public void TopicGetChannelTopic() - { - var request = new TopicRequest(ChannelRequests.TopicGetChannelTopic); - request.Parse(); - Assert.Equal("#GSP!room!test", request.ChannelName); - } - - [Fact] - public void TopicSetChannelTopic() - { - var request = new TopicRequest(ChannelRequests.TopicSetChannelTopic); - request.Parse(); - Assert.Equal("#GSP!room!test", request.ChannelName); - Assert.Equal("This is a topic message.", request.ChannelTopic); - } - } -} diff --git a/src/Servers/Chat/test/Channel/ChannelRequests.cs b/src/Servers/Chat/test/Channel/ChannelRequests.cs deleted file mode 100644 index 19c066a15..000000000 --- a/src/Servers/Chat/test/Channel/ChannelRequests.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace UniSpy.Server.Chat.Test.Channel -{ - public class ChannelRequests - { - public const string GetChannelKey = "GETCHANKEY #GSP!room!test 0000 0 :\\username\\nickname\0"; - public const string GetCKeyChannelSpecificUser = "GETCKEY #GSP!room!test spyguy 0000 0 :\\username\\nickname\0"; - public const string GetCKeyChannelAllUser = "GETCKEY #GSP!room!test * 0000 0 :\\username\\nickname\0"; - - public const string Join = "JOIN #GSP!room!test"; - - public const string JoinWithPass = "JOIN #GSP!room!test pass123"; - - public const string Kick = "KICK #islabul spyguy :Spam"; - - public const string ModeChannel = "MODE #GSP!room!test +l 2"; - public const string ModeUser = "MODE spyguy +s"; - - public const string Part = "PART #GSP!room!test :test"; - - public const string SetChannelKey = "SETCHANNELKEY #GSP!room!test 0000 0:\\b_flags\\sh\0"; - - public const string SetCKey = "SETCKEY #GSP!room!test spyguy 0000 0:\\b_flags\\sh\0"; - - public const string TopicGetChannelTopic = "TOPIC #GSP!room!test"; - - public const string TopicSetChannelTopic = "TOPIC #GSP!room!test :This is a topic message."; - } -} diff --git a/src/Servers/Chat/test/Game/GameTest.cs b/src/Servers/Chat/test/Game/GameTest.cs deleted file mode 100644 index 084595356..000000000 --- a/src/Servers/Chat/test/Game/GameTest.cs +++ /dev/null @@ -1,301 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using UniSpy.Server.Chat.Aggregate; -using UniSpy.Server.Chat.Application; -using UniSpy.Server.Chat.Handler; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Encryption; -using Xunit; - -namespace UniSpy.Server.Chat.Test -{ - public class GameTest - { - [Fact] - public void Civilization4() - { - var rawRequests = new List(){ - // "CRYPT des 1 anno1701", - "USRIP", - "USER X419pGl4sX|18 127.0.0.1 peerchat.gamespy.com :aa3041ada9385b28fc4d4e47db288769", - "NICK a1701-5", - "CDKEY 81123-67814-77652-27631-11723-47707-22638-10701", - "JOIN #GSP!anno1701 ", - "MODE #GSP!anno1701", - @"GETCKEY #GSP!anno1701 * 008 0 :\b_flags","WHO a1701-5", - "JOIN #GSP!anno1701!M9zK0KJaKM ", - "MODE #GSP!anno1701!M9zK0KJaKM", - @"SETCKEY #GSP!anno1701 a1701-5 :\b_flags\s", - @"SETCKEY #GSP!anno1701!M9zK0KJaKM a1701-5 :\b_flags\sh", - @"GETCKEY #GSP!anno1701!M9zK0KJaKM * 009 0 :\b_flags", - "TOPIC #GSP!anno1701!M9zK0KJaKM :test", - "MODE #GSP!anno1701!M9zK0KJaKM +l 4", - "MODE #GSP!anno1701!M9zK0KJaKM -i-p-s+m+n+t+l+e 4", - "PART #GSP!anno1701 :" - }; - var client = (Client)MockObject.CreateClient(); - - foreach (var raw in rawRequests) - { - new CmdSwitcher(client, raw).Handle(); - } - } - [Fact] - public void TcpMessageSplitingTest() - { - var raws = new List(){ - UniSpyEncoding.GetBytes("GETCKEY"), - UniSpyEncoding.GetBytes(" world"), - UniSpyEncoding.GetBytes(" hi").Concat(new byte[]{0x0D,0x0A}).ToArray(), - }; - var client = MockObject.CreateClient(); - foreach (var raw in raws) - { - ((ITestClient)client).TestReceived(raw); - } - // Given - - // When - - // Then - } - [Fact] - public void Worms3dTest() - { - var client1 = MockObject.CreateClient("107.244.81.1", 8888); - var client2 = MockObject.CreateClient("91.34.72.1", 8889); - var request1 = new List() - { - "CRYPT des 1 worms3\r\n", - "USRIP\r\n", - "USER X419pGl4sX|6 127.0.0.1 peerchat.gamespy.com :aa3041ada9385b28fc4d4e47db288769\r\n", - "NICK worms10\r\n", - "JOIN #GPG!622\r\n", - "MODE #GPG!622\r\n", - @"GETCKEY #GPG!622 * 024 0 :\username\b_flags"+"\r\n", - "JOIN #GSP!worms3!Ml4lz344lM\r\n", - "MODE #GSP!worms3!Ml4lz344lM\r\n", - @"SETCKEY #GPG!622 worms10 :\b_flags\s"+"\r\n", - @"SETCKEY #GSP!worms3!Ml4lz344lM worms10 :\b_flags\sh"+"\r\n", - @"GETCKEY #GSP!worms3!Ml4lz344lM * 025 0 :\username\b_flags"+"\r\n", - "TOPIC #GSP!worms3!Ml4lz344lM :tesr\r\n", - "MODE #GSP!worms3!Ml4lz344lM +l 2\r\n", - // "PART #GPG!622 :Joined staging room\r\n", - @"SETCKEY #GSP!worms3!Ml4lz344lM worms10 :\b_firewall\1\b_profileid\6\b_ipaddress\\b_publicip\255.255.255.255\b_privateip\192.168.0.60\b_authresponse\\b_gamever\1073\b_val\0"+"\r\n", - "WHO worms10\r\n", - @"SETCHANKEY #GSP!worms3!Ml4lz344lM :\b_hostname\test\b_hostport\\b_MaxPlayers\2\b_NumPlayers\1\b_SchemeChanging\0\b_gamever\1073\b_gametype\\b_mapname\Random\b_firewall\1\b_publicip\255.255.255.255\b_privateip\192.168.0.60\b_gamemode\openstaging\b_val\0\b_password\1"+"\r\n", - @"GETKEY worms20 026 0 :\b_firewall\b_profileid\b_ipaddress\b_publicip\b_privateip\b_authresponse\b_gamever\b_val"+"\r\n", - @"GETCKEY #GSP!worms3!Ml4lz344lM worms20 027 0 :\b_firewall\b_profileid\b_ipaddress\b_publicip\b_privateip\b_authresponse\b_gamever\b_val"+"\r\n", - @"SETCHANKEY #GSP!worms3!Ml4lz344lM :\b_hostname\test\b_hostport\\b_MaxPlayers\2\b_NumPlayers\1\b_SchemeChanging\0\b_gamever\1073\b_gametype\\b_mapname\Random\b_firewall\1\b_publicip\255.255.255.255\b_privateip\192.168.0.60\b_gamemode\openstaging\b_val\0\b_password\1"+"\r\n", - @"SETCHANKEY #GSP!worms3!Ml4lz344lM :\b_hostname\test\b_hostport\\b_MaxPlayers\2\b_NumPlayers\1\b_SchemeChanging\0\b_gamever\1073\b_gametype\\b_mapname\Random\b_firewall\1\b_publicip\255.255.255.255\b_privateip\192.168.0.60\b_gamemode\openstaging\b_val\0\b_password\1"+"\r\n", - "UTM #GSP!worms3!Ml4lz344lM :MDM |Obj|3|Land.Time|0|LogicalSeed|3891226431|GraphicalSeed|3269271590|Land.RealSeed|3281489942|Land.Theme|Pirate.Lumps|LevelToUse|FE.Level.RandomLand|Land.Ind|0|Wormpot.Reel1|17|Wormpot.Reel2|17|Wormpot.Reel3|17|TimeStamp|6206364", - "UTM #GSP!worms3!Ml4lz344lM :TDM aA", - "UTM #GSP!worms3!Ml4lz344lM :SDM ASFE.Scheme.StandardCUnAACADCBBCACBBFFBKBB8C/C3C!A!A*C*C() - { - "CRYPT des 1 worms3\r\n", - "USRIP\r\n", - "USER X419pGl4sX|7 127.0.0.1 peerchat.gamespy.com :5bb4f409fae8bc5aa1595cb6d5168a1c\r\n", - "NICK worms20\r\n", - "JOIN #GPG!622\r\n" , - "MODE #GPG!622\r\n", - @"GETCKEY #GPG!622 * 008 0 :\username\b_flags"+"\r\n", - "JOIN #GSP!worms3!Ml4lz344lM\r\n" , - "MODE #GSP!worms3!Ml4lz344lM\r\n", - @"SETCKEY #GPG!622 worms20 :\b_flags\s"+"\r\n", - @"SETCKEY #GSP!worms3!Ml4lz344lM worms20 :\b_flags\s"+"\r\n", - @"GETCKEY #GSP!worms3!Ml4lz344lM * 009 0 :\username\b_flags"+"\r\n", - // "PART #GPG!622 :Joined staging room"+"\r\n", - "UTM #GSP!worms3!Ml4lz344lM :APE [01]privateip[02]192.168.0.141[01]publicip[02]255.255.255.255\r\n", - "WHO worms10"+"\r\n", - @"GETCKEY #GSP!worms3!Ml4lz344lM worms10 010 0 :\b_firewall\b_profileid\b_ipaddress\b_publicip\b_privateip\b_authresponse\b_gamever\b_val", - "WHO worms20"+"\r\n" - }; - // first process client2, then client1 will get client2 in channel - foreach (var raw in request1) - { - ((ITestClient)client1).TestReceived(UniSpyEncoding.GetBytes(raw)); - } - ; - foreach (var raw in request2) - { - ((ITestClient)client2).TestReceived(UniSpyEncoding.GetBytes(raw)); - } - } - [Fact(Skip = "Error in full test")] - public void Worm3dTest20220613() - { - - var request1 = new List() - { - // "CRYPT des 1 worms3\r\n", - "USRIP\r\n", - "USER X419pGl4sX|7 127.0.0.1 peerchat.gamespy.com :9964fa3fe73f6a1fbb986d2a04b1eb65\r\n", - "NICK worms10\r\n", - "JOIN #GPG!622\r\n", - "MODE #GPG!622\r\n", - @"GETCKEY #GPG!622 * 000 0 :\username\b_flags"+"\r\n", - "PRIVMSG #GPG!622 :hello\r\n", - "JOIN #GSP!worms3!MJ0NJ4c3aM\r\n", - "MODE #GSP!worms3!MJ0NJ4c3aM\r\n", - @"SETCKEY #GPG!622 worms10 :\b_flags\s\r\n", - @"SETCKEY #GSP!worms3!MJ0NJ4c3aM worms10 :\b_flags\sh"+"\r\n", - @"GETCKEY #GSP!worms3!MJ0NJ4c3aM * 001 0 :\username\b_flags"+"\r\n", - "TOPIC #GSP!worms3!MJ0NJ4c3aM :main lobby message test\r\n", - "MODE #GSP!worms3!MJ0NJ4c3aM +l 2"+"\r\n", - // "PART #GPG!622 :Joined staging room\r\n", - @"SETCKEY #GSP!worms3!MJ0NJ4c3aM worms10 :\b_firewall\1\b_profileid\7\b_ipaddress\\b_publicip\255.255.255.255\b_privateip\192.168.0.145\b_authresponse\\b_gamever\1073\b_val\0\r\n", - "WHO worms10"+"\r\n", - @"SETCHANKEY #GSP!worms3!MJ0NJ4c3aM :\b_hostname\\b_hostport\\b_MaxPlayers\2\b_NumPlayers\0\b_SchemeChanging\0\b_gamever\1073\b_gametype\\b_mapname\Random\b_firewall\1\b_publicip\255.255.255.255\b_privateip\192.168.0.145\b_gamemode\openstaging\b_val\0\b_password\1"+"\r\n", - "PRIVMSG #GSP!worms3!MJ0NJ4c3aM :staging lobby message test"+"\r\n", - @"UTM #GSP!worms3!MJ0NJ4c3aM :ATS \nick\worms10\msg\2046\|name|Human Team 1|w0|Dave|w1|Patrick|w2|The Morriss|w3|Mike|w4|Tony|w5|Gluckman|skill|0|grave|0|SWeapon|0|flag|71|speech|Classic|InGame|0|player|worms10|alliance|1|wormCount|77111416"+"\r\n", - @"UTM #GSP!worms3!MJ0NJ4c3aM :RTS \team\Human Team 1\nick\worms10\msg\2174"+"\r\n" - }; - - var request2 = new List() - { - // "CRYPT des 1 worms3\r\n", - "USRIP\r\n", - "USER X419pGl4sX|6 127.0.0.1 peerchat.gamespy.com :dd6283e1e349806c20991020e0d6897a\r\n", - "NICK xiaojiuwo5\r\n", - "JOIN #GPG!622\r\n" , - "MODE #GPG!622\r\n", - @"GETCKEY #GPG!622 * 000 0 :\username\b_flags"+"\r\n", - "PING\r\n", - "PRIVMSG #GPG!622 :hello from the other side\r\n", - "JOIN #GSP!worms3!MJ0NJ4c3aM\r\n", - "MODE #GSP!worms3!MJ0NJ4c3aM\r\n", - @"SETCKEY #GPG!622 xiaojiuwo5 :\b_flags\s"+"\r\n", - @"SETCKEY #GSP!worms3!MJ0NJ4c3aM xiaojiuwo5 :\b_flags\s"+"\r\n", - @"GETCKEY #GSP!worms3!MJ0NJ4c3aM * 001 0 :\username\b_flags"+"\r\n", - // "PART #GPG!622 :Joined staging room\r\n", - "UTM #GSP!worms3!MJ0NJ4c3aM :APE [01]privateip[02]192.168.0.109[01]publicip[02]255.255.255.255\r\n", - "WHO xiaojiuwo5\r\n", - // "PART #GSP!worms3!MJ0NJ4c3aM :Left Game\r\n" - }; - var client1 = MockObject.CreateClient(); - var client2 = MockObject.CreateClient(); - - foreach (var raw in request1) - { - ((ITestClient)client1).TestReceived(UniSpyEncoding.GetBytes(raw)); - } - foreach (var raw in request2) - { - ((ITestClient)client2).TestReceived(UniSpyEncoding.GetBytes(raw)); - } - var userCount = ChannelManager.Channels.First().Value.Users.Count; - Assert.Equal(2, userCount); - int count1 = ((Client)client1).Info.JoinedChannels.Count(); - Assert.Equal(2, count1); - int count2 = ((Client)client2).Info.JoinedChannels.Count(); - Assert.Equal(2, count2); - - } - [Fact] - public void ConflictGlobalStorm() - { - var client = MockObject.CreateClient(); - - var request = new List() - { - // "CRYPT des 1 conflictsopc\r\n", - ":s 705 * WKNYSMENXOZQHYVS MIYLETFVYDMBDFFV\r\n", - "LOGIN 1 cgs1 149815eb972b3c370dee3b89d645ae14\r\n" - }; - foreach (var raw in request) - { - ((ITestClient)client).TestReceived(UniSpyEncoding.GetBytes(raw)); - } - } - - [Fact] - public void Worm3d20230309() - { - var client1 = MockObject.CreateClient("91.52.107.144", 42292); - var client2 = MockObject.CreateClient("91.52.107.144", 50187); - - // Given - var requests = new List>() - { - new KeyValuePair(client1,"USRIP"+"\r\n"), - new KeyValuePair(client1,"USER XO4Gqlff1X|1 127.0.0.1 peerchat.gamespy.com :e60465b8fb4bc71d36812797f498fc5b" + "\r\n"), - new KeyValuePair(client1,"NICK spyguy" + "\r\n"), - - new KeyValuePair(client1,"JOIN #GSP!worms3!Mllz4DcahM" + "\r\n"), - new KeyValuePair(client1,"MODE #GSP!worms3!Mllz4DcahM" + "\r\n"), - new KeyValuePair(client1,@"SETCKEY #GSP!worms3!Mllz4DcahM spyguy :\b_flags\sh" + "\r\n"), - new KeyValuePair(client1,@"GETCKEY #GSP!worms3!Mllz4DcahM * 001 0 :\username\b_flags" + "\r\n"), - new KeyValuePair(client1,"TOPIC #GSP!worms3!Mllz4DcahM :test" + "\r\n"), - new KeyValuePair(client1,"MODE #GSP!worms3!Mllz4DcahM +l 2" + "\r\n"), - new KeyValuePair(client1,@"SETCKEY #GSP!worms3!Mllz4DcahM spyguy :\b_firewall\1\b_profileid\1\b_ipaddress\\b_publicip\91.52.107.144\b_privateip\192.168.0.50\b_authresponse\\b_gamever\1073\b_val\0" + "\r\n"), - new KeyValuePair(client1,"WHO spyguy" + "\r\n"), - new KeyValuePair(client1,@"SETCHANKEY #GSP!worms3!Mllz4DcahM :\b_hostname\\b_hostport\\b_MaxPlayers\4\b_NumPlayers\0\b_SchemeChanging\0\b_gamever\1073\b_gametype\\b_mapname\Random\b_firewall\1\b_publicip\91.52.107.144\b_privateip\192.168.0.50\b_gamemode\openstaging\b_val\0\b_password\1" + "\r\n"), - - - - new KeyValuePair(client2,"USRIP" + "\r\n"), - new KeyValuePair(client2,"USER XO4Gqlff1X|31 127.0.0.1 peerchat.gamespy.com :a54aaa669bd5cd97e7799659de33ed22" + "\r\n"), - new KeyValuePair(client2,"NICK unispy" + "\r\n"), - new KeyValuePair(client2,"JOIN #GSP!worms3!Mllz4DcahM" + "\r\n"), - new KeyValuePair(client2,"MODE #GSP!worms3!Mllz4DcahM" + "\r\n"), - - new KeyValuePair(client1,@"GETKEY unispy 002 0 :\b_firewall\b_profileid\b_ipaddress\b_publicip\b_privateip\b_authresponse\b_gamever\b_val" + "\r\n"), - new KeyValuePair(client1,@"GETCKEY #GSP!worms3!Mllz4DcahM unispy 003 0 :\b_firewall\b_profileid\b_ipaddress\b_publicip\b_privateip\b_authresponse\b_gamever\b_val" + "\r\n"), - new KeyValuePair(client1,@"SETCHANKEY #GSP!worms3!Mllz4DcahM :\b_hostname\\b_hostport\\b_MaxPlayers\4\b_NumPlayers\0\b_SchemeChanging\0\b_gamever\1073\b_gametype\\b_mapname\Random\b_firewall\1\b_publicip\91.52.107.144\b_privateip\192.168.0.50\b_gamemode\openstaging\b_val\0\b_password\1" + "\r\n"), - new KeyValuePair(client1,@"SETCHANKEY #GSP!worms3!Mllz4DcahM :\b_hostname\\b_hostport\\b_MaxPlayers\4\b_NumPlayers\0\b_SchemeChanging\0\b_gamever\1073\b_gametype\\b_mapname\Random\b_firewall\1\b_publicip\91.52.107.144\b_privateip\192.168.0.50\b_gamemode\openstaging\b_val\0\b_password\1" + "\r\n"), - new KeyValuePair(client1,"UTM #GSP!worms3!Mllz4DcahM :MDM |Obj|3|Land.Time|0|LogicalSeed|237235259|GraphicalSeed|4280690287|Land.RealSeed|2147483642|Land.Theme|Pirate.Lumps|LevelToUse|FE.Level.RandomLand|Land.Ind|0|Wormpot.Reel1|17|Wormpot.Reel2|17|Wormpot.Reel3|17|TimeStamp|98044" + "\r\n"), - new KeyValuePair(client1,"UTM #GSP!worms3!Mllz4DcahM :TDM aA" + "\r\n"), - new KeyValuePair(client1,"UTM #GSP!worms3!Mllz4DcahM :SDM ASFE.Scheme.StandardCUnAACADCBBCACBBFFBKBB8C/C3C!A!A*C*C(client2,@"GETCKEY #GSP!worms3!Mllz4DcahM * 008 0 :\username\b_flags" + "\r\n"), - new KeyValuePair(client2,"UTM #GSP!worms3!Mllz4DcahM :APE [01]privateip[02]192.168.0.113[01]publicip[02]91.52.107.144" + "\r\n"), - new KeyValuePair(client2,"WHO unispy" + "\r\n"), - new KeyValuePair(client2,@"GETCKEY #GSP!worms3!Mllz4DcahM spyguy 009 0 :\b_firewall\b_profileid\b_ipaddress\b_publicip\b_privateip\b_authresponse\b_gamever\b_val") - }; - foreach (var item in requests) - { - ((ITestClient)(item.Key)).TestReceived(UniSpyEncoding.GetBytes(item.Value)); - } - } - - [Fact] - public void CrysisWars20230514() - { - // Given - // some game just use chat to authenticate do not use chat server to chat - var client = MockObject.CreateClient(); - var requests = new List() - { - "CRYPT des 1 crysiswars\r\n", - "LOGIN 56 crysiswars3 4f83fb3e73b69253048ab90d9efb335c\r\n", - "USER 127.0.0.1 peerchat.gamespy.com :\r\nNICK *\r\n", - "LIST *\r\nJOIN #gsp!crysiswars\r\n", - "MODE #gsp!crysiswars\r\nSETCKEY #gsp!crysiswars crysiswars3-cry "+@":\Profile\11\\DE\TimePlayed\0\Accuracy\0\KillsPerMinute\0\Kills\0\Deaths\0\FavoriteGameMode\\FavoriteMap\\FavoriteWeapon\\FavoriteVehicle\\FavoriteSuitMode\"+"\r\n" - }; - foreach (var req in requests) - { - (client as ITestClient).TestReceived(UniSpyEncoding.GetBytes(req)); - } - } - - [Fact] - public void WormsFortsUnderSiege20230520() - { - var client = MockObject.CreateClient(); - var requests = new List() - { - "CRYPT des 1 wormsforts\r\n", - "LOGIN 1 wforts 149815eb972b3c370dee3b89d645ae14\r\n", - "USRIP\r\n", - "USER XaWqp4Df1X|19 127.0.0.1 peerchat.gamespy.com :52d55c23867fcafe3453c00a3a395503\r\nNICK *\r\n" - }; - foreach (var req in requests) - { - (client as ITestClient).TestReceived(UniSpyEncoding.GetBytes(req)); - } - } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/test/General/GeneralRequestTest.cs b/src/Servers/Chat/test/General/GeneralRequestTest.cs deleted file mode 100644 index a56a2f83f..000000000 --- a/src/Servers/Chat/test/General/GeneralRequestTest.cs +++ /dev/null @@ -1,220 +0,0 @@ -using Xunit; -using UniSpy.Server.Chat.Contract.Request.General; - -namespace UniSpy.Server.Chat.Test.General -{ - public class GeneralRequestTest - { - [Fact] - public void CDKey() - { - var request = new CdKeyRequest(GeneralRequests.CDKey); - request.Parse(); - Assert.Equal("XXXX-XXXX-XXXX-XXXX", request.CdKey); - } - - [Fact] - public void Crypt() - { - var request = new CryptRequest(GeneralRequests.Crypt); - request.Parse(); - Assert.Equal("1", request.VersionID); - Assert.Equal("gmtest", request.GameName); - } - - [Fact] - public void GetKey() - { - var request = new GetKeyRequest(GeneralRequests.GetKey); - request.Parse(); - Assert.Equal("spyguy", request.NickName); - Assert.Equal("004", request.Cookie); - Assert.Equal("0", request.UnkownCmdParam); - Assert.Equal("b_firewall", request.Keys[0]); - Assert.Equal("b_profileid", request.Keys[1]); - Assert.Equal("b_ipaddress", request.Keys[2]); - Assert.Equal("b_publicip", request.Keys[3]); - Assert.Equal("b_privateip", request.Keys[4]); - Assert.Equal("b_authresponse", request.Keys[5]); - Assert.Equal("b_gamever", request.Keys[6]); - Assert.Equal("b_val", request.Keys[7]); - } - - [Fact(Skip = "No reqeust")] - public void GetUdpRelay() - { - var request = new GetUdpRelayRequest(GeneralRequests.GetUdpRelay); - request.Parse(); - } - - [Fact] - public void Invite() - { - var request = new InviteRequest(GeneralRequests.Invite); - request.Parse(); - Assert.Equal("test", request.ChannelName); - Assert.Equal("spyguy", request.NickName); - } - - [Fact] - public void ListLimit() - { - var request = new ListLimitRequest(GeneralRequests.ListLimit); - request.Parse(); - Assert.Equal("5", request.MaxNumberOfChannels.ToString()); - Assert.Equal("test", request.Filter); - } - - [Fact] - public void List() - { - var request = new ListRequest(GeneralRequests.List); - request.Parse(); - Assert.Equal("test", request.Filter); - } - - [Fact] - public void LoginPreAuth() - { - var request = new LoginPreAuth(GeneralRequests.LoginPreAuth); - request.Parse(); - Assert.Equal("xxxxx", request.AuthToken); - Assert.Equal("yyyyy", request.PartnerChallenge); - } - - [Fact] - public void LoginNickAndEmail() - { - var request = new LoginRequest(GeneralRequests.LoginNickAndEmail); - request.Parse(); - Assert.Equal(LoginReqeustType.NickAndEmailLogin, request.ReqeustType); - Assert.Equal("0", request.NamespaceId.ToString()); - Assert.Equal("spyguy", request.NickName); - Assert.Equal("xxxxx", request.PasswordHash); - Assert.Equal("spyguy@unispy.org", request.Email); - } - - [Fact] - public void LoginUniqueNick() - { - var request = new LoginRequest(GeneralRequests.LoginUniqueNick); - request.Parse(); - Assert.Equal(LoginReqeustType.UniqueNickLogin, request.ReqeustType); - Assert.Equal("0", request.NamespaceId.ToString()); - Assert.Equal("spyguy", request.UniqueNick); - Assert.Equal("xxxxx", request.PasswordHash); - } - - [Fact(Skip = "No reqeust")] - public void Names() - { - var request = new NamesRequest(GeneralRequests.Names); - request.Parse(); - } - - [Fact] - public void Nick() - { - var request = new NickRequest(GeneralRequests.Nick); - request.Parse(); - Assert.Equal("spyguy", request.NickName); - } - - [Fact(Skip = "No reqeust")] - public void Ping() - { - var request = new PingRequest(GeneralRequests.Ping); - request.Parse(); - } - - [Fact] - public void Pong() - { - var request = new PongRequest(GeneralRequests.Pong); - request.Parse(); - Assert.Equal("Pong!", request.EchoMessage); - } - - [Fact] - public void Quit() - { - var request = new QuitRequest(GeneralRequests.Quit); - request.Parse(); - Assert.Equal("Later!", request.Reason); - } - - [Fact] - public void RegisterNick() - { - var request = new RegisterNickRequest(GeneralRequests.RegisterNick); - request.Parse(); - Assert.Equal("0", request.NamespaceID); - Assert.Equal("spyguy", request.UniqueNick); - Assert.Equal("XXXX-XXXX-XXXX-XXXX", request.CDKey); - } - - [Fact] - public void SetGroup() - { - var request = new SetGroupRequest(GeneralRequests.SetGroup); - request.Parse(); - Assert.Equal("test", request.GroupName); - } - - [Fact(Skip = "TODO: add test")] - public void SetKey() - { - var request = new SetKeyRequest(GeneralRequests.SetKey); - request.Parse(); - } - - [Fact(Skip = "No reqeust")] - public void UserIP() - { - var request = new UserIPRequest(GeneralRequests.UserIP); - request.Parse(); - } - - [Fact] - public void User() - { - var request = new UserRequest(GeneralRequests.User); - request.Parse(); - Assert.Equal("spyguy", request.UserName); - Assert.Equal("127.0.0.1", request.Hostname); - Assert.Equal("peerchat.unispy.org", request.ServerName); - Assert.Equal("spyguy2", request.Name); - - request = new UserRequest("USER 127.0.0.1 peerchat.gamespy.com :"); - request.Parse(); - Assert.Equal("127.0.0.1", request.Hostname); - Assert.Equal("peerchat.gamespy.com", request.ServerName); - } - - [Fact] - public void WhoIs() - { - var request = new WhoIsRequest(GeneralRequests.WhoIs); - request.Parse(); - Assert.Equal("spyguy", request.NickName); - } - - [Fact] - public void WhoChannelUsersInfo() - { - var request = new WhoRequest(GeneralRequests.WhoChannelUsersInfo); - request.Parse(); - Assert.Equal(WhoRequestType.GetChannelUsersInfo, request.RequestType); - Assert.Equal("#room", request.ChannelName); - } - - [Fact] - public void WhoUserInfo() - { - var request = new WhoRequest(GeneralRequests.WhoUserInfo); - request.Parse(); - Assert.Equal(WhoRequestType.GetUserInfo, request.RequestType); - Assert.Equal("spyguy", request.NickName); - } - } -} diff --git a/src/Servers/Chat/test/General/GeneralRequests.cs b/src/Servers/Chat/test/General/GeneralRequests.cs deleted file mode 100644 index 34fb6e235..000000000 --- a/src/Servers/Chat/test/General/GeneralRequests.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace UniSpy.Server.Chat.Test.General -{ - public class GeneralRequests - { - public const string CDKey = "CDKEY XXXX-XXXX-XXXX-XXXX"; - - public const string Crypt = "CRYPT des 1 gmtest"; - - public const string GetKey = "GETKEY spyguy 004 0 :\\b_firewall\\b_profileid\\b_ipaddress\\b_publicip\\b_privateip\\b_authresponse\\b_gamever\\b_val"; // CRLF - - public const string GetUdpRelay = "GETUDPRELAY"; - - public const string Invite = "INVITE test spyguy"; - - public const string ListLimit = "LISTLIMIT 5 test"; - - public const string List = "LIST test"; - - public const string LoginPreAuth = "LOGINPREAUTH xxxxx yyyyy"; - - public const string LoginNickAndEmail = "LOGIN 0 * xxxxx :spyguy@spyguy@unispy.org"; // TODO: add binary data test [0D][0A] - - public const string LoginUniqueNick = "LOGIN 0 spyguy xxxxx"; - - public const string Names = "NAMES"; - - public const string Nick = "NICK :spyguy"; - - public const string Ping = "PING"; // TODO: add binary data test [0D][0A] - - public const string Pong = "PONG :Pong!"; - - public const string Quit = "QUIT :Later!"; // TODO: add binary data test [0D][0A] - - public const string RegisterNick = "REGISTERNICK 0 spyguy XXXX-XXXX-XXXX-XXXX"; - - public const string SetGroup = "SETGROUP test"; - - public const string SetKey = "SETKEY :test"; - - public const string UserIP = "USRIP"; - - public const string User = "USER spyguy 127.0.0.1 peerchat.unispy.org :spyguy2"; - - public const string WhoIs = "WHOIS spyguy"; - - public const string WhoChannelUsersInfo = "WHO #room"; - - public const string WhoUserInfo = "WHO spyguy"; - } -} diff --git a/src/Servers/Chat/test/Message/MessageRequestTest.cs b/src/Servers/Chat/test/Message/MessageRequestTest.cs deleted file mode 100644 index 81fe0dc85..000000000 --- a/src/Servers/Chat/test/Message/MessageRequestTest.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Xunit; -using UniSpy.Server.Chat.Contract.Request.Message; -using UniSpy.Server.Chat.Abstraction.BaseClass; - -namespace UniSpy.Server.Chat.Test.Message -{ - public class MessageRequestTest - { - - [Fact] - public void AboveTheTableMsg() - { - var request = new AtmRequest(MessageRequests.AboveTheTableMsg); - request.Parse(); - Assert.Equal(MessageType.ChannelMessage, request.Type); - Assert.Null(request.NickName); - Assert.Equal("#GSP!room!test", request.ChannelName); - } - - [Fact] - public void Notice() - { - var request = new NoticeRequest(MessageRequests.Notice); - request.Parse(); - Assert.Equal(MessageType.ChannelMessage, request.Type); - Assert.Null(request.NickName); - Assert.Equal("#GSP!room!test", request.ChannelName); - } - - [Fact] - public void PrivateMsg() - { - var request = new PrivateRequest(MessageRequests.PrivateMsg); - request.Parse(); - Assert.Equal(MessageType.ChannelMessage, request.Type); - Assert.Null(request.NickName); - Assert.Equal("#GSP!room!test", request.ChannelName); - } - - [Fact] - public void UnderTheTableMsg() - { - var request = new UtmRequest(MessageRequests.UnderTheTableMsg); - request.Parse(); - Assert.Equal(MessageType.ChannelMessage, request.Type); - Assert.Null(request.NickName); - Assert.Equal("#GSP!room!test", request.ChannelName); - } - } -} diff --git a/src/Servers/Chat/test/Message/MessageRequests.cs b/src/Servers/Chat/test/Message/MessageRequests.cs deleted file mode 100644 index e4c4b96ad..000000000 --- a/src/Servers/Chat/test/Message/MessageRequests.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace UniSpy.Server.Chat.Test.Message -{ - public class MessageRequests - { - public const string AboveTheTableMsg = "ATM #GSP!room!test :hello this is a test."; - - public const string Notice = "NOTICE #GSP!room!test :hello this is a test."; - - public const string PrivateMsg = "PRIVMSG #GSP!room!test :hello this is a test."; - - public const string UnderTheTableMsg = "UTM #GSP!room!test :hello this is a test."; - - public const string ActionMsg = "PRIVMSG #GSP!room!test :\001ACTION hello this is a test.\001"; - } -} diff --git a/src/Servers/Chat/test/MockObject.cs b/src/Servers/Chat/test/MockObject.cs deleted file mode 100644 index 3c38a8b16..000000000 --- a/src/Servers/Chat/test/MockObject.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Net; -using Moq; -using UniSpy.Server.Chat.Application; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.Chat.Test -{ - public class MockObject - { - public static IClient CreateClient(string ipAddress = "79.209.235.252", int port = 50558) - { - var managerMock = new Mock(); - var connectionMock = new Mock(); - connectionMock.Setup(s => s.RemoteIPEndPoint).Returns(new IPEndPoint(IPAddress.Parse(ipAddress), port)); - connectionMock.Setup(s => s.Manager).Returns(managerMock.Object); - connectionMock.Setup(s => s.ConnectionType).Returns(NetworkConnectionType.Tcp); - var serverMock = new Chat.Application.Server(managerMock.Object); - var client = new Client(connectionMock.Object, serverMock); - client.Info.GameName = "gmtest"; - return client; - } - } -} \ No newline at end of file diff --git a/src/Servers/Chat/test/RedisChatChannelTest.cs b/src/Servers/Chat/test/RedisChatChannelTest.cs deleted file mode 100644 index a34b0daac..000000000 --- a/src/Servers/Chat/test/RedisChatChannelTest.cs +++ /dev/null @@ -1,166 +0,0 @@ -using UniSpy.Server.Chat.Application; -using Xunit; -using Newtonsoft.Json; -using UniSpy.Server.Chat.Aggregate.Redis.Contract; -using UniSpy.Server.Chat.Contract.Request.Channel; -using UniSpy.Server.Chat.Test.Channel; -using UniSpy.Server.Chat.Handler.CmdHandler.Channel; -using UniSpy.Server.Chat.Aggregate; -using UniSpy.Server.Chat.Aggregate.Redis; -using UniSpy.Server.Core.Encryption; -using UniSpy.Server.Chat.Contract.Request.General; -using UniSpy.Server.Chat.Test.General; -using UniSpy.Server.Core.Abstraction.Interface; -using System.Collections.Generic; -using System.Net; -using Moq; - -namespace UniSpy.Server.Chat.Test -{ - public class RedisChatChannelTest - { - public RedisChatChannelTest() - { - var mockServer = new Mock(); - mockServer.Setup(s => s.PublicIPEndPoint).Returns(IPEndPoint.Parse("202.91.0.1:123")); - mockServer.Setup(s => s.Id).Returns(System.Guid.Parse("00000000-0000-0000-0000-000000000000")); - ServerLauncher.ServerInstances.Add(mockServer.Object); - } - - [Fact] - public void JsonSerialization() - { - var client = MockObject.CreateClient() as Client; - client.Info.IsLoggedIn = true; - client.Info.NickName = "xiaojiuwo1"; - var remoteClient = client.GetRemoteClient(); - var request = new JoinRequest(ChannelRequests.Join); - request.Parse(); - var clientStr = JsonConvert.SerializeObject(remoteClient); - var clientObj = JsonConvert.DeserializeObject(clientStr); - var message = new RemoteMessage(request, remoteClient); - var msgStr = JsonConvert.SerializeObject(message); - var msgObj = JsonConvert.DeserializeObject(msgStr); - Assert.True(msgObj.Type == "JOIN"); - var req = new JoinRequest(UniSpyEncoding.GetString(msgObj.RawRequest)); - var handler = new JoinHandler(msgObj.Client, req); - handler.Handle(); - Assert.True(((ClientInfo)(msgObj.Client.Info)).JoinedChannels.Count == 1); - } - [Fact] - public void RedisChannel() - { - var client = MockObject.CreateClient() as Client; - - client.Info.IsLoggedIn = true; - client.Info.NickName = "xiaojiuwo2"; - var remoteClient = client.GetRemoteClient(); - var request = new JoinRequest(ChannelRequests.Join); - request.Parse(); - var message = new RemoteMessage(request, remoteClient); - var msgStr = JsonConvert.SerializeObject(message); - var msgObj = JsonConvert.DeserializeObject(msgStr); - var chan = new GeneralMessageChannel(); - chan.ReceivedMessage(msgObj); - } - [Fact] - public void Crypt() - { - - var request1 = new DisconnectRequest(); - var client = MockObject.CreateClient() as Client; - - client.Info.IsLoggedIn = true; - client.Info.NickName = "xiaojiuwo3"; - var remoteClient = client.GetRemoteClient(); - var request = new CryptRequest(GeneralRequests.Crypt); - request.Parse(); - var message = new RemoteMessage(request, remoteClient); - var chan = new GeneralMessageChannel(); - chan.ReceivedMessage(message); - } - [Fact] - public void GeneralTest() - { - var type = typeof(GeneralRequests); - // var fields = type.GetFields(); - var request1 = new List() - { - "CRYPT des 1 worms3\r\n", - "USRIP\r\n", - "USER X419pGl4sX|7 127.0.0.1 peerchat.gamespy.com :9964fa3fe73f6a1fbb986d2a04b1eb65\r\n", - "NICK worms10\r\n", - "JOIN #GPG!622\r\n", - "MODE #GPG!622\r\n", - @"GETCKEY #GPG!622 * 000 0 :\username\b_flags"+"\r\n", - "PRIVMSG #GPG!622 :hello\r\n", - "JOIN #GSP!worms3!MJ0NJ4c3aM\r\n", - "MODE #GSP!worms3!MJ0NJ4c3aM\r\n", - @"SETCKEY #GPG!622 worms10 :\b_flags\s\r\n", - @"SETCKEY #GSP!worms3!MJ0NJ4c3aM worms10 :\b_flags\sh"+"\r\n", - @"GETCKEY #GSP!worms3!MJ0NJ4c3aM * 001 0 :\username\b_flags"+"\r\n", - "TOPIC #GSP!worms3!MJ0NJ4c3aM :main lobby message test\r\n", - "MODE #GSP!worms3!MJ0NJ4c3aM +l 2"+"\r\n", - "PART #GPG!622 :Joined staging room\r\n", - @"SETCKEY #GSP!worms3!MJ0NJ4c3aM worms10 :\b_firewall\1\b_profileid\7\b_ipaddress\\b_publicip\255.255.255.255\b_privateip\192.168.0.145\b_authresponse\\b_gamever\1073\b_val\0\r\n", - "WHO worms10"+"\r\n", - @"SETCHANKEY #GSP!worms3!MJ0NJ4c3aM :\b_hostname\\b_hostport\\b_MaxPlayers\2\b_NumPlayers\0\b_SchemeChanging\0\b_gamever\1073\b_gametype\\b_mapname\Random\b_firewall\1\b_publicip\255.255.255.255\b_privateip\192.168.0.145\b_gamemode\openstaging\b_val\0\b_password\1"+"\r\n", - "PRIVMSG #GSP!worms3!MJ0NJ4c3aM :staging lobby message test"+"\r\n", - @"UTM #GSP!worms3!MJ0NJ4c3aM :ATS \nick\worms10\msg\2046\|name|Human Team 1|w0|Dave|w1|Patrick|w2|The Morriss|w3|Mike|w4|Tony|w5|Gluckman|skill|0|grave|0|SWeapon|0|flag|71|speech|Classic|InGame|0|player|worms10|alliance|1|wormCount|77111416"+"\r\n", - @"UTM #GSP!worms3!MJ0NJ4c3aM :RTS \team\Human Team 1\nick\worms10\msg\2174"+"\r\n" - }; - var client1 = MockObject.CreateClient(port: 1234) as Client; - // Client.ClientPool.Remove(client1.Connection.RemoteIPEndPoint, out _); - ClientManager.RemoveClient(client1); - var remoteClient = client1.GetRemoteClient() as ITestClient; - ClientManager.AddClient((IClient)remoteClient); - foreach (var r in request1) - { - var count = ClientManager.ClientPool.Count; - remoteClient.TestReceived(UniSpyEncoding.GetBytes(r)); - count = ClientManager.ClientPool.Count; - } - // IChatClient - var request2 = new List() - { - // "CRYPT des 1 worms3\r\n", - "USRIP\r\n", - "USER X419pGl4sX|6 127.0.0.1 peerchat.gamespy.com :dd6283e1e349806c20991020e0d6897a\r\n", - "NICK xiaojiuwo4\r\n", - "JOIN #GPG!622\r\n" , - "MODE #GPG!622\r\n", - @"GETCKEY #GPG!622 * 000 0 :\username\b_flags"+"\r\n", - "PING\r\n", - "PRIVMSG #GPG!622 :hello from the other side\r\n", - "JOIN #GSP!worms3!MJ0NJ4c3aM\r\n", - "MODE #GSP!worms3!MJ0NJ4c3aM\r\n", - @"SETCKEY #GPG!622 xiaojiuwo4 :\b_flags\s"+"\r\n", - @"SETCKEY #GSP!worms3!MJ0NJ4c3aM xiaojiuwo4 :\b_flags\s"+"\r\n", - @"GETCKEY #GSP!worms3!MJ0NJ4c3aM * 001 0 :\username\b_flags"+"\r\n", - // "PART #GPG!622 :Joined staging room\r\n", - "UTM #GSP!worms3!MJ0NJ4c3aM :APE [01]privateip[02]192.168.0.109[01]publicip[02]255.255.255.255\r\n", - "WHO xiaojiuwo4\r\n", - // "PART #GSP!worms3!MJ0NJ4c3aM :Left Game\r\n" - }; - var client2 = MockObject.CreateClient(port: 1235) as ITestClient; - foreach (var r in request2) - { - var count = ClientManager.ClientPool.Count; - client2.TestReceived(UniSpyEncoding.GetBytes(r)); - count = ClientManager.ClientPool.Count; - } - } - [Fact] - public void ChannelInfoTest() - { - var client = MockObject.CreateClient() as Client; - client.Info.IsLoggedIn = true; - client.Info.NickName = "xiaojiuwo"; - var channel = ChannelManager.CreateChannel("xiaojiuwo", creator: client); - var user = channel.GetUser(client); - - var channelStr = JsonConvert.SerializeObject(channel.GetChannelCache()); - var channelObj = JsonConvert.DeserializeObject(channelStr); - } - } -} diff --git a/src/Servers/Chat/test/UniSpy.Server.Chat.Test.csproj b/src/Servers/Chat/test/UniSpy.Server.Chat.Test.csproj deleted file mode 100644 index 4970e5e64..000000000 --- a/src/Servers/Chat/test/UniSpy.Server.Chat.Test.csproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - net6.0 - false - ..\..\..\..\common\Icon\UniSpy_Logo.ico - - - AnyCPU - ..\..\..\..\build\$(Configuration) - - - ..\..\..\..\build\$(Configuration) - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - - \ No newline at end of file diff --git a/src/Servers/GameStatus/src/Abstraction/BaseClass/CmdHandlerBase.cs b/src/Servers/GameStatus/src/Abstraction/BaseClass/CmdHandlerBase.cs deleted file mode 100755 index fceb1c697..000000000 --- a/src/Servers/GameStatus/src/Abstraction/BaseClass/CmdHandlerBase.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.GameStatus.Application; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.GameStatus.Abstraction.BaseClass -{ - /// - /// we only use selfdefine error code here - /// so we do not need to send it to client - /// - public abstract class CmdHandlerBase : UniSpy.Server.Core.Abstraction.BaseClass.CmdHandlerBase - { - protected new Client _client => (Client)base._client; - protected new RequestBase _request => (RequestBase)base._request; - protected new ResultBase _result { get => (ResultBase)base._result; set => base._result = value; } - protected CmdHandlerBase(IClient client, IRequest request) : base(client, request) - { - } - } -} diff --git a/src/Servers/GameStatus/src/Abstraction/BaseClass/RequestBase.cs b/src/Servers/GameStatus/src/Abstraction/BaseClass/RequestBase.cs deleted file mode 100755 index bd8b0098c..000000000 --- a/src/Servers/GameStatus/src/Abstraction/BaseClass/RequestBase.cs +++ /dev/null @@ -1,52 +0,0 @@ - -using System.Collections.Generic; -using System.Linq; -using UniSpy.Server.Core.Misc; - -namespace UniSpy.Server.GameStatus.Abstraction.BaseClass -{ - public abstract class RequestBase : UniSpy.Server.Core.Abstraction.BaseClass.RequestBase - { - public new string CommandName { get => (string)base.CommandName; protected set => base.CommandName = value; } - public new string RawRequest => (string)base.RawRequest; - /// - /// LocalId is used to indicate the request sequence in gamespy clients - /// - public int? LocalId { get; protected set; } - public Dictionary KeyValues { get; protected set; } - - public RequestBase(string rawRequest) : base(rawRequest) - { - } - public static Dictionary ConvertGameDataToKeyValues(string gameData) - { - var parts = gameData.Split("\u0001", System.StringSplitOptions.RemoveEmptyEntries); - return GameSpyUtils.ConvertToKeyValue(parts); - } - public override void Parse() - { - // the localid lid is used to indicate the request sequence on the client side - // we just respond it with same lid to client - KeyValues = GameSpyUtils.ConvertToKeyValue(RawRequest); - CommandName = KeyValues.Keys.First(); - - if (KeyValues.ContainsKey("lid")) - { - if (!int.TryParse(KeyValues["lid"], out var localId)) - { - throw new GameStatus.Exception("localid format is incorrect."); - } - LocalId = localId; - } - //worms 3d use id not lid so we added an condition here - if (KeyValues.ContainsKey("id")) - { - if (!int.TryParse(KeyValues["id"], out var localId)) - { - throw new GameStatus.Exception("localid format is incorrect."); - } - LocalId = localId; - } - } - } -} diff --git a/src/Servers/GameStatus/src/Abstraction/BaseClass/ResponseBase.cs b/src/Servers/GameStatus/src/Abstraction/BaseClass/ResponseBase.cs deleted file mode 100755 index fe304674b..000000000 --- a/src/Servers/GameStatus/src/Abstraction/BaseClass/ResponseBase.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace UniSpy.Server.GameStatus.Abstraction.BaseClass -{ - public abstract class ResponseBase : UniSpy.Server.Core.Abstraction.BaseClass.ResponseBase - { - protected new RequestBase _request => (RequestBase)base._request; - protected new ResultBase _result => (ResultBase)base._result; - protected new string SendingBuffer{ get => (string)base.SendingBuffer; set => base.SendingBuffer = value; } - public ResponseBase(UniSpy.Server.Core.Abstraction.BaseClass.RequestBase request, UniSpy.Server.Core.Abstraction.BaseClass.ResultBase result) : base(request, result) - { - } - - } -} diff --git a/src/Servers/GameStatus/src/Abstraction/BaseClass/ResultBase.cs b/src/Servers/GameStatus/src/Abstraction/BaseClass/ResultBase.cs deleted file mode 100755 index cdc1440fa..000000000 --- a/src/Servers/GameStatus/src/Abstraction/BaseClass/ResultBase.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace UniSpy.Server.GameStatus.Abstraction.BaseClass -{ - public abstract class ResultBase : UniSpy.Server.Core.Abstraction.BaseClass.ResultBase - { - public ResultBase() - { - } - } -} diff --git a/src/Servers/GameStatus/src/Abstraction/Interface/IStorageOperation.cs b/src/Servers/GameStatus/src/Abstraction/Interface/IStorageOperation.cs deleted file mode 100644 index 606d7894a..000000000 --- a/src/Servers/GameStatus/src/Abstraction/Interface/IStorageOperation.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.GameStatus.Enumerate; - -namespace UniSpy.Server.GameStatus.Abstraction.Interface -{ - public interface IStorageOperation - { - void CreateNewGameData(); - void CreateNewPlayerData(Dictionary playerData); - void UpdatePlayerData(int profileId, PersistStorageType storageType, int dataIndex, Dictionary data); - int GetProfileId(string token); - int GetProfileId(string cdKey, string nickName); - int GetProfileId(int profileId); - Dictionary GetPlayerData(int profileId, PersistStorageType storageType, int dataIndex); - } -} \ No newline at end of file diff --git a/src/Servers/GameStatus/src/Aggregate/Misc/GSCrypt.cs b/src/Servers/GameStatus/src/Aggregate/Misc/GSCrypt.cs deleted file mode 100755 index 9d45bba81..000000000 --- a/src/Servers/GameStatus/src/Aggregate/Misc/GSCrypt.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Linq; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Encryption; - - -namespace UniSpy.Server.GameStatus.Aggregate.Misc -{ - public class GSCrypt : ICryptography - { - /// - /// Decrypt the message, skip decrypt \final\ - /// Must contains \final\ - /// - public byte[] Decrypt(byte[] buffer) - { - if (!UniSpyEncoding.GetString(buffer).Contains(@"\final\")) - { - throw new GameStatus.Exception(@"Ciphertext must contains delimeter \final\"); - } - //remove \final\, later we add final back - byte[] cipher = buffer.Take(buffer.Length - 7).ToArray(); - byte[] plain = XOREncoding.Encode(cipher, XorType.Type1); - Array.Copy(plain, buffer, plain.Length); - return buffer; - } - /// - /// Encrypt the message, skip encrypt \final\ - /// - public byte[] Encrypt(byte[] buffer) - { - if (!UniSpyEncoding.GetString(buffer).Contains(@"\final\")) - { - throw new GameStatus.Exception(@"Plaintext must contains delimeter \final\"); - } - byte[] plain = buffer.Take(buffer.Length - 7).ToArray(); - byte[] cipher = XOREncoding.Encode(plain, XorType.Type1); - Array.Copy(cipher, buffer, cipher.Length); - return buffer; - } - } -} diff --git a/src/Servers/GameStatus/src/Application/Client.cs b/src/Servers/GameStatus/src/Application/Client.cs deleted file mode 100644 index b4402a580..000000000 --- a/src/Servers/GameStatus/src/Application/Client.cs +++ /dev/null @@ -1,51 +0,0 @@ -using UniSpy.Server.GameStatus.Aggregate.Misc; -using UniSpy.Server.GameStatus.Handler; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Encryption; -using UniSpy.Server.Core.Logging; -using System; - -namespace UniSpy.Server.GameStatus.Application -{ - public sealed class Client : ClientBase - { - public new ClientInfo Info { get => (ClientInfo)base.Info; private set => base.Info = value; } - public Client(IConnection connection, IServer server) : base(connection, server) - { - Info = new ClientInfo(); - } - protected override void OnConnected() - { - Crypto = new GSCrypt(); - this.LogNetworkSending(ClientInfo.ChallengeResponse); - Connection.Send(Crypto.Encrypt(ClientInfo.ChallengeResponseBytes)); - base.OnConnected(); - } - protected override byte[] DecryptMessage(byte[] buffer) - { - // unit test - if (Crypto is null) - { - return buffer; - } - - // multiple request; - var buffers = UniSpyEncoding.GetString(buffer).Split(@"\final\", StringSplitOptions.RemoveEmptyEntries); - if (buffers.Length > 1) - { - string message = ""; - foreach (var buf in buffers) - { - var completeBuf = UniSpyEncoding.GetBytes(buf + @"\final\"); - message += UniSpyEncoding.GetString(Crypto.Decrypt(completeBuf)); - } - return UniSpyEncoding.GetBytes(message); - } - return Crypto.Decrypt(buffer); - } - - - protected override ISwitcher CreateSwitcher(object buffer) => new CmdSwitcher(this, UniSpyEncoding.GetString((byte[])buffer)); - } -} \ No newline at end of file diff --git a/src/Servers/GameStatus/src/Application/ClientInfo.cs b/src/Servers/GameStatus/src/Application/ClientInfo.cs deleted file mode 100644 index 088d828ab..000000000 --- a/src/Servers/GameStatus/src/Application/ClientInfo.cs +++ /dev/null @@ -1,21 +0,0 @@ -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Encryption; - -namespace UniSpy.Server.GameStatus.Application -{ - public sealed class ClientInfo : ClientInfoBase - { - public const string ChallengeResponse = @"\challenge\00000000000000000000\final\"; - public static byte[] ChallengeResponseBytes => UniSpyEncoding.GetBytes(ClientInfo.ChallengeResponse); - public int? SessionKey { get; set; } - public string GameName { get; set; } - public bool IsUserAuthenticated { get; set; } - public bool IsPlayerAuthenticated { get; set; } - public bool IsGameAuthenticated { get; set; } - public int? ProfileId { get; set; } - public int? GameSessionKey { get; set; } - public ClientInfo() - { - } - } -} \ No newline at end of file diff --git a/src/Servers/GameStatus/src/Application/Program.cs b/src/Servers/GameStatus/src/Application/Program.cs deleted file mode 100755 index 332f62cb1..000000000 --- a/src/Servers/GameStatus/src/Application/Program.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using UniSpy.Server.Core.Logging; - -namespace UniSpy.Server.GameStatus.Application -{ - public class Program - { - static void Main(string[] args) - { - try - { - new ServerLauncher().Start(); - Console.WriteLine("Press < Q > to exit. "); - while (Console.ReadKey().Key != ConsoleKey.Q) { } - } - catch (System.Exception e) - { - LogWriter.LogError(e); - } - } - } -} diff --git a/src/Servers/GameStatus/src/Application/Server.cs b/src/Servers/GameStatus/src/Application/Server.cs deleted file mode 100644 index 7ec2ccd78..000000000 --- a/src/Servers/GameStatus/src/Application/Server.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Net; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Network.Tcp.Server; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.GameStatus.Application -{ - public sealed class Server : ServerBase - { - static Server() - { - _name = "GameStatus"; - } - - public Server(){ } - - public Server(IConnectionManager manager) : base(manager){} - - protected override IClient CreateClient(IConnection connection) => new Client(connection, this); - protected override IConnectionManager CreateConnectionManager(IPEndPoint endPoint) => new TcpConnectionManager(endPoint); - } -} \ No newline at end of file diff --git a/src/Servers/GameStatus/src/Application/ServerLauncher.cs b/src/Servers/GameStatus/src/Application/ServerLauncher.cs deleted file mode 100644 index dd4658ce7..000000000 --- a/src/Servers/GameStatus/src/Application/ServerLauncher.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Core.Abstraction.BaseClass.Factory; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.GameStatus.Application -{ - public sealed class ServerLauncher : ServerLauncherBase - { - protected override List LaunchNetworkService() => new List { new Server() }; - } -} \ No newline at end of file diff --git a/src/Servers/GameStatus/src/Application/StorageOperation.cs b/src/Servers/GameStatus/src/Application/StorageOperation.cs deleted file mode 100644 index 684834bc6..000000000 --- a/src/Servers/GameStatus/src/Application/StorageOperation.cs +++ /dev/null @@ -1,120 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.GameStatus.Abstraction.Interface; - -using UniSpy.Server.Core.Database.DatabaseModel; -using System.Linq; -using UniSpy.Server.GameStatus.Enumerate; - -namespace UniSpy.Server.GameStatus.Application -{ - internal sealed class StorageOperation : IStorageOperation - { - public static IStorageOperation Persistance = new StorageOperation(); - public void CreateNewGameData() - { - throw new GameStatus.Exception("Implement create storage for game data"); - } - - public void CreateNewPlayerData(Dictionary playerData) - { - throw new GameStatus.Exception("Implement create storage for player data"); - } - public void UpdatePlayerData(int profileId, PersistStorageType storageType, int dataIndex, Dictionary data) - { - using (var db = new UniSpyContext()) - { - - var result = from p in db.Pstorages - where p.ProfileId == profileId - && p.Dindex == dataIndex - && p.Ptype == (int)storageType - select p; - - Pstorage ps; - if (result.Count() == 0) - { - //insert a new record in database - ps = new Pstorage(); - ps.Dindex = dataIndex; - ps.ProfileId = profileId; - ps.Ptype = (int)storageType; - ps.Data = data; - db.Pstorages.Add(ps); - } - else if (result.Count() == 1) - { - //update an existed record in database - ps = result.First(); - ps.Data = data; - } - - db.SaveChanges(); - } - } - - public int GetProfileId(string token) - { - using (var db = new UniSpyContext()) - { - var result = from s in db.Subprofiles - where s.Authtoken == token - select s.ProfileId; - if (result.Count() != 1) - { - throw new GameStatus.Exception("No records found in database by authtoken."); - } - return result.First(); - } - } - - public int GetProfileId(string cdKey, string nickName) - { - using (var db = new UniSpyContext()) - { - var result = from s in db.Subprofiles - join p in db.Profiles on s.ProfileId equals p.ProfileId - where s.Cdkeyenc == cdKey && p.Nick == nickName - select s.ProfileId; - if (result.Count() != 1) - { - throw new GameStatus.Exception("No records found in database by cdkey hash."); - } - return result.First(); - } - } - - public int GetProfileId(int profileId) - { - using (var db = new UniSpyContext()) - { - var result = from p in db.Profiles - where p.ProfileId == profileId - select p.ProfileId; - if (result.Count() != 1) - { - throw new GameStatus.Exception("No records found in database by profileid."); - } - return result.First(); - } - } - - public Dictionary GetPlayerData(int profileId, PersistStorageType storageType, int dataIndex) - { - using (var db = new UniSpyContext()) - { - var result = from ps in db.Pstorages - where ps.Ptype == (int)storageType - && ps.Dindex == dataIndex - && ps.ProfileId == profileId - select ps.Data; - - if (result.Count() != 1) - { - throw new GameStatus.Exception("No records found in database."); - } - return result.FirstOrDefault(); - } - - } - } -} \ No newline at end of file diff --git a/src/Servers/GameStatus/src/Contract/Request/AuthGameRequest.cs b/src/Servers/GameStatus/src/Contract/Request/AuthGameRequest.cs deleted file mode 100755 index c93150a04..000000000 --- a/src/Servers/GameStatus/src/Contract/Request/AuthGameRequest.cs +++ /dev/null @@ -1,49 +0,0 @@ -using UniSpy.Server.GameStatus.Abstraction.BaseClass; - - -namespace UniSpy.Server.GameStatus.Contract.Request -{ - /// - /// Request: //auth\\gamename\%s\response\%s\port\%d\id\1 */ - /// - - public sealed class AuthGameRequest : RequestBase - { - public string GameName { get; private set; } - public int Port { get; private set; } - public AuthGameRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - if (!KeyValues.ContainsKey("lid") && !KeyValues.ContainsKey("id")) - { - throw new GameStatus.Exception("localid is missing."); - } - base.Parse(); - if (!KeyValues.ContainsKey("gamename")) - { - throw new GameStatus.Exception("gamename is missing."); - } - - if (!KeyValues.ContainsKey("response")) - { - throw new GameStatus.Exception("response is missing."); - } - - if (KeyValues.ContainsKey("port")) - { - int port; - if (!int.TryParse(KeyValues["port"], out port)) - { - throw new GameStatus.Exception("port format is incorrect."); - } - Port = port; - } - - GameName = KeyValues["gamename"]; - } - } -} diff --git a/src/Servers/GameStatus/src/Contract/Request/AuthPlayerRequest.cs b/src/Servers/GameStatus/src/Contract/Request/AuthPlayerRequest.cs deleted file mode 100755 index a6968d249..000000000 --- a/src/Servers/GameStatus/src/Contract/Request/AuthPlayerRequest.cs +++ /dev/null @@ -1,59 +0,0 @@ -using UniSpy.Server.GameStatus.Abstraction.BaseClass; -using UniSpy.Server.GameStatus.Enumerate; - - -namespace UniSpy.Server.GameStatus.Contract.Request -{ - // worm3d \authp\\pid\1\resp\7b6658e99f448388fbeddc93654e6dd4\lid\295[19][17]R([1B]zm}BKy[16]+sOhT[07][7F]{/[04]sz;j[00][15]RG=[16][1B]jBP9\final\ - public sealed class AuthPlayerRequest : RequestBase - { - public AuthMethod RequestType { get; private set; } - public int ProfileId { get; private set; } - public string AuthToken { get; private set; } - public string Response { get; private set; } - public string CdKeyHash { get; private set; } - public string NickName { get; private set; } - - public AuthPlayerRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - - if (!KeyValues.ContainsKey("lid") && !KeyValues.ContainsKey("id")) - { - throw new GameStatus.Exception("localid is missing."); - } - - if (KeyValues.ContainsKey("pid") && KeyValues.ContainsKey("resp")) - { - //we parse profileid here - int profileID; - if (!int.TryParse(KeyValues["pid"], out profileID)) - { - throw new GameStatus.Exception("pid format is incorrect."); - } - ProfileId = profileID; - RequestType = AuthMethod.ProfileIdAuth; - } - else if (KeyValues.ContainsKey("authtoken") && KeyValues.ContainsKey("response")) - { - AuthToken = KeyValues["authtoken"]; - Response = KeyValues["response"]; - RequestType = AuthMethod.PartnerIdAuth; - } - else if (KeyValues.ContainsKey("keyhash") && KeyValues.ContainsKey("nick")) - { - RequestType = AuthMethod.CDkeyAuth; - CdKeyHash = KeyValues["keyhash"]; - NickName = KeyValues["nick"]; - } - else - { - throw new GameStatus.Exception("Unknown authp request method."); - } - } - } -} diff --git a/src/Servers/GameStatus/src/Contract/Request/GetPlayerDataRequest.cs b/src/Servers/GameStatus/src/Contract/Request/GetPlayerDataRequest.cs deleted file mode 100755 index 3bbf16a68..000000000 --- a/src/Servers/GameStatus/src/Contract/Request/GetPlayerDataRequest.cs +++ /dev/null @@ -1,82 +0,0 @@ -using UniSpy.Server.GameStatus.Abstraction.BaseClass; -using UniSpy.Server.GameStatus.Enumerate; - -using System; -using System.Collections.Generic; - -namespace UniSpy.Server.GameStatus.Contract.Request -{ - - public sealed class GetPlayerDataRequest : RequestBase - { - public int ProfileId { get; private set; } - public PersistStorageType StorageType { get; private set; } - public int DataIndex { get; private set; } - public List Keys { get; private set; } - public bool GetAllDataFlag { get; private set; } - public GetPlayerDataRequest(string rawRequest) : base(rawRequest) - { - Keys = new List(); - } - - public override void Parse() - { - base.Parse(); - if (!KeyValues.ContainsKey("lid") && !KeyValues.ContainsKey("id")) - { - throw new GameStatus.Exception("localid is missing."); - } - - if (KeyValues.ContainsKey("pid")) - { - int profileID; - if (!int.TryParse(KeyValues["pid"], out profileID)) - { - throw new GameStatus.Exception("pid format is incorrect."); - } - ProfileId = profileID; - } - - if (KeyValues.ContainsKey("ptype")) - { - PersistStorageType storageType; - if (!Enum.TryParse(KeyValues["ptype"], out storageType)) - { - throw new GameStatus.Exception("ptype format is incorrect."); - } - StorageType = storageType; - } - - - if (KeyValues.ContainsKey("dindex")) - { - int dataIndex; - if (!int.TryParse(KeyValues["dindex"], out dataIndex)) - { - throw new GameStatus.Exception("dindex format is incorrect."); - } - DataIndex = dataIndex; - } - - if (!KeyValues.ContainsKey("keys")) - { - throw new GameStatus.Exception("keys is missing."); - } - - string keys = KeyValues["keys"]; - if (keys == "") - { - GetAllDataFlag = true; - } - else - { - string[] keyArray = keys.Split('\x1'); - foreach (var key in keyArray) - { - Keys.Add(key); - } - GetAllDataFlag = false; - } - } - } -} diff --git a/src/Servers/GameStatus/src/Contract/Request/GetProfileIDRequest.cs b/src/Servers/GameStatus/src/Contract/Request/GetProfileIDRequest.cs deleted file mode 100755 index 0f70d04da..000000000 --- a/src/Servers/GameStatus/src/Contract/Request/GetProfileIDRequest.cs +++ /dev/null @@ -1,40 +0,0 @@ -using UniSpy.Server.GameStatus.Abstraction.BaseClass; - - -namespace UniSpy.Server.GameStatus.Contract.Request -{ - - public sealed class GetProfileIDRequest : RequestBase - { - public string Nick { get; private set; } - public string KeyHash { get; private set; } - - public GetProfileIDRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - if (!KeyValues.ContainsKey("lid") && !KeyValues.ContainsKey("id")) - { - throw new GameStatus.Exception("localid is missing."); - } - - if (!KeyValues.ContainsKey("nick") || !KeyValues.ContainsKey("keyhash")) - { - throw new GameStatus.Exception("nick or keyhash is missing."); - } - - if (KeyValues.ContainsKey("nick")) - { - Nick = KeyValues["nick"]; - } - - if (KeyValues.ContainsKey("keyhash")) - { - KeyHash = KeyValues["keyhash"]; - } - } - } -} diff --git a/src/Servers/GameStatus/src/Contract/Request/NewGameRequest.cs b/src/Servers/GameStatus/src/Contract/Request/NewGameRequest.cs deleted file mode 100755 index 236be0c54..000000000 --- a/src/Servers/GameStatus/src/Contract/Request/NewGameRequest.cs +++ /dev/null @@ -1,52 +0,0 @@ -using UniSpy.Server.GameStatus.Abstraction.BaseClass; - - -namespace UniSpy.Server.GameStatus.Contract.Request -{ - // "\newgame\\sesskey\%d\challenge\%d"; - //"\newgame\\connid\%d\sesskey\%d" - // worm3d \newgame\\connid\0\sesskey\87563063\final\ - public sealed class NewGameRequest : RequestBase - { - public bool IsClientLocalStorageAvailable { get; private set; } - public string Challenge { get; private set; } - public int? ConnectionID { get; private set; } - /// - /// new game data storage session key, this is different from authgame session key - /// - public int? SessionKey { get; private set; } - public NewGameRequest(string rawRequest) : base(rawRequest) - { - } - public override void Parse() - { - base.Parse(); - - if (!KeyValues.ContainsKey("sesskey")) - { - throw new GameStatus.Exception("sesskey is missing."); - } - if (!int.TryParse(KeyValues["sesskey"], out var sessKey)) - { - throw new GameStatus.Exception("sesskey is not a valid int."); - } - SessionKey = sessKey; - - if (!KeyValues.ContainsKey("connid")) - { - throw new GameStatus.Exception("connid is missing."); - } - if (!int.TryParse(KeyValues["connid"], out var connectionID)) - { - throw new GameStatus.Exception("connid format is incorrect."); - } - ConnectionID = connectionID; - - if (KeyValues.ContainsKey("challenge")) - { - IsClientLocalStorageAvailable = true; - Challenge = KeyValues["challenge"]; - } - } - } -} diff --git a/src/Servers/GameStatus/src/Contract/Request/SetPlayerDataRequest.cs b/src/Servers/GameStatus/src/Contract/Request/SetPlayerDataRequest.cs deleted file mode 100755 index 530695480..000000000 --- a/src/Servers/GameStatus/src/Contract/Request/SetPlayerDataRequest.cs +++ /dev/null @@ -1,79 +0,0 @@ -using UniSpy.Server.GameStatus.Abstraction.BaseClass; -using UniSpy.Server.GameStatus.Enumerate; - -using System; - -namespace UniSpy.Server.GameStatus.Contract.Request -{ - /// - /// "\setpd\\pid\4\ptype\4\dindex\4\kv\\key1\value1\key2\value2\key3\value3\lid\2\length\5\data\final\" - /// - - - public sealed class SetPlayerDataRequest : RequestBase - { - public SetPlayerDataRequest(string request) : base(request) - { - } - public int ProfileId { get; private set; } - public PersistStorageType StorageType { get; private set; } - public int DataIndex { get; private set; } - public int Length { get; private set; } - public string Report { get; private set; } - public string Data { get; private set; } - public override void Parse() - { - base.Parse(); - - if (!KeyValues.ContainsKey("pid")) - throw new GameStatus.Exception("pid is missing."); - - if (!KeyValues.ContainsKey("ptype")) - throw new GameStatus.Exception("ptype is missing."); - - if (!KeyValues.ContainsKey("dindex")) - throw new GameStatus.Exception("dindex is missing."); - - if (!KeyValues.ContainsKey("length")) - throw new GameStatus.Exception("length is missing."); - - - int profileID; - if (!int.TryParse(KeyValues["pid"], out profileID)) - { - throw new GameStatus.Exception("pid format is incorrect."); - } - ProfileId = profileID; - - int storageType; - if (!int.TryParse(KeyValues["ptype"], out storageType)) - { - throw new GameStatus.Exception("ptype is missing."); - } - - if (!Enum.IsDefined(typeof(PersistStorageType), storageType)) - { - throw new GameStatus.Exception("storage type is incorrect."); - } - - StorageType = (PersistStorageType)storageType; - - int dindex; - if (!int.TryParse(KeyValues["dindex"], out dindex)) - { - throw new GameStatus.Exception("dindex format is incorrect."); - } - DataIndex = dindex; - - int length; - if (!int.TryParse(KeyValues["length"], out length)) - { - throw new GameStatus.Exception("length format is incorrect."); - } - Length = length; - - Report = KeyValues["report"]; - Data = KeyValues["data"]; - } - } -} diff --git a/src/Servers/GameStatus/src/Contract/Request/UpdateGameRequest.cs b/src/Servers/GameStatus/src/Contract/Request/UpdateGameRequest.cs deleted file mode 100755 index 337d390c7..000000000 --- a/src/Servers/GameStatus/src/Contract/Request/UpdateGameRequest.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.GameStatus.Abstraction.BaseClass; - - -namespace UniSpy.Server.GameStatus.Contract.Request -{ - - public sealed class UpdateGameRequest : RequestBase - { - public int? ConnectionID { get; private set; } - public bool IsDone { get; private set; } - public bool IsClientLocalStorageAvailable { get; private set; } - public string GameData { get; private set; } - public Dictionary GameDataKeyValues { get; private set; } - public int? SessionKey { get; private set; } - public UpdateGameRequest(string rawRequest) : base(rawRequest) - { - } - public override void Parse() - { - base.Parse(); - if (!KeyValues.ContainsKey("gamedata")) - { - throw new GameStatus.Exception("request must contians gamedata"); - } - GameData = KeyValues["gamedata"]; - GameDataKeyValues = ConvertGameDataToKeyValues(GameData); - - if (KeyValues.ContainsKey("dl")) - { - IsClientLocalStorageAvailable = true; - } - - if (!KeyValues.ContainsKey("done")) - { - throw new GameStatus.Exception("done is missing."); - } - - - if (KeyValues["done"] == "1") - { - IsDone = true; - } - else if (KeyValues["done"] == "0") - { - IsDone = false; - } - else - { - throw new GameStatus.Exception("done format is incorrect."); - } - - - if (!int.TryParse(KeyValues["sesskey"], out var sessKey)) - { - throw new GameStatus.Exception("sesskey is not a valid int."); - } - SessionKey = sessKey; - - - if (KeyValues.ContainsKey("connid")) - { - if (!int.TryParse(KeyValues["connid"], out var connID)) - { - throw new GameStatus.Exception("connid is not a valid int."); - } - ConnectionID = connID; - } - } - } -} \ No newline at end of file diff --git a/src/Servers/GameStatus/src/Contract/Response/AuthGameResponse.cs b/src/Servers/GameStatus/src/Contract/Response/AuthGameResponse.cs deleted file mode 100755 index 5d8c08231..000000000 --- a/src/Servers/GameStatus/src/Contract/Response/AuthGameResponse.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.GameStatus.Abstraction.BaseClass; -using UniSpy.Server.GameStatus.Contract.Request; -using UniSpy.Server.GameStatus.Contract.Result; - -namespace UniSpy.Server.GameStatus.Contract.Response -{ - public sealed class AuthGameResponse : ResponseBase - { - private new AuthGameRequest _request => (AuthGameRequest)base._request; - private new AuthGameResult _result => (AuthGameResult)base._result; - public AuthGameResponse(AuthGameRequest request, AuthGameResult result) : base(request, result) - { - } - - public override void Build() - { - SendingBuffer = $@"\sesskey\{_result.SessionKey}\lid\{ _request.LocalId}\final\"; - } - } -} diff --git a/src/Servers/GameStatus/src/Contract/Response/AuthPlayerResponse.cs b/src/Servers/GameStatus/src/Contract/Response/AuthPlayerResponse.cs deleted file mode 100755 index b993089b7..000000000 --- a/src/Servers/GameStatus/src/Contract/Response/AuthPlayerResponse.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.GameStatus.Abstraction.BaseClass; -using UniSpy.Server.GameStatus.Contract.Request; -using UniSpy.Server.GameStatus.Contract.Result; - -namespace UniSpy.Server.GameStatus.Contract.Response -{ - public sealed class AuthPlayerResponse : ResponseBase - { - private new AuthPlayerResult _result => (AuthPlayerResult)base._result; - private new AuthPlayerRequest _request => (AuthPlayerRequest)base._request; - public AuthPlayerResponse(AuthPlayerRequest request, AuthPlayerResult result) : base(request, result) - { - } - - public override void Build() - { - SendingBuffer = $@"\pauthr\{_result.ProfileId}\lid\{ _request.LocalId}\final\"; - } - } -} diff --git a/src/Servers/GameStatus/src/Contract/Response/GetPlayerDataResponse.cs b/src/Servers/GameStatus/src/Contract/Response/GetPlayerDataResponse.cs deleted file mode 100755 index 8f10eb8c2..000000000 --- a/src/Servers/GameStatus/src/Contract/Response/GetPlayerDataResponse.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.GameStatus.Abstraction.BaseClass; -using UniSpy.Server.GameStatus.Contract.Request; -using UniSpy.Server.GameStatus.Contract.Result; - -namespace UniSpy.Server.GameStatus.Contract.Response -{ - public sealed class GetPlayerDataResponse : ResponseBase - { - private new GetPlayerDataResult _result => (GetPlayerDataResult)base._result; - private new GetPlayerDataRequest _request => (GetPlayerDataRequest)base._request; - public GetPlayerDataResponse(GetPlayerDataRequest request, GetPlayerDataResult result) : base(request, result) - { - } - - public override void Build() - { - SendingBuffer = $@"\getpdr\1\pid\{_request.ProfileId}\lid\{_request.LocalId}\mod\1234\length\5\data\mydata\final\"; - } - } -} diff --git a/src/Servers/GameStatus/src/Contract/Response/GetProfileIDResponse.cs b/src/Servers/GameStatus/src/Contract/Response/GetProfileIDResponse.cs deleted file mode 100755 index b195d982d..000000000 --- a/src/Servers/GameStatus/src/Contract/Response/GetProfileIDResponse.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.GameStatus.Abstraction.BaseClass; -using UniSpy.Server.GameStatus.Contract.Request; -using UniSpy.Server.GameStatus.Contract.Result; - -namespace UniSpy.Server.GameStatus.Contract.Response -{ - public sealed class GetProfileIDResponse : ResponseBase - { - private new GetProfileIDResult _result => (GetProfileIDResult)base._result; - private new GetProfileIDRequest _request => (GetProfileIDRequest)base._request; - public GetProfileIDResponse(GetProfileIDRequest request, GetProfileIDResult result) : base(request, result) - { - } - - public override void Build() - { - SendingBuffer = $@"\getpidr\{_result.ProfileId}\lid\{ _request.LocalId}\final\"; - } - } -} diff --git a/src/Servers/GameStatus/src/Contract/Response/SetPlayerDataResponse.cs b/src/Servers/GameStatus/src/Contract/Response/SetPlayerDataResponse.cs deleted file mode 100755 index c11613f63..000000000 --- a/src/Servers/GameStatus/src/Contract/Response/SetPlayerDataResponse.cs +++ /dev/null @@ -1,21 +0,0 @@ -using UniSpy.Server.GameStatus.Abstraction.BaseClass; -using UniSpy.Server.GameStatus.Contract.Request; -using UniSpy.Server.GameStatus.Contract.Result; -using System; - -namespace UniSpy.Server.GameStatus.Contract.Response -{ - public sealed class SetPlayerDataResponse : ResponseBase - { - private new SetPlayerDataResult _result => (SetPlayerDataResult)base._result; - private new SetPlayerDataRequest _request => (SetPlayerDataRequest)base._request; - public SetPlayerDataResponse(SetPlayerDataRequest request, SetPlayerDataResult result) : base(request, result) - { - } - - public override void Build() - { - throw new NotImplementedException(); - } - } -} diff --git a/src/Servers/GameStatus/src/Contract/Result/AuthGameResult.cs b/src/Servers/GameStatus/src/Contract/Result/AuthGameResult.cs deleted file mode 100755 index 660472f18..000000000 --- a/src/Servers/GameStatus/src/Contract/Result/AuthGameResult.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.GameStatus.Abstraction.BaseClass; - -namespace UniSpy.Server.GameStatus.Contract.Result -{ - public sealed class AuthGameResult : ResultBase - { - public int SessionKey { get; set; } - public AuthGameResult() - { - } - } -} diff --git a/src/Servers/GameStatus/src/Contract/Result/AuthPlayerResult.cs b/src/Servers/GameStatus/src/Contract/Result/AuthPlayerResult.cs deleted file mode 100755 index 5b368a9fa..000000000 --- a/src/Servers/GameStatus/src/Contract/Result/AuthPlayerResult.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.GameStatus.Abstraction.BaseClass; - -namespace UniSpy.Server.GameStatus.Contract.Result -{ - public sealed class AuthPlayerResult : ResultBase - { - public int? ProfileId { get; set; } - public AuthPlayerResult() - { - } - } -} diff --git a/src/Servers/GameStatus/src/Contract/Result/GetPlayerDataResult.cs b/src/Servers/GameStatus/src/Contract/Result/GetPlayerDataResult.cs deleted file mode 100755 index ce8252068..000000000 --- a/src/Servers/GameStatus/src/Contract/Result/GetPlayerDataResult.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.GameStatus.Abstraction.BaseClass; -using System.Collections.Generic; - -namespace UniSpy.Server.GameStatus.Contract.Result -{ - public sealed class GetPlayerDataResult : ResultBase - { - public Dictionary KeyValues { get; set; } - public GetPlayerDataResult() - { - } - } -} diff --git a/src/Servers/GameStatus/src/Contract/Result/GetProfileIDResult.cs b/src/Servers/GameStatus/src/Contract/Result/GetProfileIDResult.cs deleted file mode 100755 index 15c7a88c9..000000000 --- a/src/Servers/GameStatus/src/Contract/Result/GetProfileIDResult.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.GameStatus.Abstraction.BaseClass; - -namespace UniSpy.Server.GameStatus.Contract.Result -{ - public sealed class GetProfileIDResult : ResultBase - { - public int ProfileId { get; set; } - public GetProfileIDResult() - { - } - } -} diff --git a/src/Servers/GameStatus/src/Contract/Result/SetPlayerDataResult.cs b/src/Servers/GameStatus/src/Contract/Result/SetPlayerDataResult.cs deleted file mode 100755 index 2429cbe9f..000000000 --- a/src/Servers/GameStatus/src/Contract/Result/SetPlayerDataResult.cs +++ /dev/null @@ -1,11 +0,0 @@ -using UniSpy.Server.GameStatus.Abstraction.BaseClass; - -namespace UniSpy.Server.GameStatus.Contract.Result -{ - public sealed class SetPlayerDataResult : ResultBase - { - public SetPlayerDataResult() - { - } - } -} diff --git a/src/Servers/GameStatus/src/Dockerfile b/src/Servers/GameStatus/src/Dockerfile deleted file mode 100755 index 9c4fdf87d..000000000 --- a/src/Servers/GameStatus/src/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM mcr.microsoft.com/dotnet/runtime:6.0 AS base -WORKDIR /app -EXPOSE 29920 - -FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build -WORKDIR /src -COPY ["src/Servers/GameStatus/src/UniSpy.Server.GameStatus.csproj", "src/Servers/GameStatus/src/"] -COPY ["src/Libraries/Core/src/UniSpy.Server.Core.csproj", "src/Libraries/Core/src/"] -RUN dotnet restore "src/Servers/GameStatus/src/UniSpy.Server.GameStatus.csproj" -COPY . . -WORKDIR "/src/src/Servers/GameStatus/src" -RUN dotnet build "UniSpy.Server.GameStatus.csproj" -c Release -o /app/build - -FROM build AS publish -RUN dotnet publish "UniSpy.Server.GameStatus.csproj" -c Release -o /app/publish - -FROM base AS final -WORKDIR /app -COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "UniSpy.Server.GameStatus.dll"] \ No newline at end of file diff --git a/src/Servers/GameStatus/src/Enumerate/AuthMethod.cs b/src/Servers/GameStatus/src/Enumerate/AuthMethod.cs deleted file mode 100755 index 014461cc9..000000000 --- a/src/Servers/GameStatus/src/Enumerate/AuthMethod.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace UniSpy.Server.GameStatus.Enumerate -{ - public enum AuthMethod - { - Unknown, - ProfileIdAuth, - PartnerIdAuth, - CDkeyAuth, - } -} diff --git a/src/Servers/GameStatus/src/Enumerate/GSErrorCode.cs b/src/Servers/GameStatus/src/Enumerate/GSErrorCode.cs deleted file mode 100755 index f69b29b9d..000000000 --- a/src/Servers/GameStatus/src/Enumerate/GSErrorCode.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace UniSpy.Server.GameStatus.Enumerate -{ - /// - /// In gamespy protocol there are no error response message - /// from server to client, which mean we only need to make - /// public error system. - /// - public enum GSErrorCode - { - General, - Parse, - Database, - NoError - } -} diff --git a/src/Servers/GameStatus/src/Enumerate/PersistantStorage.cs b/src/Servers/GameStatus/src/Enumerate/PersistantStorage.cs deleted file mode 100755 index 499c55a5a..000000000 --- a/src/Servers/GameStatus/src/Enumerate/PersistantStorage.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace UniSpy.Server.GameStatus.Enumerate -{ - public enum PersistStorageType : int - { - /// - /// Readable only by the authenticated client it belongs to, can only by set on the server - /// - PrivateRO, - /// - /// Readable only by the authenticated client it belongs to, set by the authenticated client it belongs to - /// - PrivateRW, - /// - /// Readable by any client, can only be set on the server - /// - PublicRO, - /// - /// Readable by any client, set by the authenicated client is belongs to - /// - PublicRW, - } -} diff --git a/src/Servers/GameStatus/src/Exception/GSException.cs b/src/Servers/GameStatus/src/Exception/GSException.cs deleted file mode 100755 index ad126c155..000000000 --- a/src/Servers/GameStatus/src/Exception/GSException.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace UniSpy.Server.GameStatus -{ - public class Exception : UniSpy.Exception - { - public Exception() - { - } - - public Exception(string message) : base(message) - { - } - - public Exception(string message, System.Exception innerException) : base(message, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/GameStatus/src/Handler/CmdHandler/AuthGameHandler.cs b/src/Servers/GameStatus/src/Handler/CmdHandler/AuthGameHandler.cs deleted file mode 100755 index 8aaa836f4..000000000 --- a/src/Servers/GameStatus/src/Handler/CmdHandler/AuthGameHandler.cs +++ /dev/null @@ -1,31 +0,0 @@ -using UniSpy.Server.GameStatus.Abstraction.BaseClass; -using UniSpy.Server.GameStatus.Contract.Request; -using UniSpy.Server.GameStatus.Contract.Response; -using UniSpy.Server.GameStatus.Contract.Result; -using UniSpy.Server.GameStatus.Application; - -namespace UniSpy.Server.GameStatus.Handler.CmdHandler -{ - - public sealed class AuthGameHandler : CmdHandlerBase - { - private new AuthGameRequest _request => (AuthGameRequest)base._request; - private new AuthGameResult _result { get => (AuthGameResult)base._result; set => base._result = value; } - public AuthGameHandler(Client client, AuthGameRequest request) : base(client, request) - { - _result = new AuthGameResult(); - } - protected override void DataOperation() - { - // for now we do not check this challenge correction - _client.Info.SessionKey = 2020; - _client.Info.GameName = _request.GameName; - _client.Info.IsGameAuthenticated = true; - } - - protected override void ResponseConstruct() - { - _response = new AuthGameResponse(_request, _result); - } - } -} diff --git a/src/Servers/GameStatus/src/Handler/CmdHandler/AuthPlayerHandler.cs b/src/Servers/GameStatus/src/Handler/CmdHandler/AuthPlayerHandler.cs deleted file mode 100755 index f46f11aea..000000000 --- a/src/Servers/GameStatus/src/Handler/CmdHandler/AuthPlayerHandler.cs +++ /dev/null @@ -1,57 +0,0 @@ -using UniSpy.Server.GameStatus.Abstraction.BaseClass; -using UniSpy.Server.GameStatus.Enumerate; -using UniSpy.Server.GameStatus.Contract.Request; -using UniSpy.Server.GameStatus.Contract.Response; -using UniSpy.Server.GameStatus.Contract.Result; -using UniSpy.Server.GameStatus.Application; - -namespace UniSpy.Server.GameStatus.Handler.CmdHandler -{ - /// - /// Authenticate with partnerid or profileid - /// because we are not gamespy - /// so we do not check response string - /// - public sealed class AuthPlayerHandler : CmdHandlerBase - { - private new AuthPlayerRequest _request => (AuthPlayerRequest)base._request; - private new AuthPlayerResult _result { get => (AuthPlayerResult)base._result; set => base._result = value; } - public AuthPlayerHandler(Client client, AuthPlayerRequest request) : base(client, request) - { - _result = new AuthPlayerResult(); - } - protected override void DataOperation() - { - //search database for user's password - //We do not store user's plaintext password, so we can not check this response - - switch (_request.RequestType) - { - case AuthMethod.PartnerIdAuth: - _client.Info.ProfileId = StorageOperation.Persistance.GetProfileId(_request.AuthToken); - break; - case AuthMethod.ProfileIdAuth: - //even if we do not check response challenge - //we have to check the pid is in our databse - _client.Info.ProfileId = StorageOperation.Persistance.GetProfileId(_request.ProfileId); - break; - case AuthMethod.CDkeyAuth: - _client.Info.ProfileId = StorageOperation.Persistance.GetProfileId(_request.CdKeyHash, _request.NickName); - break; - default: - throw new GameStatus.Exception("Unknown AuthP request type."); - } - if (_client.Info.ProfileId is null) - { - throw new GameStatus.Exception("Can not find profileID"); - } - _result.ProfileId = _client.Info.ProfileId; - _client.Info.IsPlayerAuthenticated = true; - } - - protected override void ResponseConstruct() - { - _response = new AuthPlayerResponse(_request, _result); - } - } -} diff --git a/src/Servers/GameStatus/src/Handler/CmdHandler/GetPlayerDataHandler.cs b/src/Servers/GameStatus/src/Handler/CmdHandler/GetPlayerDataHandler.cs deleted file mode 100755 index 9c27d93e7..000000000 --- a/src/Servers/GameStatus/src/Handler/CmdHandler/GetPlayerDataHandler.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.GameStatus.Abstraction.BaseClass; -using UniSpy.Server.GameStatus.Application; - -using UniSpy.Server.GameStatus.Contract.Request; -using UniSpy.Server.GameStatus.Contract.Response; -using UniSpy.Server.GameStatus.Contract.Result; - -namespace UniSpy.Server.GameStatus.Handler.CmdHandler -{ - - public sealed class GetPlayerDataHandler : CmdHandlerBase - { - //\getpd\\pid\%d\ptype\%d\dindex\%d\keys\%s\lid\%d - private new GetPlayerDataRequest _request => (GetPlayerDataRequest)base._request; - private new GetPlayerDataResult _result { get => (GetPlayerDataResult)base._result; set => base._result = value; } - public GetPlayerDataHandler(Client client, GetPlayerDataRequest request) : base(client, request) - { - _result = new GetPlayerDataResult(); - } - protected override void DataOperation() - { - //search player data in database; - Dictionary keyValues; - - keyValues = StorageOperation.Persistance.GetPlayerData(_request.ProfileId, _request.StorageType, _request.DataIndex); - //TODO figure out what is the function of keys in request - - - if (_request.GetAllDataFlag) - { - _result.KeyValues = keyValues; - } - else - { - foreach (var key in _request.Keys) - { - if (keyValues.ContainsKey(key)) - { - _result.KeyValues.Add(key, keyValues[key]); - } - else - { - throw new GameStatus.Exception($"can not find key:{key} in GetPD request."); - } - } - } - } - - protected override void ResponseConstruct() - { - _response = new GetPlayerDataResponse(_request, _result); - } - } -} diff --git a/src/Servers/GameStatus/src/Handler/CmdHandler/GetProfileIDHandler.cs b/src/Servers/GameStatus/src/Handler/CmdHandler/GetProfileIDHandler.cs deleted file mode 100755 index 3966654d9..000000000 --- a/src/Servers/GameStatus/src/Handler/CmdHandler/GetProfileIDHandler.cs +++ /dev/null @@ -1,31 +0,0 @@ -using UniSpy.Server.GameStatus.Abstraction.BaseClass; -using UniSpy.Server.GameStatus.Contract.Request; -using UniSpy.Server.GameStatus.Contract.Response; -using UniSpy.Server.GameStatus.Contract.Result; -using UniSpy.Server.GameStatus.Application; - -namespace UniSpy.Server.GameStatus.Handler.CmdHandler -{ - - public sealed class GetProfileIdHandler : CmdHandlerBase - { - //request \getpid\\nick\%s\keyhash\%s\lid\%d - //response \getpidr - private int _profileId; - private new GetProfileIDRequest _request => (GetProfileIDRequest)base._request; - private new GetProfileIDResult _result { get => (GetProfileIDResult)base._result; set => base._result = value; } - public GetProfileIdHandler(Client client, GetProfileIDRequest request) : base(client, request) - { - _result = new GetProfileIDResult(); - } - protected override void DataOperation() - { - _profileId = StorageOperation.Persistance.GetProfileId(_request.KeyHash, _request.Nick); - } - - protected override void ResponseConstruct() - { - _response = new GetProfileIDResponse(_request, _result); - } - } -} diff --git a/src/Servers/GameStatus/src/Handler/CmdHandler/NewGameHandler.cs b/src/Servers/GameStatus/src/Handler/CmdHandler/NewGameHandler.cs deleted file mode 100755 index 23f76387e..000000000 --- a/src/Servers/GameStatus/src/Handler/CmdHandler/NewGameHandler.cs +++ /dev/null @@ -1,29 +0,0 @@ -using UniSpy.Server.GameStatus.Abstraction.BaseClass; -using UniSpy.Server.GameStatus.Application; -using UniSpy.Server.GameStatus.Contract.Request; - -namespace UniSpy.Server.GameStatus.Handler.CmdHandler -{ - /// - /// Create a game specified information storage space - /// for further game snap shot storage - /// - - public sealed class NewGameHandler : CmdHandlerBase - { - private new NewGameRequest _request => (NewGameRequest)base._request; - public NewGameHandler(Client client, NewGameRequest request) : base(client, request) - { - } - protected override void RequestCheck() - { - base.RequestCheck(); - _client.Info.GameSessionKey = _request.SessionKey; - } - protected override void DataOperation() - { - // store game data to database - StorageOperation.Persistance.CreateNewGameData(); - } - } -} diff --git a/src/Servers/GameStatus/src/Handler/CmdHandler/SetPlayerDataHandler.cs b/src/Servers/GameStatus/src/Handler/CmdHandler/SetPlayerDataHandler.cs deleted file mode 100755 index 4b07d07a7..000000000 --- a/src/Servers/GameStatus/src/Handler/CmdHandler/SetPlayerDataHandler.cs +++ /dev/null @@ -1,24 +0,0 @@ -using UniSpy.Server.GameStatus.Abstraction.BaseClass; -using UniSpy.Server.GameStatus.Contract.Request; -using UniSpy.Server.GameStatus.Application; - -namespace UniSpy.Server.GameStatus.Handler.CmdHandler -{ - /// - /// Save persist storage data - /// No response for this handler - /// - public sealed class SetPlayerDataHandler : CmdHandlerBase - { - private new SetPlayerDataRequest _request => (SetPlayerDataRequest)base._request; - public SetPlayerDataHandler(Client client, SetPlayerDataRequest request) : base(client, request) - { - } - - protected override void DataOperation() - { - throw new GameStatus.Exception("implement set player data"); - // StorageOperation.Persistance.UpdatePlayerData(_request.ProfileId, _request.StorageType, _request.DataIndex, _request.KeyValues); - } - } -} diff --git a/src/Servers/GameStatus/src/Handler/CmdHandler/UpdateGameHandler.cs b/src/Servers/GameStatus/src/Handler/CmdHandler/UpdateGameHandler.cs deleted file mode 100755 index 31cebe2e3..000000000 --- a/src/Servers/GameStatus/src/Handler/CmdHandler/UpdateGameHandler.cs +++ /dev/null @@ -1,39 +0,0 @@ -using UniSpy.Server.GameStatus.Abstraction.BaseClass; - -using UniSpy.Server.GameStatus.Contract.Request; -using UniSpy.Server.GameStatus.Application; - -namespace UniSpy.Server.GameStatus.Handler.CmdHandler -{ - /// - /// Handles game snapshot and update game data - /// - - public sealed class UpdateGameHandler : CmdHandlerBase - { - //old request "\updgame\\sesskey\%d\done\%d\gamedata\%s" - //new request "\updgame\\sesskey\%d\connid\%d\done\%d\gamedata\%s" - private new UpdateGameRequest _request => (UpdateGameRequest)base._request; - public UpdateGameHandler(Client client, UpdateGameRequest request) : base(client, request) - { - } - protected override void RequestCheck() - { - base.RequestCheck(); - if (_request.SessionKey != _client.Info.GameSessionKey) - { - throw new GameStatus.Exception("Game session key is not match"); - } - } - protected override void DataOperation() - { - if (_request.GameData is null) - { - // the gamedata is null, we do not need to process this request - return; - } - // replace game data with new data - throw new GameStatus.Exception("Implement update game handler."); - } - } -} diff --git a/src/Servers/GameStatus/src/Handler/CmdSwitcher.cs b/src/Servers/GameStatus/src/Handler/CmdSwitcher.cs deleted file mode 100755 index 8faff7887..000000000 --- a/src/Servers/GameStatus/src/Handler/CmdSwitcher.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Linq; -using System.Collections.Generic; -using UniSpy.Server.GameStatus.Contract.Request; -using UniSpy.Server.GameStatus.Handler.CmdHandler; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Logging; -using UniSpy.Server.GameStatus.Application; - -namespace UniSpy.Server.GameStatus.Handler -{ - public sealed class CmdSwitcher : CmdSwitcherBase - { - private new string _rawRequest => (string)base._rawRequest; - private new Client _client => (Client)base._client; - public CmdSwitcher(Client client, string rawRequest) : base(client, rawRequest) - { - } - protected override void ProcessRawRequest() - { - var rawRequests = _rawRequest.Split(@"\final\", StringSplitOptions.RemoveEmptyEntries); - - foreach (var rawRequest in rawRequests) - { - if (_rawRequest[0] != '\\') - { - // throw new UniSpy.Exception("Invalid request"); - _client.LogError($"Invaid request: {rawRequest}"); - continue; - } - - var name = rawRequest.TrimStart('\\').Split('\\').First(); - _requests.Add(new KeyValuePair(name, rawRequest)); - } - } - - protected override IHandler CreateCmdHandlers(object name, object rawRequest) - { - switch ((string)name) - { - case "auth": - return new AuthGameHandler(_client, new AuthGameRequest((string)rawRequest)); - case "authp": - return new AuthPlayerHandler(_client, new AuthPlayerRequest((string)rawRequest)); - case "newgame": - return new NewGameHandler(_client, new NewGameRequest((string)rawRequest)); - case "getpd": - return new GetPlayerDataHandler(_client, new GetPlayerDataRequest((string)rawRequest)); - case "setpd": - return new SetPlayerDataHandler(_client, new SetPlayerDataRequest((string)rawRequest)); - case "updgame": - return new UpdateGameHandler(_client, new UpdateGameRequest((string)rawRequest)); - default: - return null; - } - } - } -} diff --git a/src/Servers/GameStatus/src/UniSpy.Server.GameStatus.csproj b/src/Servers/GameStatus/src/UniSpy.Server.GameStatus.csproj deleted file mode 100755 index 8b9381e25..000000000 --- a/src/Servers/GameStatus/src/UniSpy.Server.GameStatus.csproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - Exe - net6.0 - ..\..\..\..\common\Icon\UniSpy_Logo.ico - Linux - ..\..\..\.. - - - ..\..\..\..\build\$(Configuration) - - - ..\..\..\..\build\$(Configuration) - - - - - - - - \ No newline at end of file diff --git a/src/Servers/GameStatus/test/GameTest.cs b/src/Servers/GameStatus/test/GameTest.cs deleted file mode 100644 index 5adf71c07..000000000 --- a/src/Servers/GameStatus/test/GameTest.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Encryption; -using Xunit; - -namespace UniSpy.Server.GameStatus.Test -{ - public class GameTest - { - [Fact] - public void Worm3d20230331() - { - var client1 = (ITestClient)MockObject.CreateClient(port: 123); - var client2 = (ITestClient)MockObject.CreateClient(port: 124); - // Given - var requests = new List> - { - new KeyValuePair(client1,@"\auth\\gamename\worms3\response\bc3ca727a7825879eb9f13d9fd51bbb9\port\0\id\1\final\"), - new KeyValuePair(client2,@"\auth\\gamename\worms3\response\bc3ca727a7825879eb9f13d9fd51bbb9\port\0\id\1\final\"), - new KeyValuePair(client2,@"\newgame\\connid\0\sesskey\144562\final\"), - new KeyValuePair(client2,@"\newgame\\connid\0\sesskey\144563\final\"), - new KeyValuePair(client1,@"\authp\\pid\1\resp\7b6658e99f448388fbeddc93654e6dd4\lid\2\final\"), - new KeyValuePair(client1,@"\authp\\pid\1\resp\7b6658e99f448388fbeddc93654e6dd4\lid\1\final\"), - new KeyValuePair(client1,@"\setpd\\pid\1\ptype\1\dindex\0\kv\1\lid\2\length\111\data\\report\|title||victories|0|timestamp|66613|league|Team17|winner||crc|-1|player_0|spyguy|ip_0||pid_0|0|auth_0|[00]\final\"), - new KeyValuePair(client2,@"\authp\\pid\16\resp\7b6658e99f448388fbeddc93654e6dd4\lid\2\final\"), - new KeyValuePair(client2,@"\authp\\pid\16\resp\7b6658e99f448388fbeddc93654e6dd4\lid\1\final\"), - new KeyValuePair(client2,@"\setpd\\pid\16\ptype\1\dindex\0\kv\1\lid\2\length\125\data\\report\|title||victories|0|timestamp|66613|league|Team17|winner||crc|-1|player_0|unispy|ip_0|192.168.1.102|pid_0|16|auth_0|[00]\final\") - }; - - foreach (var item in requests) - { - item.Key.TestReceived(UniSpyEncoding.GetBytes(item.Value)); - } - } - [Fact] - public void Gmtest() - { - // Given - var requests = new List() - { - @"\auth\\gamename\crysis2\response\xxxxx\port\30\id\1\final\", - @"\getpd\\pid\0\ptype\0\dindex\1\keys\hello" + "\x1" + @"hi\lid\1\final\", - @"\getpid\\nick\xiaojiuwo\keyhash\00000\lid\1\final\", - @"\newgame\\connid\123\sesskey\123456\lid\1\final\", - @"\newgame\\connid\123\sesskey\2020\lid\1\final\", - @"\newgame\\connid\123\sesskey\123456\challenge\123456789\lid\1\final\", - @"\newgame\\connid\123\sesskey\2020\challenge\123456789\lid\1\final\", - @"\setpd\\pid\123\ptype\0\dindex\1\kv\%d\lid\1\length\5\data\11\lid\1\final\", - @"\updgame\\sesskey\0\done\1\gamedata\hello\lid\1\final\", - @"\updgame\\sesskey\2020\done\1\gamedata\hello\lid\1\final\", - @"\updgame\\sesskey\2020\connid\1\done\1\gamedata\hello\lid\1\final\", - @"\updgame\\sesskey\0\connid\1\done\1\gamedata\hello\lid\1\final\", - }; - foreach (var req in requests) - { - ((ITestClient)MockObject.Client).TestReceived(UniSpyEncoding.GetBytes(req)); - } - } - } -} \ No newline at end of file diff --git a/src/Servers/GameStatus/test/MockObject.cs b/src/Servers/GameStatus/test/MockObject.cs deleted file mode 100644 index f6947c39b..000000000 --- a/src/Servers/GameStatus/test/MockObject.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Net; -using Moq; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.GameStatus.Application; - -namespace UniSpy.Server.GameStatus.Test -{ - public static class MockObject - { - public static IClient Client = CreateClient(); - public static Client CreateClient(string ipAddress = "192.168.1.1", int port = 9999) - { - - var managerMock = new Mock(); - var connectionMock = new Mock(); - connectionMock.Setup(s => s.RemoteIPEndPoint).Returns(new IPEndPoint(IPAddress.Parse(ipAddress), port)); - connectionMock.Setup(s => s.Manager).Returns(managerMock.Object); - connectionMock.Setup(s => s.ConnectionType).Returns(NetworkConnectionType.Tcp); - var serverMock = new GameStatus.Application.Server(managerMock.Object); - - return new Client(connectionMock.Object, serverMock); - } - } -} \ No newline at end of file diff --git a/src/Servers/GameStatus/test/RequestTest.cs b/src/Servers/GameStatus/test/RequestTest.cs deleted file mode 100644 index 91e681918..000000000 --- a/src/Servers/GameStatus/test/RequestTest.cs +++ /dev/null @@ -1,135 +0,0 @@ -using UniSpy.Server.GameStatus.Enumerate; -using UniSpy.Server.GameStatus.Contract.Request; -using Xunit; -using UniSpy.Server.Core.Encryption; - -namespace UniSpy.Server.GameStatus.Test -{ - public class RequestTest - { - [Fact] - public void SetPlayerData20230329() - { - // Given - var raw = @"\setpd\\pid\1\ptype\1\dindex\0\kv\1\lid\2\length\111\data\\report\|title||victories|0|timestamp|37155|league|Team17|winner||crc|-1|player_0|spyguy|ip_0||pid_0|0|auth_0|[00]\final\"; - var req = new SetPlayerDataRequest(raw); - req.Parse(); - // When - - // Then - } - [Fact] - public void GameSpySDKUpdateGameRequest20230329() - { - var raw1 = "\\updgame\\\\sesskey\\20298203\\connid\\0\\done\\0\\gamedata\\\u0001hostname\u0001My l33t Server\u0001mapname\u0001Level 33\u0001gametype\u0001hunter\u0001gamever\u00011.230000\u0001player_0\u0001Bob!\u0001points_0\u00014\u0001deaths_0\u00012\u0001pid_0\u000132432423\u0001auth_0\u00017cca8e60a13781eebc820a50754f57cd\u0001player_1\u0001Joey\u0001points_1\u00012\u0001deaths_1\u00014\u0001pid_1\u0001643423\u0001auth_1\u000119ea14d9d92a7fcc635cf5716944d9bc\\final\\"; - var raw2 = "\\updgame\\\\sesskey\\20298203\\connid\\0\\done\\1\\gamedata\\\u0001hostname\u0001My l33t Server\u0001mapname\u0001Level 33\u0001gametype\u0001hunter\u0001gamever\u00011.230000\u0001player_0\u0001Bob!\u0001points_0\u00016\u0001deaths_0\u00013\u0001pid_0\u000132432423\u0001auth_0\u00017cca8e60a13781eebc820a50754f57cd\u0001player_1\u0001Joey\u0001points_1\u00013\u0001deaths_1\u00016\u0001pid_1\u0001643423\u0001auth_1\u000119ea14d9d92a7fcc635cf5716944d9bc\\final\\"; - var r1 = new UpdateGameRequest(raw1); - r1.Parse(); - var r2 = new UpdateGameRequest(raw2); - r2.Parse(); - } - [Fact] - public void Worm3dAuthPlayer() - { - var request = "2\x0F\x16\x10]%+=veKaB3a(UC`b$\x1CO\x11VZX\x09w\x1Cu\x08L@\x13=X!\x1E{\x0EL\x1DLf[qN \x04G\x130[#N'\x09(IC`b$"; - var buffer = UniSpyEncoding.GetBytes(request); - var buffer2 = XOREncoding.Encode(buffer, XorType.Type1); - var data = UniSpyEncoding.GetString(buffer2); - } - [Fact] - public void AuthPlayerTest() - { - var raw = @"\auth\\gamename\crysis2\response\xxxxx\port\30\id\1\final"; - var request = new AuthGameRequest(raw); - request.Parse(); - Assert.Equal("crysis2", request.GameName); - Assert.Equal(30, request.Port); - Assert.Equal((int)1, request.LocalId); - } - [Fact] - public void AuthGameTest() - { - var raw = @"\auth\\gamename\gmtest\response\xxxx\port\0\id\1"; - var request = new AuthGameRequest(raw); - request.Parse(); - Assert.Equal("gmtest", request.GameName); - Assert.Equal(0, request.Port); - Assert.Equal((int)1, request.LocalId); - } - [Fact] - public void GetPlayerDataTest() - { - var raw = @"\getpd\\pid\0\ptype\0\dindex\1\keys\hello" + "\x1" + @"hi\lid\1"; - var request = new GetPlayerDataRequest(raw); - request.Parse(); - Assert.Equal((int)0, request.ProfileId); - Assert.Equal(PersistStorageType.PrivateRO, request.StorageType); - Assert.Equal((int)1, request.DataIndex); - Assert.Equal(2, request.Keys.Count); - Assert.Equal("hello", request.Keys[0]); - Assert.Equal("hi", request.Keys[1]); - } - [Fact] - public void GetProfileIDTest() - { - var raw = @"\getpid\\nick\xiaojiuwo\keyhash\00000\lid\1"; - var request = new GetProfileIDRequest(raw); - request.Parse(); - Assert.Equal("xiaojiuwo", request.Nick); - Assert.Equal("00000", request.KeyHash); - Assert.Equal((int)1, request.LocalId); - } - [Fact] - public void NewGameTest() - { - var raw = @"\newgame\\connid\123\sesskey\123456\lid\1"; - var request = new NewGameRequest(raw); - request.Parse(); - Assert.Equal((int)123, request.ConnectionID); - Assert.Equal((int)123456, request.SessionKey); - Assert.Equal((int)1, request.LocalId); - - raw = @"\newgame\\connid\123\sesskey\123456\challenge\123456789\lid\1"; - request = new NewGameRequest(raw); - request.Parse(); - Assert.Equal((int)123, request.ConnectionID); - Assert.Equal((int)123456, request.SessionKey); - Assert.Equal("123456789", request.Challenge); - Assert.Equal((int)1, request.LocalId); - } - [Fact] - public void SetPlayerDataTest() - { - var raw = @"\setpd\\pid\123\ptype\0\dindex\1\kv\%d\lid\1\length\5\data\11\lid\1"; - var request = new SetPlayerDataRequest(raw); - Assert.Throws(() => request.Parse()); - raw = @"\setpd\\pid\123\ptype\0\dindex\1\kv\%d\lid\1\report\hello\length\5\data\11\lid\1"; - request = new SetPlayerDataRequest(raw); - request.Parse(); - Assert.Equal((int)123, request.ProfileId); - Assert.Equal(PersistStorageType.PrivateRO, request.StorageType); - Assert.Equal((int)1, request.DataIndex); - Assert.Equal((int)5, request.Length); - } - [Fact] - public void UpdateGameTest() - { - var raw = @"\updgame\\sesskey\0\done\1\gamedata\hello\lid\1"; - var request = new UpdateGameRequest(raw); - request.Parse(); - Assert.True(0 == request.SessionKey); - Assert.True(true == request.IsDone); - Assert.True("hello" == request.GameData); - Assert.Null(request.ConnectionID); - - - raw = @"\updgame\\sesskey\0\connid\1\done\1\gamedata\hello\lid\1"; - request = new UpdateGameRequest(raw); - request.Parse(); - Assert.True(0 == request.SessionKey); - Assert.True(true == request.IsDone); - Assert.True("hello" == request.GameData); - Assert.True(1 == request.ConnectionID); - } - } -} diff --git a/src/Servers/GameStatus/test/UniSpy.Server.GameStatus.Test.csproj b/src/Servers/GameStatus/test/UniSpy.Server.GameStatus.Test.csproj deleted file mode 100644 index fc0c4c027..000000000 --- a/src/Servers/GameStatus/test/UniSpy.Server.GameStatus.Test.csproj +++ /dev/null @@ -1,31 +0,0 @@ - - - - net6.0 - false - ..\..\..\..\common\Icon\UniSpy_Logo.ico - - - AnyCPU - ..\..\..\..\build\$(Configuration) - - - ..\..\..\..\build\$(Configuration) - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - \ No newline at end of file diff --git a/src/Servers/GameTrafficRelay/src/Application/Program.cs b/src/Servers/GameTrafficRelay/src/Application/Program.cs deleted file mode 100755 index 98a92506a..000000000 --- a/src/Servers/GameTrafficRelay/src/Application/Program.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using UniSpy.Server.Core.Logging; - -namespace UniSpy.Server.GameTrafficRelay.Application -{ - public class Program - { - static void Main(string[] args) - { - try - { - new ServerLauncher().Start(); - Console.WriteLine("Press < Q > to exit. "); - while (Console.ReadKey().Key != ConsoleKey.Q) { } - } - catch (System.Exception e) - { - LogWriter.LogError(e); - } - } - } -} diff --git a/src/Servers/GameTrafficRelay/src/Application/Server.cs b/src/Servers/GameTrafficRelay/src/Application/Server.cs deleted file mode 100644 index a7d12dfdb..000000000 --- a/src/Servers/GameTrafficRelay/src/Application/Server.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System.Net; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using UniSpy.Server.GameTrafficRelay.Entity; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.GameTrafficRelay.Application -{ - public class Server : ServerBase - { - private ServerStatusReporter _reporter; - static Server() - { - _name = "GameTrafficRelay"; - } - - public Server() : base(null) - { - _reporter = new ServerStatusReporter(this); - } - - public override void Start() - { - _reporter.Start(); - var builder = WebApplication.CreateBuilder(); - builder.Host.ConfigureLogging((ctx, loggerConfiguration) => - { - loggerConfiguration.AddFilter("Microsoft.Hosting.Lifetime", LogLevel.Warning); - }); - // builder.Host.UseSerilog((ctx, loggerConfiguration) => - // { - // loggerConfiguration = LogWriter.LogConfig; - // loggerConfiguration.Enrich.FromLogContext() - // .Enrich.WithProperty("ApplicationName", typeof(Program).Assembly.GetName().Name) - // .Enrich.WithProperty("Environment", ctx.HostingEnvironment) - // .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) - // .MinimumLevel.Override("Microsoft.Hosting.Lifetime", LogEventLevel.Information); - // // .MinimumLevel.Override("Microsoft.Hosting.Lifetime", LogEventLevel.Warning); - // #if DEBUG - // // Used to filter out potentially bad data due debugging. - // // Very useful when doing Seq dashboards and want to remove logs under debugging session. - // loggerConfiguration.Enrich.WithProperty("DebuggerAttached", Debugger.IsAttached); - // #endif - // }); - - // Add services to the container. - builder.Services.AddControllers() - .AddNewtonsoftJson(); - // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle - builder.Services.AddEndpointsApiExplorer(); - builder.Services.AddSwaggerGen(); - - var app = builder.Build(); - - // Configure the HTTP request pipeline. - if (app.Environment.IsDevelopment()) - { - app.UseSwagger(); - app.UseSwaggerUI(); - } - - // app.UseSerilogRequestLogging(); - - app.UseHttpsRedirection(); - - app.UseAuthorization(); - - app.MapControllers(); - // asp.net will block here, we do not want to block our codes, so we let them run in background - Task.Run(() => app.Run($"http://{ListeningIPEndPoint}")); - } - - protected override IConnectionManager CreateConnectionManager(IPEndPoint endPoint) => null; - - protected override IClient CreateClient(IConnection connection) => null; - } -} \ No newline at end of file diff --git a/src/Servers/GameTrafficRelay/src/Application/ServerLauncher.cs b/src/Servers/GameTrafficRelay/src/Application/ServerLauncher.cs deleted file mode 100644 index a845da67f..000000000 --- a/src/Servers/GameTrafficRelay/src/Application/ServerLauncher.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Collections.Generic; -using System.Net; -using UniSpy.Server.Core.Abstraction.BaseClass.Factory; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.GameTrafficRelay.Application -{ - public sealed class ServerLauncher : ServerLauncherBase - { - public static IServer Server => ServerInstances[0]; - protected override List LaunchNetworkService() - { - - var server = new Server(); - if (server.PublicIPEndPoint.Address.Equals(IPAddress.Any) || server.PublicIPEndPoint.Address.Equals(IPAddress.Loopback)) - { - throw new System.Exception("Game traffic relay server public address can not set to 0.0.0.0 or 127.0.0.1 !"); - } - return new List { server }; - } - } -} \ No newline at end of file diff --git a/src/Servers/GameTrafficRelay/src/Application/StorageOperation.cs b/src/Servers/GameTrafficRelay/src/Application/StorageOperation.cs deleted file mode 100644 index 33b92a3d2..000000000 --- a/src/Servers/GameTrafficRelay/src/Application/StorageOperation.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using UniSpy.Server.GameTrafficRelay.Entity; -using UniSpy.Server.GameTrafficRelay.Interface; - -namespace UniSpy.Server.GameTrafficRelay.Application -{ - public sealed class StorageOperation : IStorageOperation - { - /// - /// Game relay server information redis server. - /// - private static RedisClient _redisClient = new RedisClient(); - - public static IStorageOperation Persistance = new StorageOperation(); - public List GetAvaliableRelayServers() - { - return _redisClient.Context.ToList(); - } - } -} \ No newline at end of file diff --git a/src/Servers/GameTrafficRelay/src/Contracts/NatNegotiation.cs b/src/Servers/GameTrafficRelay/src/Contracts/NatNegotiation.cs deleted file mode 100644 index c3cd1e289..000000000 --- a/src/Servers/GameTrafficRelay/src/Contracts/NatNegotiation.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Net; -using Newtonsoft.Json; -using UniSpy.Server.Core.Misc; - -namespace UniSpy.Server.GameTrafficRelay -{ - public record NatNegotiationRequest - { - public uint Cookie { get; set; } - public Guid ServerId { get; set; } - } - public record NatNegotiationResponse - { - [JsonConverter(typeof(IPEndPointConverter))] - public IPEndPoint IPEndPoint1 { get; set; } - [JsonConverter(typeof(IPEndPointConverter))] - public IPEndPoint IPEndPoint2 { get; set; } - } -} \ No newline at end of file diff --git a/src/Servers/GameTrafficRelay/src/Controllers/NatNegotiationController.cs b/src/Servers/GameTrafficRelay/src/Controllers/NatNegotiationController.cs deleted file mode 100644 index 56dcf4fcb..000000000 --- a/src/Servers/GameTrafficRelay/src/Controllers/NatNegotiationController.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Collections.Concurrent; -using System.Net; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Logging; -using UniSpy.Server.GameTrafficRelay.Application; -using UniSpy.Server.GameTrafficRelay.Entity; -using UniSpy.Server.GameTrafficRelay.Aggregate; -using System.Threading.Tasks; - -namespace UniSpy.Server.GameTrafficRelay.Controller -{ - [ApiController] - [Route("[controller]")] - public class NatNegotiationController : ControllerBase - { - private readonly ILogger _logger; - public static ConcurrentDictionary ConnectionPairs = new ConcurrentDictionary(); - public NatNegotiationController(ILogger logger) - { - _logger = logger; - } - [HttpPost] - public Task GetNatNegotiationInfo(NatNegotiationRequest request) - { - // natneg connecthandler will send 2 request to game traffic relay - ConnectionPair pair; - if (!ConnectionPairs.TryGetValue(request.Cookie, out pair)) - { - var ports = NetworkUtils.GetAvailablePorts(); - var ends = new IPEndPoint[]{new IPEndPoint(IPAddress.Any,ports[0]), - new IPEndPoint(IPAddress.Any,ports[1])}; - pair = new ConnectionPair(ends[0], ends[1], request.Cookie); - ConnectionPairs.TryAdd(request.Cookie, pair); - } - - var response = new NatNegotiationResponse() - { - IPEndPoint1 = new IPEndPoint(ServerLauncher.Server.PublicIPEndPoint.Address, pair.Listener1.ListeningEndPoint.Port), - IPEndPoint2 = new IPEndPoint(ServerLauncher.Server.PublicIPEndPoint.Address, pair.Listener2.ListeningEndPoint.Port) - }; - return Task.FromResult(response); - } - } -} - - diff --git a/src/Servers/GameTrafficRelay/src/Dockerfile b/src/Servers/GameTrafficRelay/src/Dockerfile deleted file mode 100755 index 88e190851..000000000 --- a/src/Servers/GameTrafficRelay/src/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base -WORKDIR /app -EXPOSE 10086/udp - -FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build -WORKDIR /src -COPY ["src/Servers/GameTrafficRelay/src/UniSpy.Server.GameTrafficRelay.csproj", "src/Servers/GameTrafficRelay/src/"] -COPY ["src/Libraries/Core/src/UniSpy.Server.Core.csproj", "src/Libraries/Core/src/"] -RUN dotnet restore "src/Servers/GameTrafficRelay/src/UniSpy.Server.GameTrafficRelay.csproj" -COPY . . -WORKDIR "/src/src/Servers/GameTrafficRelay/src" -RUN dotnet build "UniSpy.Server.GameTrafficRelay.csproj" -c Release -o /app/build - -FROM build AS publish -RUN dotnet publish "UniSpy.Server.GameTrafficRelay.csproj" -c Release -o /app/publish - -FROM base AS final -WORKDIR /app -COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "UniSpy.Server.GameTrafficRelay.dll"] \ No newline at end of file diff --git a/src/Servers/GameTrafficRelay/src/Entity/ConnectionForwardClient.cs b/src/Servers/GameTrafficRelay/src/Entity/ConnectionForwardClient.cs deleted file mode 100644 index 734c97ba0..000000000 --- a/src/Servers/GameTrafficRelay/src/Entity/ConnectionForwardClient.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.GameTrafficRelay.Interface; -using UniSpy.Server.Core.Extension; -using UniSpy.Server.Core.Logging; -namespace UniSpy.Server.GameTrafficRelay.Aggregate -{ - public sealed class ConnectionForwardClient : IConnectionForwardClient - { - public IConnectionListener GameSpyTrafficListener { get; set; } - public IConnectionForwardClient ForwardTargetClient { get; set; } - public ConnectionForwardClient() - { - } - public void ForwardMessage(byte[] data) - { - LogWriter.LogDebug($" [{GameSpyTrafficListener.ListeningEndPoint}] => [{ForwardTargetClient.GameSpyTrafficListener.ListeningEndPoint}] {StringExtensions.ConvertPrintableBytesToString(data)} [{StringExtensions.ConvertByteToHexString(data)}]"); - ForwardTargetClient.ForwardMessage(data); - } - } -} \ No newline at end of file diff --git a/src/Servers/GameTrafficRelay/src/Entity/ConnectionListener.cs b/src/Servers/GameTrafficRelay/src/Entity/ConnectionListener.cs deleted file mode 100644 index 0d29ccd52..000000000 --- a/src/Servers/GameTrafficRelay/src/Entity/ConnectionListener.cs +++ /dev/null @@ -1,108 +0,0 @@ -using System; -using System.Linq; -using System.Net; -using System.Threading; -using UniSpy.Server.GameTrafficRelay.Controller; -using UniSpy.Server.GameTrafficRelay.Interface; -using UniSpy.Server.Core.Extension; -using UniSpy.Server.Core.Logging; - -namespace UniSpy.Server.GameTrafficRelay.Aggregate -{ - public class ConnectionListener : NetCoreServer.UdpServer, IConnectionListener - { - public uint Cookie { get; private set; } - public IPEndPoint ListeningEndPoint => (IPEndPoint)Endpoint; - /// - /// The other gamespy client that message need forward to - /// - public IConnectionListener ForwardTargetListener { get; set; } - public IPEndPoint GameSpyClientIPEndPoint { get; private set; } - public DateTime LastPacketReceivedTime { get; private set; } - public TimeSpan ConnectionExistedTime => DateTime.Now - LastPacketReceivedTime; - private TimeSpan _expireTimeInterval; - private System.Timers.Timer _timer; - public ConnectionListener(IPEndPoint listeningEndPoint, uint cookie) : base(listeningEndPoint.Address, listeningEndPoint.Port) - { - // after create listener we start it - Cookie = cookie; - Start(); - LastPacketReceivedTime = DateTime.Now; - // we set expire time to 2 minutes - _expireTimeInterval = new TimeSpan(0, 2, 0); - _timer = new System.Timers.Timer - { - Enabled = true, - Interval = 60000, - AutoReset = true - };//10000 - _timer.Start(); - _timer.Elapsed += (s, e) => CheckExpiredClient(); - LogWriter.LogDebug($"[{ListeningEndPoint}] gamespy client listener started."); - } - protected override void OnStarted() => ReceiveAsync(); - private void CheckExpiredClient() - { - // we calculate the interval between last packe and current time - if (ConnectionExistedTime > _expireTimeInterval) - { - ((IConnectionListener)this).Dispose(); - } - } - protected override void OnReceived(EndPoint endpoint, byte[] buffer, long offset, long size) - { - var message = buffer.Skip((int)offset).Take((int)size).ToArray(); - OnReceived(endpoint, message); - } - protected void OnReceived(EndPoint endPoint, byte[] buffer) - { - // we only accept the gamespy client message - - if (GameSpyClientIPEndPoint is null) - { - GameSpyClientIPEndPoint = (IPEndPoint)endPoint; - } - - ThreadPool.QueueUserWorkItem(o => { try { ReceiveAsync(); } catch { } }); - LogWriter.LogDebug($"[{GameSpyClientIPEndPoint}] [recv] {StringExtensions.ConvertPrintableBytesToString(buffer)} [{StringExtensions.ConvertByteToHexString(buffer)}]"); - ForwardTargetListener.ForwardMessage(buffer); - LastPacketReceivedTime = DateTime.Now; - } - - public void ForwardMessage(byte[] data) - { - // we must send the every message to both client - var retryCount = 0; - // we wait for clients connect 5 sec - if (GameSpyClientIPEndPoint is null) - { - LogWriter.LogDebug($"[{ListeningEndPoint}] is waiting for gamespy client to connect."); - Thread.Sleep(5000); - retryCount++; - } - - // after waiting for 10 sec client still not connecting we just dispose it - if (GameSpyClientIPEndPoint is null) - { - ForwardTargetListener?.Dispose(); - if (NatNegotiationController.ConnectionPairs.TryGetValue(Cookie, out _)) - { - NatNegotiationController.ConnectionPairs.TryRemove(Cookie, out _); - } - ((IConnectionListener)this).Dispose(); - return; - } - LogWriter.LogDebug($"[{ListeningEndPoint}] => [{GameSpyClientIPEndPoint}] {StringExtensions.ConvertPrintableBytesToString(data)} [{StringExtensions.ConvertByteToHexString(data)}]"); - SendAsync(GameSpyClientIPEndPoint, data); - } - - void IConnectionListener.Dispose() - { - if (!IsDisposed) - { - LogWriter.LogDebug($"[{ListeningEndPoint}] gamespy client listener stoped"); - Dispose(); - } - } - } -} \ No newline at end of file diff --git a/src/Servers/GameTrafficRelay/src/Entity/ConnectionPairs.cs b/src/Servers/GameTrafficRelay/src/Entity/ConnectionPairs.cs deleted file mode 100644 index 1631f7fb5..000000000 --- a/src/Servers/GameTrafficRelay/src/Entity/ConnectionPairs.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Net; -using UniSpy.Server.GameTrafficRelay.Interface; - -namespace UniSpy.Server.GameTrafficRelay.Aggregate -{ - public class ConnectionForwardBridge - { - public IConnectionForwardClient Client { get; private set; } - public IConnectionListener Listener { get; private set; } - public ConnectionForwardBridge(IConnectionListener listener, IConnectionForwardClient client) - { - Listener = listener; - Client = client; - } - } - /// - /// This class represent a connection pair, - /// in this class 2 IConnectionForwardBridge instances is created and listen to 2 different avaliable udp port. - /// The message send from gamespy client is redirect by the client in IConnectionForwardBridge - /// - public sealed class ConnectionPair - { - public uint Cookie { get; private set; } - public IConnectionListener Listener1 { get; private set; } - public IConnectionListener Listener2 { get; private set; } - - public ConnectionPair(IPEndPoint gameSpyClient1ListeningEnd, IPEndPoint gameSpyClient2ListeningEnd, uint cookie) - { - Cookie = cookie; - Listener1 = new ConnectionListener(gameSpyClient1ListeningEnd, cookie); - Listener2 = new ConnectionListener(gameSpyClient2ListeningEnd, cookie); - // bind listener1 with client1 - Listener1.ForwardTargetListener = Listener2; - Listener2.ForwardTargetListener = Listener1; - } - } -} \ No newline at end of file diff --git a/src/Servers/GameTrafficRelay/src/Entity/NetworkUtils.cs b/src/Servers/GameTrafficRelay/src/Entity/NetworkUtils.cs deleted file mode 100644 index f9c85698a..000000000 --- a/src/Servers/GameTrafficRelay/src/Entity/NetworkUtils.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.Linq; -using System.Net.NetworkInformation; - -namespace UniSpy.Server.GameTrafficRelay.Entity -{ - public sealed class NetworkUtils - { - /// - /// Find 2 ports is not using by other programs - /// - /// - /// ports array - public static int[] GetAvailablePorts(int startingPort = 1025) - { - var properties = IPGlobalProperties.GetIPGlobalProperties(); - - //getting active connections - var tcpConnectionPorts = properties.GetActiveTcpConnections() - .Where(n => n.LocalEndPoint.Port >= startingPort) - .Select(n => n.LocalEndPoint.Port); - - //getting active tcp listners - WCF service listening in tcp - var tcpListenerPorts = properties.GetActiveTcpListeners() - .Where(n => n.Port >= startingPort) - .Select(n => n.Port); - - //getting active udp listeners - var udpListenerPorts = properties.GetActiveUdpListeners() - .Where(n => n.Port >= startingPort) - .Select(n => n.Port); - - var ports = Enumerable.Range(startingPort, ushort.MaxValue) - .Where(i => !tcpConnectionPorts.Contains(i)) - .Where(i => !tcpListenerPorts.Contains(i)) - .Where(i => !udpListenerPorts.Contains(i)) - .Take(2).ToArray(); - - return ports; - } - } -} \ No newline at end of file diff --git a/src/Servers/GameTrafficRelay/src/Entity/RelayServerInfo.cs b/src/Servers/GameTrafficRelay/src/Entity/RelayServerInfo.cs deleted file mode 100644 index 74b82c0b6..000000000 --- a/src/Servers/GameTrafficRelay/src/Entity/RelayServerInfo.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Net; -using Newtonsoft.Json; -using StackExchange.Redis; -using UniSpy.LinqToRedis; -using UniSpy.Server.Core.Config; -using UniSpy.Server.Core.Extension.Redis; -using UniSpy.Server.Core.Misc; - -namespace UniSpy.Server.GameTrafficRelay.Entity -{ - public record RelayServerInfo : UniSpy.Server.Core.Abstraction.BaseClass.RedisKeyValueObject - { - [RedisKey] - public Guid? ServerID { get; init; } - [RedisKey] - [JsonConverter(typeof(IPEndPointConverter))] - public IPEndPoint PublicIPEndPoint { get; init; } - public int ClientCount { get; set; } - - public RelayServerInfo() : base(RedisDbNumber.GameTrafficRelay, TimeSpan.FromMinutes(1)) - { - } - } - - public class RedisClient : UniSpy.Server.Core.Abstraction.BaseClass.RedisClient - { - public RedisClient() { } - } -} \ No newline at end of file diff --git a/src/Servers/GameTrafficRelay/src/Entity/ServerStatusReporter.cs b/src/Servers/GameTrafficRelay/src/Entity/ServerStatusReporter.cs deleted file mode 100644 index f94bb0728..000000000 --- a/src/Servers/GameTrafficRelay/src/Entity/ServerStatusReporter.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using UniSpy.Server.GameTrafficRelay.Controller; -using UniSpy.Server.Core.Extension; - -namespace UniSpy.Server.GameTrafficRelay.Entity -{ - internal class ServerStatusReporter - { - private EasyTimer _myTimer; - private RedisClient _redisClient = new RedisClient(); - private Core.Abstraction.Interface.IServer _server; - public ServerStatusReporter(Core.Abstraction.Interface.IServer server) - { - _server = server; - UpdateServerInfo(); - } - public void Start() - { - _myTimer = new EasyTimer(TimeSpan.FromMinutes(1), TimeSpan.FromSeconds(10), UpdateServerInfo); - } - private void UpdateServerInfo() - { - var info = new RelayServerInfo() - { - ServerID = _server.Id, - PublicIPEndPoint = _server.PublicIPEndPoint, - ClientCount = NatNegotiationController.ConnectionPairs.Values.Count * 2 - }; - _ = _redisClient.SetValueAsync(info); - var data = _redisClient.GetKeyValues(); - } - } -} \ No newline at end of file diff --git a/src/Servers/GameTrafficRelay/src/Interface/IConnectionForwardClient.cs b/src/Servers/GameTrafficRelay/src/Interface/IConnectionForwardClient.cs deleted file mode 100644 index 51ca82c01..000000000 --- a/src/Servers/GameTrafficRelay/src/Interface/IConnectionForwardClient.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace UniSpy.Server.GameTrafficRelay.Interface -{ - public interface IConnectionForwardClient - { - IConnectionListener GameSpyTrafficListener { get; } - IConnectionForwardClient ForwardTargetClient { get; } - void ForwardMessage(byte[] data); - } -} \ No newline at end of file diff --git a/src/Servers/GameTrafficRelay/src/Interface/IConnectionListener.cs b/src/Servers/GameTrafficRelay/src/Interface/IConnectionListener.cs deleted file mode 100644 index a909ae9a1..000000000 --- a/src/Servers/GameTrafficRelay/src/Interface/IConnectionListener.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Net; - -namespace UniSpy.Server.GameTrafficRelay.Interface -{ - public interface IConnectionListener - { - IPEndPoint ListeningEndPoint { get; } - // IConnectionForwardClient Client { get; } - IPEndPoint GameSpyClientIPEndPoint { get; } - public IConnectionListener ForwardTargetListener { get; set; } - - void ForwardMessage(byte[] data); - void Dispose(); - } -} \ No newline at end of file diff --git a/src/Servers/GameTrafficRelay/src/Interface/IStorageOperation.cs b/src/Servers/GameTrafficRelay/src/Interface/IStorageOperation.cs deleted file mode 100644 index 006262927..000000000 --- a/src/Servers/GameTrafficRelay/src/Interface/IStorageOperation.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.GameTrafficRelay.Entity; - -namespace UniSpy.Server.GameTrafficRelay.Interface -{ - public interface IStorageOperation - { - List GetAvaliableRelayServers(); - } -} \ No newline at end of file diff --git a/src/Servers/GameTrafficRelay/src/UniSpy.Server.GameTrafficRelay.csproj b/src/Servers/GameTrafficRelay/src/UniSpy.Server.GameTrafficRelay.csproj deleted file mode 100644 index f7ad3587f..000000000 --- a/src/Servers/GameTrafficRelay/src/UniSpy.Server.GameTrafficRelay.csproj +++ /dev/null @@ -1,28 +0,0 @@ - - - - Exe - net6.0 - ..\..\..\..\common\Icon\UniSpy_Logo.ico - Linux - ..\..\..\.. - - - ..\..\..\..\build\$(Configuration) - - - ..\..\..\..\build\$(Configuration) - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Servers/GameTrafficRelay/src/appsettings.Development.json b/src/Servers/GameTrafficRelay/src/appsettings.Development.json deleted file mode 100644 index ff66ba6b2..000000000 --- a/src/Servers/GameTrafficRelay/src/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} diff --git a/src/Servers/GameTrafficRelay/src/appsettings.json b/src/Servers/GameTrafficRelay/src/appsettings.json deleted file mode 100644 index 4d566948d..000000000 --- a/src/Servers/GameTrafficRelay/src/appsettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "AllowedHosts": "*" -} diff --git a/src/Servers/GameTrafficRelay/test/GameTest.cs b/src/Servers/GameTrafficRelay/test/GameTest.cs deleted file mode 100644 index 0492d7507..000000000 --- a/src/Servers/GameTrafficRelay/test/GameTest.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Net; -using Xunit; -using UniSpy.Server.GameTrafficRelay.Controller; -using System.Net.NetworkInformation; -using UniSpy.Server.GameTrafficRelay.Application; -using Moq; - -namespace UniSpy.Server.GameTrafficRelay.Test -{ - public class GameTest - { - public GameTest() - { - TestClasses.CreateServer(); - } - - [Fact] - public void GetNagNegotiationInfo() - { - var mockServer = new Mock(); - mockServer.Setup(s => s.PublicIPEndPoint).Returns(IPEndPoint.Parse("202.91.0.1:123")); - ServerLauncher.ServerInstances.Add(mockServer.Object); - - var httpContext = new Microsoft.AspNetCore.Http.DefaultHttpContext(); - - var controllerContext = new Microsoft.AspNetCore.Mvc.ControllerContext() - { - HttpContext = httpContext - }; - controllerContext.HttpContext.Connection.LocalIpAddress = IPAddress.Parse("127.0.0.1"); - var controller = new NatNegotiationController(null) - { - ControllerContext = controllerContext - }; - - var request = new NatNegotiationRequest() - { - Cookie = 123456, - ServerId = System.Guid.NewGuid() - }; - - controller.GetNatNegotiationInfo(request); - - // Assert.ThrowsAsync(() => controller.GetNatNegotiationInfo(request)); - - // var resp = controller.GetNatNegotiationInfo(request); - - // Assert.True(IsPortUsing(resp.IPEndPoint1.Port)); - // Assert.True(IsPortUsing(resp.IPEndPoint2.Port)); - // var sock = new Socket(AddressFamily.InterNetwork, - // SocketType.Dgram, - // ProtocolType.Udp); - // // we only use one client to send message to check if the listener shutdown - // var req = new byte[] { 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x07, 0x00, 0x00, 0x02, 0x9A, 0xC0, 0xA8, 0x01, 0x67, 0x6C, 0xFD, 0x00, 0x00 }; - // sock.SendTo(req, resp.IPEndPoint1); - // // Thread.Sleep(10000); - // // we check if listener is stoped - // Assert.False(IsPortUsing(resp.IPEndPoint1.Port)); - // Assert.False(IsPortUsing(resp.IPEndPoint2.Port)); - // // because we are not runing server, so the server object is null - // Assert.Null(resp.IPEndPoint1); - // Assert.Null(resp.IPEndPoint2); - - } - internal static bool IsPortUsing(int port) - { - var tcpPorts = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners().Select(p => p.Port).ToArray(); - var udpPorts = IPGlobalProperties.GetIPGlobalProperties().GetActiveUdpListeners().Select(p => p.Port).ToArray(); - var usedPorts = new List(); - usedPorts.AddRange(tcpPorts); - usedPorts.AddRange(udpPorts); - usedPorts.Sort(); - usedPorts.Distinct(); - if (usedPorts.Contains(port)) - { - return true; - } - else - { - return false; - } - } - } -} \ No newline at end of file diff --git a/src/Servers/GameTrafficRelay/test/TestClasses.cs b/src/Servers/GameTrafficRelay/test/TestClasses.cs deleted file mode 100644 index e9c39dd19..000000000 --- a/src/Servers/GameTrafficRelay/test/TestClasses.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Net; -using Moq; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.GameTrafficRelay.Test -{ - public static class TestClasses - { - public static IServer Server = CreateServer(); - - public static IServer CreateServer(string ipAddress = "192.168.1.1", int port = 9999) - { - var managerMock = new Mock(); - var connectionMock = new Mock(); - connectionMock.Setup(s => s.RemoteIPEndPoint).Returns(new IPEndPoint(IPAddress.Parse(ipAddress), port)); - connectionMock.Setup(s => s.Manager).Returns(managerMock.Object); - connectionMock.Setup(s => s.ConnectionType).Returns(NetworkConnectionType.Tcp); - var serverMock = new GameTrafficRelay.Application.Server(); - return serverMock; - } - } -} \ No newline at end of file diff --git a/src/Servers/GameTrafficRelay/test/UniSpy.Server.GameTrafficRelay.Test.csproj b/src/Servers/GameTrafficRelay/test/UniSpy.Server.GameTrafficRelay.Test.csproj deleted file mode 100644 index 6e8d71534..000000000 --- a/src/Servers/GameTrafficRelay/test/UniSpy.Server.GameTrafficRelay.Test.csproj +++ /dev/null @@ -1,31 +0,0 @@ - - - - net6.0 - false - ..\..\..\..\common\Icon\UniSpy_Logo.ico - - - AnyCPU - ..\..\..\..\build\$(Configuration) - - - ..\..\..\..\build\$(Configuration) - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Abstraction/BaseClass/CmdHandlerBase.cs b/src/Servers/NatNegotiation/src/Abstraction/BaseClass/CmdHandlerBase.cs deleted file mode 100755 index b5856b6c2..000000000 --- a/src/Servers/NatNegotiation/src/Abstraction/BaseClass/CmdHandlerBase.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.NatNegotiation.Application; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.NatNegotiation.Abstraction.BaseClass -{ - /// - /// because we are using self defined error code so we do not need - /// to send it to client, when we detect errorCode != noerror we just log it - /// - public abstract class CmdHandlerBase : UniSpy.Server.Core.Abstraction.BaseClass.CmdHandlerBase - { - protected new Client _client => (Client)base._client; - protected new RequestBase _request => (RequestBase)base._request; - protected new ResultBase _result { get => (ResultBase)base._result; set => base._result = value; } - public CmdHandlerBase(IClient client, IRequest request) : base(client, request) - { - } - } -} diff --git a/src/Servers/NatNegotiation/src/Abstraction/BaseClass/CommonRequestBase.cs b/src/Servers/NatNegotiation/src/Abstraction/BaseClass/CommonRequestBase.cs deleted file mode 100644 index ac0e33d14..000000000 --- a/src/Servers/NatNegotiation/src/Abstraction/BaseClass/CommonRequestBase.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using UniSpy.Server.NatNegotiation.Enumerate; - -namespace UniSpy.Server.NatNegotiation.Abstraction.BaseClass -{ - public abstract class CommonRequestBase : RequestBase - { - public NatClientIndex ClientIndex { get; protected set; } - public bool UseGamePort { get; protected set; } - protected CommonRequestBase(byte[] rawRequest) : base(rawRequest) - { - } - public override void Parse() - { - base.Parse(); - ClientIndex = (NatClientIndex)RawRequest[13]; - UseGamePort = Convert.ToBoolean(RawRequest[14]); - } - } -} diff --git a/src/Servers/NatNegotiation/src/Abstraction/BaseClass/CommonResponseBase.cs b/src/Servers/NatNegotiation/src/Abstraction/BaseClass/CommonResponseBase.cs deleted file mode 100644 index 32f01034c..000000000 --- a/src/Servers/NatNegotiation/src/Abstraction/BaseClass/CommonResponseBase.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace UniSpy.Server.NatNegotiation.Abstraction.BaseClass -{ - public abstract class CommonResponseBase : ResponseBase - { - private new CommonResultBase _result => (CommonResultBase)base._result; - private new CommonRequestBase _request => (CommonRequestBase)base._request; - public CommonResponseBase(UniSpy.Server.Core.Abstraction.BaseClass.RequestBase request, UniSpy.Server.Core.Abstraction.BaseClass.ResultBase result) : base(request, result) - { - } - public override void Build() - { - base.Build(); - List data = new List(); - data.AddRange(SendingBuffer); - data.Add((byte)_request.PortType); - data.Add((byte)_request.ClientIndex); - data.Add(Convert.ToByte(_request.UseGamePort)); - data.AddRange(_result.RemoteIPAddressBytes); - data.AddRange(_result.RemotePortBytes); - SendingBuffer = data.ToArray(); - } - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Abstraction/BaseClass/CommonResultBase.cs b/src/Servers/NatNegotiation/src/Abstraction/BaseClass/CommonResultBase.cs deleted file mode 100644 index 19b553108..000000000 --- a/src/Servers/NatNegotiation/src/Abstraction/BaseClass/CommonResultBase.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Linq; -using System.Net; - -namespace UniSpy.Server.NatNegotiation.Abstraction.BaseClass -{ - public abstract class CommonResultBase : ResultBase - { - public IPEndPoint RemoteIPEndPoint { get; set; } - public byte[] RemoteIPAddressBytes => RemoteIPEndPoint.Address.GetAddressBytes().ToArray(); - public byte[] RemotePortBytes => BitConverter.GetBytes((ushort)RemoteIPEndPoint.Port).Reverse().ToArray(); - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Abstraction/BaseClass/RequestBase.cs b/src/Servers/NatNegotiation/src/Abstraction/BaseClass/RequestBase.cs deleted file mode 100755 index 151ed3344..000000000 --- a/src/Servers/NatNegotiation/src/Abstraction/BaseClass/RequestBase.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Linq; -using UniSpy.Server.NatNegotiation.Enumerate; - -namespace UniSpy.Server.NatNegotiation.Abstraction.BaseClass -{ - /// - /// NatNeg request base - /// - public abstract class RequestBase : UniSpy.Server.Core.Abstraction.BaseClass.RequestBase - { - public static readonly byte[] MagicData = { 0xfd, 0xfc, 0x1e, 0x66, 0x6a, 0xb2 }; - public new byte[] RawRequest => (byte[])base.RawRequest; - public byte Version { get; protected set; } - /// - /// Cookie is a random int, which we can not trace two clients - /// - /// - public uint Cookie { get; protected set; } - public NatPortType PortType { get; protected set; } - public new RequestType CommandName { get => (RequestType)base.CommandName; set => base.CommandName = value; } - public RequestBase(byte[] rawRequest) : base(rawRequest) - { - } - public RequestBase() { } - public override void Parse() - { - if (RawRequest.Length < 12) - { - return; - } - - Version = RawRequest[6]; - CommandName = (RequestType)RawRequest[7]; - Cookie = BitConverter.ToUInt32(RawRequest.Skip(8).Take(4).ToArray()); - PortType = (NatPortType)RawRequest[12]; - } - } -} diff --git a/src/Servers/NatNegotiation/src/Abstraction/BaseClass/ResponseBase.cs b/src/Servers/NatNegotiation/src/Abstraction/BaseClass/ResponseBase.cs deleted file mode 100755 index b785d1b4d..000000000 --- a/src/Servers/NatNegotiation/src/Abstraction/BaseClass/ResponseBase.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Collections.Generic; -// ReSharper disable All - -namespace UniSpy.Server.NatNegotiation.Abstraction.BaseClass -{ - public abstract class ResponseBase : UniSpy.Server.Core.Abstraction.BaseClass.ResponseBase - { - protected new RequestBase _request => (RequestBase)base._request; - protected new ResultBase _result => (ResultBase)base._result; - public new byte[] SendingBuffer - { - get => (byte[])base.SendingBuffer; - protected set => base.SendingBuffer = value; - } - public ResponseBase(UniSpy.Server.Core.Abstraction.BaseClass.RequestBase request, UniSpy.Server.Core.Abstraction.BaseClass.ResultBase result) : base(request, result) - { - } - public override void Build() - { - List data = new List(); - data.AddRange(RequestBase.MagicData); - data.Add((byte)_request.Version); - data.Add((byte)_result.PacketType); - data.AddRange(BitConverter.GetBytes((uint)_request.Cookie)); - SendingBuffer = data.ToArray(); - } - } -} diff --git a/src/Servers/NatNegotiation/src/Abstraction/BaseClass/ResultBase.cs b/src/Servers/NatNegotiation/src/Abstraction/BaseClass/ResultBase.cs deleted file mode 100755 index 4f5b6f75d..000000000 --- a/src/Servers/NatNegotiation/src/Abstraction/BaseClass/ResultBase.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.NatNegotiation.Enumerate; - -namespace UniSpy.Server.NatNegotiation.Abstraction.BaseClass -{ - public class ResultBase : UniSpy.Server.Core.Abstraction.BaseClass.ResultBase - { - public ResponseType? PacketType { get; set; } - public ResultBase() - { - } - } -} diff --git a/src/Servers/NatNegotiation/src/Abstraction/Interface/IStorageOperation.cs b/src/Servers/NatNegotiation/src/Abstraction/Interface/IStorageOperation.cs deleted file mode 100644 index 9a22c1584..000000000 --- a/src/Servers/NatNegotiation/src/Abstraction/Interface/IStorageOperation.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using UniSpy.Server.NatNegotiation.Aggregate.Redis; - -namespace UniSpy.Server.NatNegotiation.Abstraction.Interface -{ - public interface IStorageOperation - { - void UpdateInitInfo(NatAddressInfo info); - int CountInitInfo(uint cookie, byte version); - List GetInitInfos(Guid serverId, uint cookie); - void RemoveInitInfo(NatAddressInfo info); - void UpdateNatFailInfo(NatNegotiation.Aggregate.Redis.Fail.NatFailInfo info); - int GetNatFailInfo(NatNegotiation.Aggregate.Redis.Fail.NatFailInfo info); - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Aggregate/Misc/NatProperty.cs b/src/Servers/NatNegotiation/src/Aggregate/Misc/NatProperty.cs deleted file mode 100644 index 8f7ec37b4..000000000 --- a/src/Servers/NatNegotiation/src/Aggregate/Misc/NatProperty.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.NatNegotiation.Enumerate; - -namespace UniSpy.Server.NatNegotiation.Aggregate.Misc -{ - public record NatProperty - { - public NatType NatType { get; set; } - public NatPortMappingScheme PortMapping { get; set; } - public int PortIncrement { get; set; } - public bool isPortRestricted { get; set; } - public bool isIPRestricted { get; set; } - public NatProperty() - { - NatType = NatType.Unknown; - PortMapping = NatPortMappingScheme.Unrecognized; - isPortRestricted = false; - isIPRestricted = false; - } - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Aggregate/Misc/NatReportInfo.cs b/src/Servers/NatNegotiation/src/Aggregate/Misc/NatReportInfo.cs deleted file mode 100644 index 8a93fccde..000000000 --- a/src/Servers/NatNegotiation/src/Aggregate/Misc/NatReportInfo.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Net; -using UniSpy.Server.NatNegotiation.Enumerate; - -namespace UniSpy.Server.NatNegotiation.Aggregate.Misc -{ - public class NatReportRecord - { - public Guid ServerId { get; init; } - public IPAddress PublicIPAddress { get; init; } - public IPAddress PrivateIPAddress { get; init; } - public NatPunchStrategy CurrentPunchStrategy { get; set; } - } - public class NatReportInfo - { - public NatReportRecord MyRecord; - public NatReportRecord OthersRecord; - public static string CreateKey(IPAddress myPublicIPAddress, IPAddress myPrivateIPAddress, Guid otherClientServerId, IPAddress otherClientPrivateIP, NatClientIndex clientIndex) - { - return $"{myPublicIPAddress} {myPrivateIPAddress} {otherClientServerId} {otherClientPrivateIP} {clientIndex}"; - } - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Aggregate/Redis/NatAddressInfo.cs b/src/Servers/NatNegotiation/src/Aggregate/Redis/NatAddressInfo.cs deleted file mode 100644 index a3ed2046d..000000000 --- a/src/Servers/NatNegotiation/src/Aggregate/Redis/NatAddressInfo.cs +++ /dev/null @@ -1,200 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net; -using Newtonsoft.Json; -using UniSpy.LinqToRedis; -using UniSpy.Server.NatNegotiation.Enumerate; -using UniSpy.Server.Core.Config; -using UniSpy.Server.Core.Misc; -using UniSpy.Server.NatNegotiation.Handler.CmdHandler; -using System.Linq; -using UniSpy.Server.Core.Extension.Redis; - -namespace UniSpy.Server.NatNegotiation.Aggregate.Redis -{ - public record NatAddressInfo : UniSpy.Server.Core.Abstraction.BaseClass.RedisKeyValueObject - { - [RedisKey] - public Guid? ServerID { get; init; } - [RedisKey] - public uint? Cookie { get; init; } - [RedisKey] - public byte? Version { get; init; } - [RedisKey] - public NatPortType? PortType { get; init; } - [RedisKey] - public NatClientIndex? ClientIndex { get; init; } - [RedisKey] - public string GameName { get; init; } - public bool UseGamePort { get; init; } - [JsonConverter(typeof(IPEndPointConverter))] - public IPEndPoint PublicIPEndPoint { get; init; } - /// - /// The nat negotiation private ip and port using as p2p port - /// nn1,nn2,nn3 is using to detect NAT type - /// - [JsonConverter(typeof(IPEndPointConverter))] - public IPEndPoint PrivateIPEndPoint { get; init; } - - public NatAddressInfo() : base(RedisDbNumber.NatAddressInfo, TimeSpan.FromMinutes(3)) - { - } - } - public record NatInitInfo - { - public uint Cookie => (uint)AddressInfos.Values.Last().Cookie; - public byte Version => (byte)AddressInfos.Values.Last().Version; - public NatClientIndex ClientIndex => (NatClientIndex)AddressInfos.Values.Last().ClientIndex; - /// - /// Indicate whether game use the socket create by natneg sdk to communicate, - /// if game did not use game port, after negotiation the game communication is not established, - /// there is a port created by game that will be use to communicate - /// - public bool UseGamePort => AddressInfos.Values.Last().UseGamePort; - /// - /// Some game will not send GP init packet, we use NN3 as default. - /// - public IPEndPoint PublicIPEndPoint - { - get - { - if (Version == 2) - { - return AddressInfos[NatPortType.NN2].PublicIPEndPoint; - } - else - { - return AddressInfos[NatPortType.NN3].PublicIPEndPoint; - } - } - } - /// - /// The private address will show in NN2 and NN3 packets, in here we use private ip in NN3 as default - /// - public IPEndPoint PrivateIPEndPoint - { - get - { - if (Version == 2) - { - return AddressInfos[NatPortType.NN2].PrivateIPEndPoint; - } - else - { - return AddressInfos[NatPortType.NN3].PrivateIPEndPoint; - } - } - } - public NatType NatType - { - get - { - if (Version == 2) - { - return AddressCheckHandler.DetermineNatTypeVersion2(this).NatType; - } - else - { - return AddressCheckHandler.DetermineNatTypeVersion3(this).NatType; - } - } - } - - public Dictionary AddressInfos { get; private set; } - - public NatInitInfo(List infos) - { - AddressInfos = infos.Select((i) => new { i }).ToDictionary(a => ((NatPortType)a.i.PortType), a => a.i); - if (infos.First().Version == 2) - { - if (!(AddressInfos.ContainsKey(NatPortType.NN1) - && AddressInfos.ContainsKey(NatPortType.NN2))) - { - throw new NatNegotiation.Exception("Incomplete init packets"); - } - - if (AddressInfos[NatPortType.NN1].Cookie != AddressInfos[NatPortType.NN2].Cookie) - { - throw new NatNegotiation.Exception("Broken cookie"); - } - if (AddressInfos[NatPortType.NN1].Version != AddressInfos[NatPortType.NN2].Version) - { - throw new NatNegotiation.Exception("Broken version"); - } - if (AddressInfos[NatPortType.NN1].ClientIndex != AddressInfos[NatPortType.NN2].ClientIndex) - { - throw new NatNegotiation.Exception("Broken client index"); - } - if (!AddressInfos[NatPortType.NN1].PrivateIPEndPoint.Equals(AddressInfos[NatPortType.NN2].PrivateIPEndPoint)) - { - throw new NatNegotiation.Exception("Client is sending wrong initpacket."); - } - if (AddressInfos.ContainsKey(NatPortType.GP)) - { - if (AddressInfos[NatPortType.GP].Cookie != AddressInfos[NatPortType.NN1].Cookie || - AddressInfos[NatPortType.GP].Version != AddressInfos[NatPortType.NN1].Version || - AddressInfos[NatPortType.GP].ClientIndex != AddressInfos[NatPortType.NN1].ClientIndex || - AddressInfos[NatPortType.GP].UseGamePort != AddressInfos[NatPortType.NN1].UseGamePort) - { - throw new NatNegotiation.Exception("GP packet info is not correct"); - } - } - } - else - { - // todo - // some game will not send GP packet to natneg server, currently do not know the reason of it, need more game for analysis. - // this will happen in GameClient - if (!(AddressInfos.ContainsKey(NatPortType.NN1) - && AddressInfos.ContainsKey(NatPortType.NN2) - && AddressInfos.ContainsKey(NatPortType.NN3))) - { - throw new NatNegotiation.Exception("Incomplete init packets"); - } - - if (AddressInfos[NatPortType.NN1].Cookie != AddressInfos[NatPortType.NN2].Cookie - || AddressInfos[NatPortType.NN1].Cookie != AddressInfos[NatPortType.NN3].Cookie) - { - throw new NatNegotiation.Exception("Broken cookie"); - } - if (AddressInfos[NatPortType.NN1].Version != AddressInfos[NatPortType.NN2].Version - || AddressInfos[NatPortType.NN1].Version != AddressInfos[NatPortType.NN3].Version) - { - throw new NatNegotiation.Exception("Broken version"); - } - - if (AddressInfos[NatPortType.NN1].ClientIndex != AddressInfos[NatPortType.NN2].ClientIndex - || AddressInfos[NatPortType.NN1].ClientIndex != AddressInfos[NatPortType.NN3].ClientIndex) - { - throw new NatNegotiation.Exception("Broken client index"); - } - if (AddressInfos[NatPortType.NN1].UseGamePort != AddressInfos[NatPortType.NN2].UseGamePort - || AddressInfos[NatPortType.NN1].UseGamePort != AddressInfos[NatPortType.NN3].UseGamePort) - { - throw new NatNegotiation.Exception("Broken use game port"); - } - if (!AddressInfos[NatPortType.NN2].PrivateIPEndPoint.Equals(AddressInfos[NatPortType.NN3].PrivateIPEndPoint)) - { - throw new NatNegotiation.Exception("Client is sending wrong initpacket."); - } - if (AddressInfos.ContainsKey(NatPortType.GP)) - { - if (AddressInfos[NatPortType.GP].Cookie != AddressInfos[NatPortType.NN1].Cookie || - AddressInfos[NatPortType.GP].Version != AddressInfos[NatPortType.NN1].Version || - AddressInfos[NatPortType.GP].ClientIndex != AddressInfos[NatPortType.NN1].ClientIndex || - AddressInfos[NatPortType.GP].UseGamePort != AddressInfos[NatPortType.NN1].UseGamePort) - { - throw new NatNegotiation.Exception("GP packet info is not correct"); - } - } - } - } - } - - public class RedisClient : UniSpy.Server.Core.Abstraction.BaseClass.RedisClient - { - public RedisClient() - { - } - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Aggregate/Redis/NatFailInfo.cs b/src/Servers/NatNegotiation/src/Aggregate/Redis/NatFailInfo.cs deleted file mode 100644 index 072ce030a..000000000 --- a/src/Servers/NatNegotiation/src/Aggregate/Redis/NatFailInfo.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.Net; -using Newtonsoft.Json; -using UniSpy.LinqToRedis; -using UniSpy.Server.Core.Config; -using UniSpy.Server.Core.Extension.Redis; -using UniSpy.Server.Core.Misc; -using UniSpy.Server.NatNegotiation.Enumerate; - -namespace UniSpy.Server.NatNegotiation.Aggregate.Redis.Fail -{ - /// - /// The information pair using to switch strategy - /// - /// - public record NatFailInfo : UniSpy.Server.Core.Abstraction.BaseClass.RedisKeyValueObject - { - [RedisKey] - [JsonConverter(typeof(IPAddresConverter))] - public IPAddress PublicIPAddress1 { get; init; } - [RedisKey] - [JsonConverter(typeof(IPAddresConverter))] - public IPAddress PublicIPAddress2 { get; init; } - public NatFailInfo() : base(RedisDbNumber.NatFailInfo, TimeSpan.FromDays(1)) { } - public NatFailInfo(NatInitInfo info1, NatInitInfo info2) : base(RedisDbNumber.NatFailInfo, TimeSpan.FromDays(1)) - { - // we need to store in sequence to make consistancy and reduce duplications - if (info1.ClientIndex == NatClientIndex.GameClient) - { - PublicIPAddress1 = info1.PublicIPEndPoint.Address; - PublicIPAddress2 = info2.PublicIPEndPoint.Address; - } - else - { - PublicIPAddress1 = info2.PublicIPEndPoint.Address; - PublicIPAddress2 = info1.PublicIPEndPoint.Address; - } - } - } - - public class RedisClient : UniSpy.Server.Core.Abstraction.BaseClass.RedisClient - { - public RedisClient() { } - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Application/Client.cs b/src/Servers/NatNegotiation/src/Application/Client.cs deleted file mode 100644 index 6a69047c3..000000000 --- a/src/Servers/NatNegotiation/src/Application/Client.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using UniSpy.Server.NatNegotiation.Handler; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Extension; - -namespace UniSpy.Server.NatNegotiation.Application -{ - public class Client : ClientBase - { - public new ClientInfo Info { get => (ClientInfo)base.Info; private set => base.Info = value; } - public new IUdpConnection Connection => (IUdpConnection)base.Connection; - public Client(IConnection connection, IServer server) : base(connection, server) - { - Info = new ClientInfo(); - IsLogRaw = true; - } - protected override ISwitcher CreateSwitcher(object buffer) => new CmdSwitcher(this, (byte[])buffer); - protected override void EventBinding() - { - ((IUdpConnection)Connection).OnReceive += OnReceived; - _timer = new EasyTimer(TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(1), CheckExpiredClient); - } - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Application/ClientInfo.cs b/src/Servers/NatNegotiation/src/Application/ClientInfo.cs deleted file mode 100644 index 593fae0b9..000000000 --- a/src/Servers/NatNegotiation/src/Application/ClientInfo.cs +++ /dev/null @@ -1,15 +0,0 @@ -using UniSpy.Server.NatNegotiation.Enumerate; -using UniSpy.Server.Core.Abstraction.BaseClass; - -namespace UniSpy.Server.NatNegotiation.Application -{ - public sealed class ClientInfo : ClientInfoBase - { - public uint? Cookie { get; set; } - public NatClientIndex? ClientIndex { get; set; } - public bool IsNeigotiating { get; set; } - public ClientInfo() : base() - { - } - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Application/Program.cs b/src/Servers/NatNegotiation/src/Application/Program.cs deleted file mode 100755 index ec22fc835..000000000 --- a/src/Servers/NatNegotiation/src/Application/Program.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using UniSpy.Server.Core.Logging; - -namespace UniSpy.Server.NatNegotiation.Application -{ - public class Program - { - static void Main(string[] args) - { - try - { - new ServerLauncher().Start(); - Console.WriteLine("Press < Q > to exit. "); - while (Console.ReadKey().Key != ConsoleKey.Q) { } - } - catch (System.Exception e) - { - LogWriter.LogError(e); - } - } - } -} diff --git a/src/Servers/NatNegotiation/src/Application/Server.cs b/src/Servers/NatNegotiation/src/Application/Server.cs deleted file mode 100644 index 09908841d..000000000 --- a/src/Servers/NatNegotiation/src/Application/Server.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Net; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Network.Udp.Server; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.NatNegotiation.Application -{ - public sealed class Server : ServerBase - { - static Server() - { - _name = "NatNegotiation"; - } - - public Server() { } - - public Server(IConnectionManager manager) : base(manager) { } - - protected override IClient CreateClient(IConnection connection) => new Client(connection, this); - - protected override IConnectionManager CreateConnectionManager(IPEndPoint endPoint) => new UdpConnectionManager(endPoint); - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Application/ServerLauncher.cs b/src/Servers/NatNegotiation/src/Application/ServerLauncher.cs deleted file mode 100644 index 62a055b2e..000000000 --- a/src/Servers/NatNegotiation/src/Application/ServerLauncher.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Core.Abstraction.BaseClass.Factory; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.NatNegotiation.Application -{ - public sealed class ServerLauncher : ServerLauncherBase - { - protected override List LaunchNetworkService() => new List { new Server() }; - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Application/StorageOperation.cs b/src/Servers/NatNegotiation/src/Application/StorageOperation.cs deleted file mode 100644 index c37b21f60..000000000 --- a/src/Servers/NatNegotiation/src/Application/StorageOperation.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using UniSpy.Server.NatNegotiation.Abstraction.Interface; -using UniSpy.Server.NatNegotiation.Aggregate.Redis; - -namespace UniSpy.Server.NatNegotiation.Application -{ - internal sealed class StorageOperation : IStorageOperation - { - /// - /// natneg init information redis server. - /// - private static RedisClient _redisClient = new RedisClient(); - private static NatNegotiation.Aggregate.Redis.Fail.RedisClient _natFailRedisClient = new NatNegotiation.Aggregate.Redis.Fail.RedisClient(); - public static IStorageOperation Persistance = new StorageOperation(); - public int CountInitInfo(uint cookie, byte version) - { - return _redisClient.Context.Count(k => - k.Cookie == cookie - && k.Version == version); - } - - public List GetInitInfos(Guid serverId, uint cookie) - { - return _redisClient.Context.Where(k => - k.ServerID == serverId - && k.Cookie == cookie).ToList(); - } - - public void UpdateInitInfo(NatAddressInfo info) - { - _ = _redisClient.SetValueAsync(info); - } - - public void RemoveInitInfo(NatAddressInfo info) - { - _redisClient.DeleteKeyValue(info); - } - - public void UpdateNatFailInfo(Aggregate.Redis.Fail.NatFailInfo info) - { - _ = _natFailRedisClient.SetValueAsync(info); - } - - public int GetNatFailInfo(Aggregate.Redis.Fail.NatFailInfo info) - { - return _natFailRedisClient.Context.Where(i => i.PublicIPAddress1.Equals(info.PublicIPAddress1) && i.PublicIPAddress2.Equals(info.PublicIPAddress2)).Count(); - } - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Contract/Request/AddressCheckRequest.cs b/src/Servers/NatNegotiation/src/Contract/Request/AddressCheckRequest.cs deleted file mode 100755 index 38201f888..000000000 --- a/src/Servers/NatNegotiation/src/Contract/Request/AddressCheckRequest.cs +++ /dev/null @@ -1,13 +0,0 @@ - -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; - -namespace UniSpy.Server.NatNegotiation.Contract.Request -{ - - public sealed class AddressCheckRequest : CommonRequestBase - { - public AddressCheckRequest(byte[] rawRequest) : base(rawRequest) - { - } - } -} diff --git a/src/Servers/NatNegotiation/src/Contract/Request/ConnectAckRequest.cs b/src/Servers/NatNegotiation/src/Contract/Request/ConnectAckRequest.cs deleted file mode 100644 index c5bb9b939..000000000 --- a/src/Servers/NatNegotiation/src/Contract/Request/ConnectAckRequest.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; -using UniSpy.Server.NatNegotiation.Enumerate; - -namespace UniSpy.Server.NatNegotiation.Contract.Request -{ - - public sealed class ConnectAckRequest : RequestBase - { - public NatClientIndex ClientIndex { get; private set; } - public ConnectAckRequest(byte[] rawRequest) : base(rawRequest) - { - } - public override void Parse() - { - base.Parse(); - ClientIndex = (NatClientIndex)RawRequest[13]; - } - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Contract/Request/ConnectRequest.cs b/src/Servers/NatNegotiation/src/Contract/Request/ConnectRequest.cs deleted file mode 100755 index d7435fad0..000000000 --- a/src/Servers/NatNegotiation/src/Contract/Request/ConnectRequest.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; -using UniSpy.Server.NatNegotiation.Enumerate; -namespace UniSpy.Server.NatNegotiation.Contract.Request -{ - - public sealed class ConnectRequest : RequestBase - { - public new byte Version { get => base.Version; init => base.Version = value; } - public new uint Cookie { get => base.Cookie; init => base.Cookie = value; } - public NatClientIndex ClientIndex { get; init; } - public ConnectRequest() { } - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Contract/Request/ErtAckRequest.cs b/src/Servers/NatNegotiation/src/Contract/Request/ErtAckRequest.cs deleted file mode 100755 index 68eca6ee4..000000000 --- a/src/Servers/NatNegotiation/src/Contract/Request/ErtAckRequest.cs +++ /dev/null @@ -1,13 +0,0 @@ - -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; - -namespace UniSpy.Server.NatNegotiation.Contract.Request -{ - - public sealed class ErtAckRequest : CommonRequestBase - { - public ErtAckRequest(byte[] rawRequest) : base(rawRequest) - { - } - } -} diff --git a/src/Servers/NatNegotiation/src/Contract/Request/InitRequest.cs b/src/Servers/NatNegotiation/src/Contract/Request/InitRequest.cs deleted file mode 100755 index 203d9ce17..000000000 --- a/src/Servers/NatNegotiation/src/Contract/Request/InitRequest.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Linq; -using System.Net; -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; -using UniSpy.Server.Core.Encryption; -using UniSpy.Server.Core.Misc; - -namespace UniSpy.Server.NatNegotiation.Contract.Request -{ - - public sealed class InitRequest : CommonRequestBase - { - public string GameName { get; private set; } - /// - /// GamePort (GP) private ip address and port, using for NAT negotiation - /// - [Newtonsoft.Json.JsonConverter(typeof(IPEndPointConverter))] - public IPEndPoint PrivateIPEndPoint { get; private set; } - public InitRequest(byte[] rawRequest) : base(rawRequest) - { - } - public override void Parse() - { - base.Parse(); - var ipBytes = RawRequest.Skip(15).Take(4).ToArray(); - var portBytes = RawRequest.Skip(19).Take(2).Reverse().ToArray(); - // we found that the local port is not correct in gamespy and wireshark - ushort port; - - port = (ushort)BitConverter.ToUInt16(portBytes); - PrivateIPEndPoint = new IPEndPoint(new IPAddress(ipBytes), port); - if (RawRequest.Length > 21) - { - if (RawRequest[RawRequest.Length - 1] == 0) - { - var gameNameBytes = RawRequest.Skip(21).Take(RawRequest.Length - 22).ToArray(); - GameName = UniSpyEncoding.GetString(gameNameBytes); - } - } - } - } -} diff --git a/src/Servers/NatNegotiation/src/Contract/Request/NatifyRequest.cs b/src/Servers/NatNegotiation/src/Contract/Request/NatifyRequest.cs deleted file mode 100755 index 09980102c..000000000 --- a/src/Servers/NatNegotiation/src/Contract/Request/NatifyRequest.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; - -namespace UniSpy.Server.NatNegotiation.Contract.Request -{ - - public sealed class NatifyRequest : CommonRequestBase - { - public NatifyRequest(byte[] rawRequest) : base(rawRequest) - { - } - } -} diff --git a/src/Servers/NatNegotiation/src/Contract/Request/PingRequest.cs b/src/Servers/NatNegotiation/src/Contract/Request/PingRequest.cs deleted file mode 100644 index 31dea4953..000000000 --- a/src/Servers/NatNegotiation/src/Contract/Request/PingRequest.cs +++ /dev/null @@ -1,32 +0,0 @@ -// using System; -// using System.Linq; -// using System.Net; -// using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; -// -// using UniSpy.Server.NatNegotiation.Enumerate; - -// namespace UniSpy.Server.NatNegotiation.Contract.Request -// { -// /// -// /// When client can not start p2p game, it will use our server to redirect his game traffic -// /// -// -// public sealed class PingRequest : CommonRequestBase -// { -// public IPEndPoint GuessedTargetIPEndPoint { get; set; } -// public byte? GotYourData { get; private set; } -// public byte? IsFinished { get; private set; } -// public PingRequest(byte[] rawRequest) : base(rawRequest) -// { -// } -// public override void Parse() -// { -// base.Parse(); -// var _ipBytes = RawRequest.Skip(12).Take(4).ToArray(); -// var _portBytes = RawRequest.Skip(16).Take(2).ToArray(); -// GuessedTargetIPEndPoint = new IPEndPoint(new IPAddress(_ipBytes), BitConverter.ToUInt16(_portBytes)); -// GotYourData = RawRequest[18]; -// IsFinished = RawRequest[19]; -// } -// } -// } \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Contract/Request/PreInitRequest.cs b/src/Servers/NatNegotiation/src/Contract/Request/PreInitRequest.cs deleted file mode 100755 index 7bf8495ae..000000000 --- a/src/Servers/NatNegotiation/src/Contract/Request/PreInitRequest.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Linq; -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; -using UniSpy.Server.NatNegotiation.Enumerate; - -namespace UniSpy.Server.NatNegotiation.Contract.Request -{ - - public sealed class PreInitRequest : RequestBase - { - public PreInitState? State { get; private set; } - public uint? TargetCookie { get; private set; } - public PreInitRequest(byte[] rawRequest) : base(rawRequest) - { - } - public override void Parse() - { - base.Parse(); - State = (PreInitState)RawRequest[12]; - TargetCookie = BitConverter.ToUInt32(RawRequest.Skip(13).Take(4).ToArray()); - } - } -} diff --git a/src/Servers/NatNegotiation/src/Contract/Request/ReportRequest.cs b/src/Servers/NatNegotiation/src/Contract/Request/ReportRequest.cs deleted file mode 100755 index 782fc76d1..000000000 --- a/src/Servers/NatNegotiation/src/Contract/Request/ReportRequest.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -using System.Linq; -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; -using UniSpy.Server.NatNegotiation.Enumerate; -using UniSpy.Server.Core.Encryption; - -namespace UniSpy.Server.NatNegotiation.Contract.Request -{ - - public sealed class ReportRequest : CommonRequestBase - { - public bool? IsNatSuccess { get; private set; } - public new RequestType CommandName { get => (RequestType)base.CommandName; set => base.CommandName = value; } - public string GameName { get; private set; } - public NatType NatType { get; private set; } - public NatPortMappingScheme? MappingScheme { get; private set; } - public ReportRequest(byte[] rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - // base.Parse(); - if (RawRequest.Length < 12) - { - return; - } - Version = RawRequest[6]; - CommandName = (RequestType)RawRequest[7]; - Cookie = BitConverter.ToUInt32(RawRequest.Skip(8).Take(4).ToArray()); - // port type is set 204 by gamespy - PortType = (NatPortType)RawRequest[12]; - - ClientIndex = (NatClientIndex)RawRequest[13]; - if (RawRequest[14] == 0) - { - IsNatSuccess = false; - } - else - { - IsNatSuccess = true; - } - NatType = (NatType)RawRequest[15]; - MappingScheme = (NatPortMappingScheme)RawRequest[17]; - // initpacket is 23 long, so there are 0x00 before gamename, we need to skip it - var endIndex = Array.FindIndex(RawRequest.Skip(23).ToArray(), 1, k => k == 0); - GameName = UniSpyEncoding.GetString(RawRequest.Skip(23).Take(endIndex).ToArray()); - } - } -} diff --git a/src/Servers/NatNegotiation/src/Contract/Response/ConnectResponse.cs b/src/Servers/NatNegotiation/src/Contract/Response/ConnectResponse.cs deleted file mode 100755 index 278776c59..000000000 --- a/src/Servers/NatNegotiation/src/Contract/Response/ConnectResponse.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; -using UniSpy.Server.NatNegotiation.Contract.Request; -using UniSpy.Server.NatNegotiation.Contract.Result; - -namespace UniSpy.Server.NatNegotiation.Contract.Response -{ - public sealed class ConnectResponse : ResponseBase - { - private new ConnectRequest _request => (ConnectRequest)base._request; - private new ConnectResult _result => (ConnectResult)base._result; - public ConnectResponse(ConnectRequest request, ConnectResult result) : base(request, result) - { - } - public override void Build() - { - base.Build(); - List data = new List(); - data.AddRange(SendingBuffer); - data.AddRange(_result.RemoteIPAddressBytes); - data.AddRange(_result.RemotePortBytes); - data.Add((byte)_result.GotYourData); - data.Add((byte)_result.Finished); - SendingBuffer = data.ToArray(); - } - } -} diff --git a/src/Servers/NatNegotiation/src/Contract/Response/InitResponse.cs b/src/Servers/NatNegotiation/src/Contract/Response/InitResponse.cs deleted file mode 100755 index 3b61ae8fb..000000000 --- a/src/Servers/NatNegotiation/src/Contract/Response/InitResponse.cs +++ /dev/null @@ -1,11 +0,0 @@ -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; - -namespace UniSpy.Server.NatNegotiation.Contract.Response -{ - public sealed class InitResponse : CommonResponseBase - { - public InitResponse(RequestBase request, ResultBase result) : base(request, result) - { - } - } -} diff --git a/src/Servers/NatNegotiation/src/Contract/Response/PreInitResponse.cs b/src/Servers/NatNegotiation/src/Contract/Response/PreInitResponse.cs deleted file mode 100644 index 17ef349dd..000000000 --- a/src/Servers/NatNegotiation/src/Contract/Response/PreInitResponse.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; -using UniSpy.Server.NatNegotiation.Contract.Request; -using UniSpy.Server.NatNegotiation.Contract.Result; - -namespace UniSpy.Server.NatNegotiation.Contract.Response -{ - public sealed class PreInitResponse : CommonResponseBase - { - private new PreInitRequest _request => (PreInitRequest)base._request; - private new PreInitResult _result => (PreInitResult)base._result; - public PreInitResponse(PreInitRequest request, PreInitResult result) : base(request, result) - { - } - public override void Build() - { - base.Build(); - } - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Contract/Response/ReportResponse.cs b/src/Servers/NatNegotiation/src/Contract/Response/ReportResponse.cs deleted file mode 100755 index c831a7f7f..000000000 --- a/src/Servers/NatNegotiation/src/Contract/Response/ReportResponse.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; -using UniSpy.Server.NatNegotiation.Contract.Request; -using UniSpy.Server.NatNegotiation.Contract.Result; - -namespace UniSpy.Server.NatNegotiation.Contract.Response -{ - public sealed class ReportResponse : ResponseBase - { - private new ReportRequest _request => (ReportRequest)base._request; - private new ReportResult _result => (ReportResult)base._result; - public ReportResponse(ReportRequest request, ResultBase result) : base(request, result) - { - } - public override void Build() - { - base.Build(); - var data = new List(); - data.AddRange(SendingBuffer); - // at least 9 bytes more - // the rest bytes did not read by natneg client, but you have to make total bytes length > 21 to pass initpacket check - data.AddRange(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }); - SendingBuffer = data.ToArray(); - } - } -} diff --git a/src/Servers/NatNegotiation/src/Contract/Result/AddressCheckResult.cs b/src/Servers/NatNegotiation/src/Contract/Result/AddressCheckResult.cs deleted file mode 100755 index 03cb404b1..000000000 --- a/src/Servers/NatNegotiation/src/Contract/Result/AddressCheckResult.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; -using UniSpy.Server.NatNegotiation.Enumerate; - -namespace UniSpy.Server.NatNegotiation.Contract.Result -{ - public sealed class AddressCheckResult : CommonResultBase - { - public AddressCheckResult() - { - PacketType = ResponseType.AddressReply; - } - } -} diff --git a/src/Servers/NatNegotiation/src/Contract/Result/ConnectResult.cs b/src/Servers/NatNegotiation/src/Contract/Result/ConnectResult.cs deleted file mode 100755 index f53615392..000000000 --- a/src/Servers/NatNegotiation/src/Contract/Result/ConnectResult.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Linq; -using System.Net; -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; -using UniSpy.Server.NatNegotiation.Enumerate; - -namespace UniSpy.Server.NatNegotiation.Contract.Result -{ - public class ConnectResult : ResultBase - { - public byte? GotYourData { get; private set; } - public ConnectPacketStatus? Finished { get; private set; } - public IPEndPoint RemoteEndPoint { get; set; } - public byte[] RemoteIPAddressBytes => RemoteEndPoint.Address.GetAddressBytes(); - public byte[] RemotePortBytes => BitConverter.GetBytes((ushort)RemoteEndPoint.Port).Reverse().ToArray(); - public byte Version; - public int Cookie; - public ConnectResult() - { - PacketType = ResponseType.Connect; - GotYourData = 1; - Finished = ConnectPacketStatus.NoError; - } - } -} diff --git a/src/Servers/NatNegotiation/src/Contract/Result/ErtAckResult.cs b/src/Servers/NatNegotiation/src/Contract/Result/ErtAckResult.cs deleted file mode 100755 index 3007a85d3..000000000 --- a/src/Servers/NatNegotiation/src/Contract/Result/ErtAckResult.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; -using UniSpy.Server.NatNegotiation.Enumerate; - -namespace UniSpy.Server.NatNegotiation.Contract.Result -{ - public sealed class ErtAckResult : CommonResultBase - { - public ErtAckResult() - { - PacketType = ResponseType.ErtAck; - } - } -} diff --git a/src/Servers/NatNegotiation/src/Contract/Result/InitResult.cs b/src/Servers/NatNegotiation/src/Contract/Result/InitResult.cs deleted file mode 100755 index 62716e1e0..000000000 --- a/src/Servers/NatNegotiation/src/Contract/Result/InitResult.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; -using UniSpy.Server.NatNegotiation.Enumerate; - -namespace UniSpy.Server.NatNegotiation.Contract.Result -{ - public sealed class InitResult : CommonResultBase - { - public InitResult() - { - PacketType = ResponseType.InitAck; - } - } -} diff --git a/src/Servers/NatNegotiation/src/Contract/Result/NatifyResult.cs b/src/Servers/NatNegotiation/src/Contract/Result/NatifyResult.cs deleted file mode 100755 index bcb57ee7d..000000000 --- a/src/Servers/NatNegotiation/src/Contract/Result/NatifyResult.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; -using UniSpy.Server.NatNegotiation.Enumerate; - -namespace UniSpy.Server.NatNegotiation.Contract.Result -{ - public sealed class NatifyResult : CommonResultBase - { - public NatifyResult() - { - PacketType = ResponseType.ErtTest; - } - } -} diff --git a/src/Servers/NatNegotiation/src/Contract/Result/PreInitResult.cs b/src/Servers/NatNegotiation/src/Contract/Result/PreInitResult.cs deleted file mode 100644 index b21afa892..000000000 --- a/src/Servers/NatNegotiation/src/Contract/Result/PreInitResult.cs +++ /dev/null @@ -1,17 +0,0 @@ -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; -using UniSpy.Server.NatNegotiation.Enumerate; - -namespace UniSpy.Server.NatNegotiation.Contract.Result -{ - public sealed class PreInitResult : ResultBase - { - public int ClientIndex { get; private set; } - public PreInitState State { get; private set; } - public int ClientID { get; private set; } - public PreInitResult() - { - PacketType = ResponseType.PreInitAck; - State = PreInitState.Ready; - } - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Contract/Result/ReportResult.cs b/src/Servers/NatNegotiation/src/Contract/Result/ReportResult.cs deleted file mode 100755 index 9093d2efb..000000000 --- a/src/Servers/NatNegotiation/src/Contract/Result/ReportResult.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; -using UniSpy.Server.NatNegotiation.Enumerate; - -namespace UniSpy.Server.NatNegotiation.Contract.Result -{ - public sealed class ReportResult : ResultBase - { - public ReportResult() - { - PacketType = ResponseType.ReportAck; - } - } -} diff --git a/src/Servers/NatNegotiation/src/Dockerfile b/src/Servers/NatNegotiation/src/Dockerfile deleted file mode 100755 index ac4039932..000000000 --- a/src/Servers/NatNegotiation/src/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base -WORKDIR /app -EXPOSE 27901/udp - -FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build -WORKDIR /src -COPY ["src/Servers/NatNegotiation/src/UniSpy.Server.NatNegotiation.csproj", "src/Servers/NatNegotiation/src/"] -COPY ["src/Libraries/Core/src/UniSpy.Server.Core.csproj", "src/Libraries/Core/src/"] -RUN dotnet restore "src/Servers/NatNegotiation/src/UniSpy.Server.NatNegotiation.csproj" -COPY . . -WORKDIR "/src/src/Servers/NatNegotiation/src" -RUN dotnet build "UniSpy.Server.NatNegotiation.csproj" -c Release -o /app/build - -FROM build AS publish -RUN dotnet publish "UniSpy.Server.NatNegotiation.csproj" -c Release -o /app/publish - -FROM base AS final -WORKDIR /app -COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "UniSpy.Server.NatNegotiation.dll"] \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Enumerate/ConnectPacketStatus.cs b/src/Servers/NatNegotiation/src/Enumerate/ConnectPacketStatus.cs deleted file mode 100644 index b75d94f5b..000000000 --- a/src/Servers/NatNegotiation/src/Enumerate/ConnectPacketStatus.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace UniSpy.Server.NatNegotiation.Enumerate -{ - public enum ConnectPacketStatus : byte - { - NoError, - DeadHeartBeat, - InitPacketTimeOut - } -} diff --git a/src/Servers/NatNegotiation/src/Enumerate/NatMappingType.cs b/src/Servers/NatNegotiation/src/Enumerate/NatMappingType.cs deleted file mode 100644 index 92c0f72b4..000000000 --- a/src/Servers/NatNegotiation/src/Enumerate/NatMappingType.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace UniSpy.Server.NatNegotiation.Enumerate -{ - public enum NatType : byte - { - NoNat, - FirewallOnly, - /// - /// C发数据到210.21.12.140:8000,NAT会将数据包送到A(192.168.0.4:5000)。因为NAT上已经有了192.168.0.4:5000到210.21.12.140:8000的映射 - /// - FullCone, - /// - /// C无法和A通信,因为A从来没有和C通信过,NAT将拒绝C试图与A连接的动作。但B可以通过210.21.12.140:8000与A的 192.168.0.4:5000通信,且这里B可以使用任何端口与A通信。如:210.15.27.166:2001 -> 210.21.12.140:8000,NAT会送到A的5000端口上 - /// - AddressRestrictedCone, - /// - /// C无法与A通信,因为A从来没有和C通信过。而B也只能用它的210.15.27.166:2000与A的192.168.0.4:5000通信,因为A也从来没有和B的其他端口通信过。该类型NAT是端口受限的。 - /// - PortRestrictedCone, - /// - /// 上面3种类型,统称为Cone NAT,有一个共同点:只要是从同一个内部地址和端口出来的包,NAT都将它转换成同一个外部地址和端口。但是Symmetric有点不同,具体表现在: 只要是从同一个内部地址和端口出来,且到同一个外部目标地址和端口,则NAT也都将它转换成同一个外部地址和端口。但如果从同一个内部地址和端口出来,是 到另一个外部目标地址和端口,则NAT将使用不同的映射,转换成不同的端口(外部地址只有一个,故不变)。而且和Port Restricted Cone一样,只有曾经收到过内部地址发来包的外部地址,才能通过NAT映射后的地址向该内部地址发包。 - /// - Symmetric, - Unknown - } - public enum NatPortMappingScheme : byte - { - Unrecognized, - PrivateAsPublic, - ConsistentPort, - Incremental, - Mixed, - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Enumerate/NatNegResult.cs b/src/Servers/NatNegotiation/src/Enumerate/NatNegResult.cs deleted file mode 100644 index 265206309..000000000 --- a/src/Servers/NatNegotiation/src/Enumerate/NatNegResult.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace UniSpy.Server.NatNegotiation.Enumerate -{ - public enum NatNegResult - { - Success, - DeadBeatPartner, - InitTimeOut, - PingTimeOut, - UnknownError, - NoResult - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Enumerate/NatPacketType.cs b/src/Servers/NatNegotiation/src/Enumerate/NatPacketType.cs deleted file mode 100644 index d1ee76d96..000000000 --- a/src/Servers/NatNegotiation/src/Enumerate/NatPacketType.cs +++ /dev/null @@ -1,34 +0,0 @@ - -namespace UniSpy.Server.NatNegotiation.Enumerate -{ - public enum RequestType : byte - { - /// - /// Initialize nat negotiation with cookie - /// - Init = 0, - ErtAck = 3, - Connect = 5, - ConnectAck = 6, - Ping = 7, - AddressCheck = 10, - NatifyRequest = 12, - Report = 13, - PreInit = 15 - } - public enum ResponseType : byte - { - InitAck = 1, - ErtTest = 2, - ErtAck = 3, - Connect = 5, - AddressReply = 11, - ReportAck = 14, - PreInitAck = 16 - } - public enum NatClientIndex : byte - { - GameClient = 0, - GameServer = 1 - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Enumerate/NatPortType.cs b/src/Servers/NatNegotiation/src/Enumerate/NatPortType.cs deleted file mode 100644 index 456969b1d..000000000 --- a/src/Servers/NatNegotiation/src/Enumerate/NatPortType.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace UniSpy.Server.NatNegotiation.Enumerate -{ - public enum NatPortType : byte - { - /// - /// Use game port for nat neg - /// - GP, - /// - /// IP and Port both restricted - /// - NN1, - /// - /// IP not restricted - /// - NN2, - /// - /// Port not restriced - /// - NN3 - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Enumerate/NatPunchStrategy.cs b/src/Servers/NatNegotiation/src/Enumerate/NatPunchStrategy.cs deleted file mode 100644 index 4ee85fd36..000000000 --- a/src/Servers/NatNegotiation/src/Enumerate/NatPunchStrategy.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace UniSpy.Server.NatNegotiation.Enumerate -{ - - public enum NatPunchStrategy - { - /// - /// If 2 clients are guessed in same LAN and natneg fail we use public ip to negotiate - /// - UsingPublicIPEndPoint, - /// - /// If 2 clients are probabaly in same LAN, we use private ip to negotiate - /// - UsingPrivateIPEndpoint, - /// - /// If 2 clients are failed with public ip negotation, we use game relay service to redirect the game traffic - /// - UsingGameRelay - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Enumerate/NatStrategyType.cs b/src/Servers/NatNegotiation/src/Enumerate/NatStrategyType.cs deleted file mode 100644 index b3e3b154e..000000000 --- a/src/Servers/NatNegotiation/src/Enumerate/NatStrategyType.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace UniSpy.Server.NatNegotiation.Enumerate -{ - public enum NatStrategyType - { - UsePublicIP, - /// - /// currently we disable it - /// - UsePrivateIP, - UseGameTrafficRelay - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Enumerate/NatifyPacketType.cs b/src/Servers/NatNegotiation/src/Enumerate/NatifyPacketType.cs deleted file mode 100644 index af58b97ca..000000000 --- a/src/Servers/NatNegotiation/src/Enumerate/NatifyPacketType.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace UniSpy.Server.NatNegotiation.Enumerate -{ - public enum NatifyPacketType : byte - { - PacketMap1a, - PacketMap2, - PacketMap3, - PacketMap1b, - NumPackets - } - - public enum PreInitState : byte - { - WaitingForClient = 0, - WaitingForMatchUp = 1, - Ready = 2 - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Exception/NNException.cs b/src/Servers/NatNegotiation/src/Exception/NNException.cs deleted file mode 100755 index 6842a3b3c..000000000 --- a/src/Servers/NatNegotiation/src/Exception/NNException.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace UniSpy.Server.NatNegotiation -{ - public class Exception : UniSpy.Exception - { - public Exception() - { - } - - public Exception(string message) : base(message) - { - } - - public Exception(string message, System.Exception innerException) : base(message, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Handler/CmdHandler/AddressCheckHandler.cs b/src/Servers/NatNegotiation/src/Handler/CmdHandler/AddressCheckHandler.cs deleted file mode 100755 index 86fd0e038..000000000 --- a/src/Servers/NatNegotiation/src/Handler/CmdHandler/AddressCheckHandler.cs +++ /dev/null @@ -1,112 +0,0 @@ -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; -using UniSpy.Server.NatNegotiation.Enumerate; -using UniSpy.Server.NatNegotiation.Aggregate.Misc; -using UniSpy.Server.NatNegotiation.Aggregate.Redis; -using UniSpy.Server.NatNegotiation.Contract.Request; -using UniSpy.Server.NatNegotiation.Contract.Response; -using UniSpy.Server.NatNegotiation.Contract.Result; -using UniSpy.Server.NatNegotiation.Application; - -namespace UniSpy.Server.NatNegotiation.Handler.CmdHandler -{ - public sealed class AddressCheckHandler : CmdHandlerBase - { - private new AddressCheckRequest _request => (AddressCheckRequest)base._request; - private new AddressCheckResult _result { get => (AddressCheckResult)base._result; set => base._result = value; } - public AddressCheckHandler(Client client, AddressCheckRequest request) : base(client, request) - { - _result = new AddressCheckResult(); - } - protected override void DataOperation() - { - _result.RemoteIPEndPoint = _client.Connection.RemoteIPEndPoint; - } - protected override void ResponseConstruct() - { - _response = new InitResponse(_request, _result); - } - public static NatProperty DetermineNatTypeVersion2(NatInitInfo initInfo) - { - NatProperty natProperty = new NatProperty(); - if (initInfo.AddressInfos.Count < 3) - { - throw new NatNegotiation.Exception("We need 3 init records to determine the nat type."); - } - var nn1 = initInfo.AddressInfos[NatPortType.NN1]; - var nn2 = initInfo.AddressInfos[NatPortType.NN2]; - - // no nat - if (nn1.PublicIPEndPoint.Address.Equals(nn1.PrivateIPEndPoint.Address) - && nn2.PublicIPEndPoint.Equals(nn2.PrivateIPEndPoint)) - { - natProperty.NatType = NatType.NoNat; - } - // detect cone - else if (nn1.PublicIPEndPoint.Equals(nn2.PublicIPEndPoint)) - { - natProperty.NatType = NatType.FullCone; - } - else if (!nn1.PublicIPEndPoint.Equals(nn2.PublicIPEndPoint)) - { - natProperty.NatType = NatType.Symmetric; - natProperty.PortMapping = NatPortMappingScheme.Unrecognized; - //todo get all interval of the port increment value - var portIncrement1 = nn2.PublicIPEndPoint.Port - nn1.PublicIPEndPoint.Port; - } - else - { - natProperty.NatType = NatType.Unknown; - } - return natProperty; - } - public static NatProperty DetermineNatTypeVersion3(NatInitInfo initInfo) - { - NatProperty natProperty = new NatProperty(); - if (initInfo.AddressInfos.Count < 3) - { - throw new NatNegotiation.Exception("We need 3 init records to determine the nat type."); - } - var nn1 = initInfo.AddressInfos[NatPortType.NN1]; - var nn2 = initInfo.AddressInfos[NatPortType.NN2]; - var nn3 = initInfo.AddressInfos[NatPortType.NN3]; - - // no nat - if (nn1.PublicIPEndPoint.Address.Equals(nn1.PrivateIPEndPoint.Address) - && nn2.PublicIPEndPoint.Equals(nn2.PrivateIPEndPoint) - && nn3.PublicIPEndPoint.Equals(nn3.PrivateIPEndPoint)) - { - natProperty.NatType = NatType.NoNat; - } - // detect cone - else if (nn1.PublicIPEndPoint.Equals(nn2.PublicIPEndPoint) - && nn2.PublicIPEndPoint.Equals(nn3.PublicIPEndPoint)) - { - natProperty.NatType = NatType.FullCone; - } - else if (!nn1.PublicIPEndPoint.Equals(nn2.PublicIPEndPoint) - || !nn2.PublicIPEndPoint.Equals(nn3.PublicIPEndPoint)) - { - natProperty.NatType = NatType.Symmetric; - natProperty.PortMapping = NatPortMappingScheme.Incremental; - //todo get all interval of the port increment value - var portIncrement1 = nn2.PublicIPEndPoint.Port - nn1.PublicIPEndPoint.Port; - var portIncrement2 = nn3.PublicIPEndPoint.Port - nn2.PublicIPEndPoint.Port; - if (portIncrement1 == portIncrement2) - { - natProperty.PortIncrement = portIncrement1; - } - else - { - var increaseInterval = portIncrement2 - portIncrement1; - natProperty.PortIncrement = portIncrement2 + increaseInterval; - } - } - else - { - natProperty.NatType = NatType.Unknown; - - } - return natProperty; - } - } -} diff --git a/src/Servers/NatNegotiation/src/Handler/CmdHandler/ConnectAckHandler.cs b/src/Servers/NatNegotiation/src/Handler/CmdHandler/ConnectAckHandler.cs deleted file mode 100644 index af77fc0bb..000000000 --- a/src/Servers/NatNegotiation/src/Handler/CmdHandler/ConnectAckHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; -using UniSpy.Server.NatNegotiation.Contract.Request; -using UniSpy.Server.Core.Logging; -using UniSpy.Server.NatNegotiation.Application; - -namespace UniSpy.Server.NatNegotiation.Handler.CmdHandler -{ - /// - /// The connect ack handler indicate that the client is already received the connect packet and start nat negotiation - /// - - public class ConnectAckHandler : CmdHandlerBase - { - private new ConnectAckRequest _request => (ConnectAckRequest)base._request; - public ConnectAckHandler(Client client, ConnectAckRequest request) : base(client, request) - { - } - protected override void DataOperation() - { - _client.LogInfo($"client:{_request.ClientIndex} aknowledged connect request."); - } - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/src/Handler/CmdHandler/ConnectHandler.cs b/src/Servers/NatNegotiation/src/Handler/CmdHandler/ConnectHandler.cs deleted file mode 100755 index 70334a222..000000000 --- a/src/Servers/NatNegotiation/src/Handler/CmdHandler/ConnectHandler.cs +++ /dev/null @@ -1,169 +0,0 @@ -using System.Linq; -using System.Net; -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; -using UniSpy.Server.NatNegotiation.Application; -using UniSpy.Server.NatNegotiation.Enumerate; -using UniSpy.Server.NatNegotiation.Aggregate.Redis; -using UniSpy.Server.NatNegotiation.Contract.Request; -using UniSpy.Server.NatNegotiation.Contract.Response; -using UniSpy.Server.NatNegotiation.Contract.Result; -using UniSpy.Server.GameTrafficRelay; -using RestSharp; -using RestSharp.Serializers.NewtonsoftJson; -using UniSpy.Server.Core.Logging; - -namespace UniSpy.Server.NatNegotiation.Handler.CmdHandler -{ - - public sealed class ConnectHandler : CmdHandlerBase - { - /// - /// Indicate the init is already finished - /// |cooie|isFinished| - /// - // public static Dictionary ConnectStatus; - private new ConnectRequest _request => (ConnectRequest)base._request; - private new ConnectResult _result { get => (ConnectResult)base._result; set => base._result = value; } - private NatInitInfo _othersInitInfo; - private NatInitInfo _myInitInfo; - private IPEndPoint _guessedOthersIPEndPoint; - public ConnectHandler(Client client, ConnectRequest request) : base(client, request) - { - _result = new ConnectResult(); - } - protected override void RequestCheck() - { - // detecting nat - var addressInfos = StorageOperation.Persistance.GetInitInfos(_client.Server.Id, (uint)_client.Info.Cookie); - // if (addressInfos.Count < InitHandler.InitPacketCount) - // { - // throw new NatNegotiation.Exception($"The number of init info in redis with cookie: {_client.Info.Cookie} is not bigger than 7."); - // } - var otherClientIndex = (NatClientIndex)(1 - (int)_request.ClientIndex); - // we need both info to determine nat type - _othersInitInfo = new NatInitInfo(addressInfos.Where(i => i.ClientIndex == otherClientIndex).OrderBy(i => i.PortType).ToList()); - _myInitInfo = new NatInitInfo(addressInfos.Where(i => i.ClientIndex == _request.ClientIndex).OrderBy(i => i.PortType).ToList()); - } - - // NOTE: If GTR is not used and both clients are on the same LAN, we need to use PrivateIPEndPoint. - protected override void DataOperation() - { - var info = new NatNegotiation.Aggregate.Redis.Fail.NatFailInfo(_myInitInfo, _othersInitInfo); - NatStrategyType strategy; - - if (StorageOperation.Persistance.GetNatFailInfo(info) == 0) - { - strategy = DetermineNATStrategy(_myInitInfo, _othersInitInfo); - } - else - { - _client.LogInfo("The public ip is in nat fail record database, we use game traffic relay."); - strategy = NatStrategyType.UseGameTrafficRelay; - } - - switch (strategy) - { - case NatStrategyType.UsePublicIP: - UsingPublicAddressToNegotiate(); - break; - // due to multi NAT situation, we have to check if clients are in same public ip address, and both client are no NAT - // if two clients have one public ip like 202.91.34.188, we set the negotiate address for each other such as - // client1 public ip 202.91.34.188:123, private ip: 192.168.1.100 - // client2 public ip 202.91.34.188:124, private ip: 192.168.1.101 - // there are situations as follows. - // 1. clients are in multi NAT with different router - // 2. clients are in one NAT with same router - // there are solutions as follows. - // 1. we can set public ip as negotiation address, but if situation 1 happen, the router will not transfer data for each clients. - // 2. we can set private IP as negotiation address, but if situation 1 happen, two clients can not receive each information, because they are not in same router. - // 3. we can set private ip as negotiation address, if clients are in one NAT, small possibility - // gamespy sdk need 100% success on nat negotiation, therefore if clients have same public ip and have NAT, to make sure 100% success, we use GameTrafficRelay server. - case NatStrategyType.UsePrivateIP: - // temprary use GTR - UsingPrivateAddressToNegotiate(); - break; - case NatStrategyType.UseGameTrafficRelay: - UsingGameRelayServerToNegotiate(); - break; - } - _client.LogInfo($"My NAT type: {_myInitInfo.NatType}, others NAT type: {_othersInitInfo.NatType} Strategy: {strategy}, Guessing IPEndPoint: {_guessedOthersIPEndPoint}"); - } - - protected override void ResponseConstruct() - { - _response = new ConnectResponse( - _request, - new ConnectResult { RemoteEndPoint = _guessedOthersIPEndPoint }); - } - - private void UsingPublicAddressToNegotiate() - { - _guessedOthersIPEndPoint = _othersInitInfo.PublicIPEndPoint; - } - private void UsingPrivateAddressToNegotiate() - { - _guessedOthersIPEndPoint = _othersInitInfo.PrivateIPEndPoint; - } - private void UsingGameRelayServerToNegotiate() - { - var relayServers = GameTrafficRelay.Application.StorageOperation.Persistance.GetAvaliableRelayServers(); - if (relayServers.Count == 0) - { - throw new NatNegotiation.Exception("No GameRelayServer found, you must start a GameRelayServer!"); - } - //todo the optimized server will be selected - var relayEndPoint = relayServers.OrderBy(x => x.ClientCount).First().PublicIPEndPoint; - var req = new NatNegotiationRequest() - { - Cookie = _myInitInfo.Cookie, - ServerId = _client.Server.Id - }; - var client = new RestClient($"http://{relayEndPoint}/NatNegotiation").UseNewtonsoftJson(); - var request = new RestRequest().AddJsonBody(req); - var resp = client.Post(request); - if (_client.Info.ClientIndex == NatClientIndex.GameClient) - { - _guessedOthersIPEndPoint = resp.IPEndPoint1; - } - else if (_client.Info.ClientIndex == NatClientIndex.GameServer) - { - _guessedOthersIPEndPoint = resp.IPEndPoint2; - } - else - { - throw new NatNegotiation.Exception("The client index is not applied"); - } - } - - public static NatStrategyType DetermineNATStrategy(NatInitInfo info1, NatInitInfo info2) - { - bool IsBothHaveSamePublicIP = info1.PublicIPEndPoint.Address.Equals(info2.PublicIPEndPoint.Address); - // whether first 3 bytes of ip address is same, like 192.168.1.101 and 192.168.1.102 - bool IsBothInSamePrivateIPRange = info1.PrivateIPEndPoint.Address.GetAddressBytes().Take(3) - .SequenceEqual(info2.PrivateIPEndPoint.Address.GetAddressBytes().Take(3)); - if (info1.NatType < NatType.Symmetric && info2.NatType < NatType.Symmetric) - { - if (IsBothHaveSamePublicIP) - { - if (IsBothInSamePrivateIPRange) - { - return NatStrategyType.UsePrivateIP; - - } - else - { - return NatStrategyType.UseGameTrafficRelay; - } - } - else - { - return NatStrategyType.UsePublicIP; - } - } - else - { - return NatStrategyType.UseGameTrafficRelay; - } - } - } -} diff --git a/src/Servers/NatNegotiation/src/Handler/CmdHandler/ErtAckHandler.cs b/src/Servers/NatNegotiation/src/Handler/CmdHandler/ErtAckHandler.cs deleted file mode 100755 index cbc7d2dd5..000000000 --- a/src/Servers/NatNegotiation/src/Handler/CmdHandler/ErtAckHandler.cs +++ /dev/null @@ -1,27 +0,0 @@ -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; -using UniSpy.Server.NatNegotiation.Contract.Request; -using UniSpy.Server.NatNegotiation.Contract.Response; -using UniSpy.Server.NatNegotiation.Contract.Result; -using UniSpy.Server.NatNegotiation.Application; - -namespace UniSpy.Server.NatNegotiation.Handler.CmdHandler -{ - - public sealed class ErtAckHandler : CmdHandlerBase - { - private new ErtAckRequest _request => (ErtAckRequest)base._request; - private new ErtAckResult _result { get => (ErtAckResult)base._result; set => base._result = value; } - public ErtAckHandler(Client client, ErtAckRequest request) : base(client, request) - { - _result = new ErtAckResult(); - } - protected override void DataOperation() - { - _result.RemoteIPEndPoint = _client.Connection.RemoteIPEndPoint; - } - protected override void ResponseConstruct() - { - _response = new InitResponse(_request, _result); - } - } -} diff --git a/src/Servers/NatNegotiation/src/Handler/CmdHandler/InitHandler.cs b/src/Servers/NatNegotiation/src/Handler/CmdHandler/InitHandler.cs deleted file mode 100755 index c753311dd..000000000 --- a/src/Servers/NatNegotiation/src/Handler/CmdHandler/InitHandler.cs +++ /dev/null @@ -1,140 +0,0 @@ -using System.Threading.Tasks; -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; -using UniSpy.Server.NatNegotiation.Application; -using UniSpy.Server.NatNegotiation.Enumerate; -using UniSpy.Server.NatNegotiation.Aggregate.Redis; -using UniSpy.Server.NatNegotiation.Contract.Request; -using UniSpy.Server.NatNegotiation.Contract.Response; -using UniSpy.Server.NatNegotiation.Contract.Result; -using UniSpy.Server.Core.Logging; - -namespace UniSpy.Server.NatNegotiation.Handler.CmdHandler -{ - - public sealed class InitHandler : CmdHandlerBase - { - public static readonly int InitPacketCount = 6; - private new InitRequest _request => (InitRequest)base._request; - private new InitResult _result { get => (InitResult)base._result; set => base._result = value; } - /// - /// Local NatInitInfo storage, after all init packets are received we send all into redis database - /// - private NatAddressInfo _addressInfo; - public InitHandler(Client client, InitRequest request) : base(client, request) - { - _result = new InitResult(); - } - protected override void DataOperation() - { - _addressInfo = new NatAddressInfo() - { - ServerID = _client.Server.Id, - Cookie = (uint)_request.Cookie, - UseGamePort = _request.UseGamePort, - ClientIndex = (NatClientIndex)_request.ClientIndex, - Version = _request.Version, - PortType = _request.PortType, - GameName = _request.GameName, - PublicIPEndPoint = _client.Connection.RemoteIPEndPoint, - PrivateIPEndPoint = _request.PrivateIPEndPoint - }; - _client.LogInfo($"Received init request with private ip: [{_addressInfo.PrivateIPEndPoint}], cookie: {_addressInfo.Cookie}, client index: {_addressInfo.ClientIndex}."); - _result.RemoteIPEndPoint = _client.Connection.RemoteIPEndPoint; - } - protected override void ResponseConstruct() - { - _response = new InitResponse(_request, _result); - } - protected override void Response() - { - base.Response(); - - lock (_client.Info) - { - if (_client.Info.ClientIndex is null) - { - _client.Info.ClientIndex = _request.ClientIndex; - } - if (_client.Info.Cookie is null) - { - _client.Info.Cookie = _request.Cookie; - } - } - - // todo make the code do not block and redis do not have thread theaf problem - // Task.Run(() => StorageOperation.Persistance.UpdateInitInfo(_addressInfo)); - StorageOperation.Persistance.UpdateInitInfo(_addressInfo); - // init packet nn3 is the last one client send, although receiving nn3 does not mean we received other init packets, but we can use this as a flag to prevent start multiple connect handler - if (_request.Version == 2) - { - if (_request.PortType == NatPortType.NN2 && _client.Info.IsNeigotiating == false) - { - _client.Info.IsNeigotiating = true; - PrepareForConnectingAsync(); - } - } - else - { - if (_request.PortType == NatPortType.NN3 && _client.Info.IsNeigotiating == false) - { - _client.Info.IsNeigotiating = true; - PrepareForConnectingAsync(); - } - } - } - - - /// - /// Prepare to send connect response - /// - private async void PrepareForConnectingAsync() - { - _client.LogInfo($"Watting for negotiator's initInfo with cookie:{_request.Cookie}."); - await Task.Delay(2000); - int totalWaitCount = 4; - if (_request.Version == 2) - { - totalWaitCount = 3; - } - - int waitCount = 1; - // we only wait 8 seconds - while (waitCount <= totalWaitCount) - { - var initCount = StorageOperation.Persistance.CountInitInfo(_request.Cookie, _request.Version); - // some client do not send GP init packet, we can only receive 7 packets - if (initCount >= InitPacketCount) - { - _client.LogInfo("2 neigotiators found, start negotiating."); - StartConnecting(); - break; - } - else - { - _client.LogInfo($"No negotiator found with cookie: {_request.Cookie}, retry count: {waitCount}."); - } - waitCount++; - await Task.Delay(2000); - } - // if server can not find the client2 within 8 retry, then we log the error. - if (waitCount > 4) - { - _client.LogWarn($"cookie: {_request.Cookie} have no negotiator found , we clean init information, please connect again."); - } - } - - /// - /// Start connect handler to tell each other's public ip and port - /// - private void StartConnecting() - { - var request = new ConnectRequest - { - Version = _request.Version, - Cookie = _request.Cookie, - ClientIndex = _request.ClientIndex - }; - new ConnectHandler(_client, request).Handle(); - } - } -} diff --git a/src/Servers/NatNegotiation/src/Handler/CmdHandler/NatifyHandler.cs b/src/Servers/NatNegotiation/src/Handler/CmdHandler/NatifyHandler.cs deleted file mode 100755 index 64cf9f423..000000000 --- a/src/Servers/NatNegotiation/src/Handler/CmdHandler/NatifyHandler.cs +++ /dev/null @@ -1,27 +0,0 @@ -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; -using UniSpy.Server.NatNegotiation.Contract.Request; -using UniSpy.Server.NatNegotiation.Contract.Response; -using UniSpy.Server.NatNegotiation.Contract.Result; -using UniSpy.Server.NatNegotiation.Application; - -namespace UniSpy.Server.NatNegotiation.Handler.CmdHandler -{ - - public sealed class NatifyHandler : CmdHandlerBase - { - private new NatifyRequest _request => (NatifyRequest)base._request; - private new NatifyResult _result { get => (NatifyResult)base._result; set => base._result = value; } - public NatifyHandler(Client client, NatifyRequest request) : base(client, request) - { - _result = new NatifyResult(); - } - protected override void DataOperation() - { - _result.RemoteIPEndPoint = _client.Connection.RemoteIPEndPoint; - } - protected override void ResponseConstruct() - { - _response = new InitResponse(_request, _result); - } - } -} diff --git a/src/Servers/NatNegotiation/src/Handler/CmdHandler/ReportHandler.cs b/src/Servers/NatNegotiation/src/Handler/CmdHandler/ReportHandler.cs deleted file mode 100755 index 428536933..000000000 --- a/src/Servers/NatNegotiation/src/Handler/CmdHandler/ReportHandler.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System.Linq; -using UniSpy.Server.NatNegotiation.Abstraction.BaseClass; -using UniSpy.Server.NatNegotiation.Application; -using UniSpy.Server.NatNegotiation.Enumerate; -using UniSpy.Server.NatNegotiation.Aggregate.Redis; -using UniSpy.Server.NatNegotiation.Contract.Request; -using UniSpy.Server.NatNegotiation.Contract.Response; -using UniSpy.Server.NatNegotiation.Contract.Result; -using UniSpy.Server.Core.Logging; - -namespace UniSpy.Server.NatNegotiation.Handler.CmdHandler -{ - /// - /// Get nat neg result report success or fail - /// - - public sealed class ReportHandler : CmdHandlerBase - { - private new ReportRequest _request => (ReportRequest)base._request; - private new ReportResult _result { get => (ReportResult)base._result; set => base._result = value; } - /// - /// The first layer key is the current client's public ip address, the second layer key is the current clients's private ip address, the third layer key is the other client's natneg server id, and the fourth key is the other client's private ip address - /// the hash value of the same IPAddress is the same, so it can be used as the dictionary key. - /// - // internal static Dictionary NatFailRecordInfos; - private NatInitInfo _myInitInfo; - private NatInitInfo _othersInitInfo; - // private string _searchKey; - static ReportHandler() - { - // NatFailRecordInfos = new Dictionary(); - } - public ReportHandler(Client client, ReportRequest request) : base(client, request) - { - _result = new ReportResult(); - } - protected override void RequestCheck() - { - base.RequestCheck(); - var addressInfos = StorageOperation.Persistance.GetInitInfos(_client.Server.Id, (uint)_request.Cookie); - if (addressInfos.Count < InitHandler.InitPacketCount) - { - throw new NatNegotiation.Exception($"The number of init info in redis with cookie: {_request.Cookie} is not bigger than 6."); - } - - NatClientIndex otherClientIndex = (NatClientIndex)(1 - _request.ClientIndex); - // we need both info to determine nat type - _othersInitInfo = new NatInitInfo(addressInfos.Where(i => i.ClientIndex == otherClientIndex).OrderBy(i => i.PortType).ToList()); - _myInitInfo = new NatInitInfo(addressInfos.Where(i => i.ClientIndex == _request.ClientIndex).OrderBy(i => i.PortType).ToList()); - } - protected override void ResponseConstruct() - { - _response = new ReportResponse(_request, _result); - } - - protected override void Response() - { - // we first response, the client will timeout if no response is received in some interval - base.Response(); - _client.LogInfo($"natneg success: {(bool)_request.IsNatSuccess}, version: {_request.Version}, gamename: {_request.GameName}, nat type: {_request.NatType} mapping scheme: {_request.MappingScheme}, cookie: {_request.Cookie}, client index: {_request.ClientIndex} port type: {_request.PortType}"); - // when negotiation failed we store the information - if (!(bool)_request.IsNatSuccess) - { - //todo we save the fail information some where else. - var info = new NatNegotiation.Aggregate.Redis.Fail.NatFailInfo(_myInitInfo, _othersInitInfo); - if (StorageOperation.Persistance.GetNatFailInfo(info) == 0) - { - StorageOperation.Persistance.UpdateNatFailInfo(info); - } - } - } - } -} diff --git a/src/Servers/NatNegotiation/src/Handler/CmdSwitcher.cs b/src/Servers/NatNegotiation/src/Handler/CmdSwitcher.cs deleted file mode 100755 index 87d69547b..000000000 --- a/src/Servers/NatNegotiation/src/Handler/CmdSwitcher.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.NatNegotiation.Enumerate; -using UniSpy.Server.NatNegotiation.Contract.Request; -using UniSpy.Server.NatNegotiation.Handler.CmdHandler; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.NatNegotiation.Application; - -namespace UniSpy.Server.NatNegotiation.Handler -{ - public sealed class CmdSwitcher : CmdSwitcherBase - { - private new byte[] _rawRequest => (byte[])base._rawRequest; - private new Client _client => (Client)base._client; - public CmdSwitcher(Client client, byte[] rawRequest) : base(client, rawRequest) - { - } - protected override void ProcessRawRequest() - { - var name = (RequestType)_rawRequest[7]; - _requests.Add(new KeyValuePair(name, _rawRequest)); - } - - protected override IHandler CreateCmdHandlers(object name, object rawRequest) - { - var req = (byte[])rawRequest; - switch ((RequestType)name) - { - case RequestType.Init: - return new InitHandler(_client, new InitRequest(req)); - case RequestType.AddressCheck: - return new AddressCheckHandler(_client, new AddressCheckRequest(req)); - case RequestType.NatifyRequest: - return new NatifyHandler(_client, new NatifyRequest(req)); - case RequestType.ErtAck: - return new ErtAckHandler(_client, new ErtAckRequest(req)); - case RequestType.Report: - return new ReportHandler(_client, new ReportRequest(req)); - case RequestType.ConnectAck: - return new ConnectAckHandler(_client, new ConnectAckRequest(req)); - default: - return null; - } - } - } -} diff --git a/src/Servers/NatNegotiation/src/UniSpy.Server.NatNegotiation.csproj b/src/Servers/NatNegotiation/src/UniSpy.Server.NatNegotiation.csproj deleted file mode 100755 index 711438cda..000000000 --- a/src/Servers/NatNegotiation/src/UniSpy.Server.NatNegotiation.csproj +++ /dev/null @@ -1,24 +0,0 @@ - - - - Exe - net6.0 - ..\..\..\..\common\Icon\UniSpy_Logo.ico - Linux - ..\..\..\.. - - - ..\..\..\..\build\$(Configuration) - - - ..\..\..\..\build\$(Configuration) - - - - - - - - - - \ No newline at end of file diff --git a/src/Servers/NatNegotiation/test/GameTest.cs b/src/Servers/NatNegotiation/test/GameTest.cs deleted file mode 100644 index dc1b3c725..000000000 --- a/src/Servers/NatNegotiation/test/GameTest.cs +++ /dev/null @@ -1,335 +0,0 @@ -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using UniSpy.Server.NatNegotiation.Aggregate.Redis; -using UniSpy.Server.Core.Abstraction.Interface; -using Xunit; - -namespace UniSpy.Server.NatNegotiation.Test -{ - public class GameTest - { - [Fact] - public void Anno1701_20230209() - { - new RedisClient().Db.Execute("FLUSHALL"); - var clients = new Dictionary() - { - {"client1gp",MockObject.CreateClient("192.168.0.109",1111)}, - {"client1nn",MockObject.CreateClient("192.168.0.109",64900)}, - {"client2nn",MockObject.CreateClient("192.168.0.109",4901)}, - }; - // Given - var gameClientInit = new List>() - { - //gameclient init - new KeyValuePair("client2nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0x00,0x00,0x50,0x7A,0x03,0x00,0x01,0xAC,0x1A,0x50,0x01,0x54,0xC5,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}), - new KeyValuePair("client2nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0x00,0x00,0x50,0x7A,0x02,0x00,0x01,0xAC,0x1A,0x50,0x01,0x54,0xC5,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}), - new KeyValuePair("client2nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0x00,0x00,0x50,0x7A,0x01,0x00,0x01,0xAC,0x1A,0x50,0x01,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}) - }; - var gameServerInit = new List>() - { - //gameserver init - new KeyValuePair("client1gp",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0x00,0x00,0x50,0x7A,0x03,0x01,0x01,0xC0,0xA8,0x00,0xD5,0x54,0xC5,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}), - new KeyValuePair("client1nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0x00,0x00,0x50,0x7A,0x02,0x01,0x01,0xC0,0xA8,0x00,0xD5,0x54,0xC5,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}), - new KeyValuePair("client1nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0x00,0x00,0x50,0x7A,0x00,0x01,0x01,0xC0,0xA8,0x00,0xD5,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}), - new KeyValuePair("client1nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0x00,0x00,0x50,0x7A,0x01,0x01,0x01,0xC0,0xA8,0x00,0xD5,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}), - }; - foreach (var request in gameServerInit) - { - Task.Run(() => ((ITestClient)clients[request.Key]).TestReceived(request.Value)); - } - foreach (var request in gameClientInit) - { - Task.Run(() => ((ITestClient)clients[request.Key]).TestReceived(request.Value)); - } - Thread.Sleep(5000); - // Then - } - [Fact] - public void Anno1701_20230127() - { - // Given - var req1 = new byte[] { 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x06, 0x00, 0x00, 0x35, 0x7A, 0xD4, 0x00, 0xA7, 0x08, 0xC0, 0xFC, 0xA7, 0x08, 0x00 }; - var req2 = new byte[] { 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x06, 0x00, 0x00, 0x35, 0x7A, 0x99, 0x01, 0x78, 0x6D, 0xF0, 0x53, 0xE8, 0x13, 0x5D }; - // When - var client = (ITestClient)MockObject.CreateClient("192.168.0.109", 64900); - client.TestReceived(req1); - client.TestReceived(req2); - // Then - } - [Fact] - /// - /// natneg success - /// - public void GameSpySDK20221116() - { - new RedisClient().Db.Execute("FLUSHDB"); - var clients = new Dictionary() - { - {"client1gp",MockObject.CreateClient("192.168.0.109",1111)}, - {"client1nn",MockObject.CreateClient("192.168.0.109",64900)}, - {"client2nn",MockObject.CreateClient("192.168.0.109",4901)}, - }; - var gameServerInit = new List>() - { - //gameserver init - new KeyValuePair("client1gp",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0xA6,0x38,0xF1,0x2B,0x00,0x01,0x01,0xC0,0xA8,0x00,0x6D,0x00,0x00,0x67,0x6D,0x74,0x65,0x73,0x74,0x00}), - new KeyValuePair("client1nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0xA6,0x38,0xF1,0x2B,0x01,0x01,0x01,0xC0,0xA8,0x00,0x6D,0x00,0x00,0x67,0x6D,0x74,0x65,0x73,0x74,0x00}), - new KeyValuePair("client1nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0xA6,0x38,0xF1,0x2B,0x02,0x01,0x01,0xC0,0xA8,0x00,0x6D,0x2B,0x67,0x67,0x6D,0x74,0x65,0x73,0x74,0x00}), - new KeyValuePair("client1nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0xA6,0x38,0xF1,0x2B,0x03,0x01,0x01,0xC0,0xA8,0x00,0x6D,0x2B,0x67,0x67,0x6D,0x74,0x65,0x73,0x74,0x00}), - }; - var gameClientInit = new List>() - { - //gameclient init - new KeyValuePair("client2nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0xA6,0x38,0xF1,0x2B,0x01,0x00,0x00,0xC0,0xA8,0x00,0x6D,0x00,0x00,0x67,0x6D,0x74,0x65,0x73,0x74,0x00}), - new KeyValuePair("client2nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0xA6,0x38,0xF1,0x2B,0x02,0x00,0x00,0xC0,0xA8,0x00,0x6D,0xFD,0x84,0x67,0x6D,0x74,0x65,0x73,0x74,0x00}), - new KeyValuePair("client2nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0xA6,0x38,0xF1,0x2B,0x03,0x00,0x00,0xC0,0xA8,0x00,0x6D,0xFD,0x84,0x67,0x6D,0x74,0x65,0x73,0x74,0x00}) - }; - var gameServerReport = new KeyValuePair("client1gp", new byte[] { - 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x0D, 0xA6, 0x38, 0xF1, 0x2B, 0xCC, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }); - var gameClientReport = new KeyValuePair("client2nn", new byte[] { - 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x0D, 0xA6, 0x38, 0xF1, 0x2B, 0xCC, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }); - foreach (var request in gameServerInit) - { - ((ITestClient)clients[request.Key]).TestReceived(request.Value); - } - foreach (var request in gameClientInit) - { - ((ITestClient)clients[request.Key]).TestReceived(request.Value); - } - Thread.Sleep(5000); - - Task.Run(() => ((ITestClient)clients[gameServerReport.Key]).TestReceived(gameServerReport.Value)); - Task.Run(() => ((ITestClient)clients[gameClientReport.Key]).TestReceived(gameClientReport.Value)); - - Thread.Sleep(5000); - - } - [Fact] - /// - /// natneg fail with retry, test the strategy change - /// - public void NatPunchStrategy20221117() - { - new RedisClient().Db.Execute("FLUSHDB"); - var clients1 = new Dictionary() - { - {"client1gp",MockObject.CreateClient("192.168.0.109",1111)}, - {"client1nn",MockObject.CreateClient("192.168.0.109",64900)}, - {"client2nn",MockObject.CreateClient("192.168.0.109",4901)}, - }; - var gameServerInit = new List>() - { - //gameserver init - new KeyValuePair("client1gp",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0xA6,0x38,0xF1,0x2B,0x00,0x01,0x01,0xC0,0xA8,0x00,0x6D,0x00,0x00,0x67,0x6D,0x74,0x65,0x73,0x74,0x00}), - new KeyValuePair("client1nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0xA6,0x38,0xF1,0x2B,0x01,0x01,0x01,0xC0,0xA8,0x00,0x6D,0x00,0x00,0x67,0x6D,0x74,0x65,0x73,0x74,0x00}), - new KeyValuePair("client1nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0xA6,0x38,0xF1,0x2B,0x02,0x01,0x01,0xC0,0xA8,0x00,0x6D,0x2B,0x67,0x67,0x6D,0x74,0x65,0x73,0x74,0x00}), - new KeyValuePair("client1nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0xA6,0x38,0xF1,0x2B,0x03,0x01,0x01,0xC0,0xA8,0x00,0x6D,0x2B,0x67,0x67,0x6D,0x74,0x65,0x73,0x74,0x00}), - }; - var gameClientInit = new List>() - { - //gameclient init - new KeyValuePair("client2nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0xA6,0x38,0xF1,0x2B,0x01,0x00,0x00,0xC0,0xA8,0x00,0x6D,0x00,0x00,0x67,0x6D,0x74,0x65,0x73,0x74,0x00}), - new KeyValuePair("client2nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0xA6,0x38,0xF1,0x2B,0x02,0x00,0x00,0xC0,0xA8,0x00,0x6D,0xFD,0x84,0x67,0x6D,0x74,0x65,0x73,0x74,0x00}), - new KeyValuePair("client2nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0xA6,0x38,0xF1,0x2B,0x03,0x00,0x00,0xC0,0xA8,0x00,0x6D,0xFD,0x84,0x67,0x6D,0x74,0x65,0x73,0x74,0x00}) - }; - // natneg fail - var gameServerReport = new KeyValuePair("client1gp", new byte[] { - 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x0D, 0xA6, 0x38, 0xF1, 0x2B, 0xCC, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }); - var gameClientReport = new KeyValuePair("client2nn", new byte[] { - 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x0D, 0xA6, 0x38, 0xF1, 0x2B, 0xCC, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }); - foreach (var request in gameServerInit) - { - ((ITestClient)clients1[request.Key]).TestReceived(request.Value); - } - foreach (var request in gameClientInit) - { - ((ITestClient)clients1[request.Key]).TestReceived(request.Value); - } - Thread.Sleep(5000); - - Task.Run(() => ((ITestClient)clients1[gameServerReport.Key]).TestReceived(gameServerReport.Value)); - Task.Run(() => ((ITestClient)clients1[gameClientReport.Key]).TestReceived(gameClientReport.Value)); - - Thread.Sleep(5000); - - var clients2 = new Dictionary() - { - {"client1gp",MockObject.CreateClient("192.168.0.109",1111)}, - {"client1nn",MockObject.CreateClient("192.168.0.109",64902)}, - {"client2nn",MockObject.CreateClient("192.168.0.109",4902)}, - }; - // new negotiation - var gameServerInit2 = new List>() - { - //gameserver init - new KeyValuePair("client1gp",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0xA7,0x38,0xF1,0x2B,0x00,0x01,0x01,0xC0,0xA8,0x00,0x6D,0x00,0x00,0x67,0x6D,0x74,0x65,0x73,0x74,0x00}), - new KeyValuePair("client1nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0xA7,0x38,0xF1,0x2B,0x01,0x01,0x01,0xC0,0xA8,0x00,0x6D,0x00,0x00,0x67,0x6D,0x74,0x65,0x73,0x74,0x00}), - new KeyValuePair("client1nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0xA7,0x38,0xF1,0x2B,0x02,0x01,0x01,0xC0,0xA8,0x00,0x6D,0x2B,0x67,0x67,0x6D,0x74,0x65,0x73,0x74,0x00}), - new KeyValuePair("client1nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0xA7,0x38,0xF1,0x2B,0x03,0x01,0x01,0xC0,0xA8,0x00,0x6D,0x2B,0x67,0x67,0x6D,0x74,0x65,0x73,0x74,0x00}), - }; - var gameClientInit2 = new List>() - { - //gameclient init - new KeyValuePair("client2nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0xA7,0x38,0xF1,0x2B,0x01,0x00,0x00,0xC0,0xA8,0x00,0x6D,0x00,0x00,0x67,0x6D,0x74,0x65,0x73,0x74,0x00}), - new KeyValuePair("client2nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0xA7,0x38,0xF1,0x2B,0x02,0x00,0x00,0xC0,0xA8,0x00,0x6D,0xFD,0x84,0x67,0x6D,0x74,0x65,0x73,0x74,0x00}), - new KeyValuePair("client2nn",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0xA7,0x38,0xF1,0x2B,0x03,0x00,0x00,0xC0,0xA8,0x00,0x6D,0xFD,0x84,0x67,0x6D,0x74,0x65,0x73,0x74,0x00}) - }; - // natneg success - var gameServerReport2 = new KeyValuePair("client1gp", new byte[] { - 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x0D, 0xA7, 0x38, 0xF1, 0x2B, 0xCC, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }); - var gameClientReport2 = new KeyValuePair("client2nn", new byte[] { - 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x0D, 0xA7, 0x38, 0xF1, 0x2B, 0xCC, 0x01, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }); - foreach (var request in gameServerInit2) - { - ((ITestClient)clients2[request.Key]).TestReceived(request.Value); - } - foreach (var request in gameClientInit2) - { - ((ITestClient)clients2[request.Key]).TestReceived(request.Value); - } - Thread.Sleep(5000); - - Task.Run(() => ((ITestClient)clients2[gameServerReport2.Key]).TestReceived(gameServerReport2.Value)); - Task.Run(() => ((ITestClient)clients2[gameClientReport2.Key]).TestReceived(gameClientReport2.Value)); - - Thread.Sleep(5000); - - } - [Fact] - public void NatFullConeTest() - { - // clean all stuff in database - new RedisClient().Db.Execute("FLUSHDB"); - - var client = MockObject.CreateClient("192.168.1.2", 9999); - var server = MockObject.CreateClient("192.168.1.3", 9999); - var clientInitGP = new byte[] { 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x00, 0x00, 0x00, 0x02, 0x9A, 0x00, 0x00, 0x01, 0x7F, 0x00, 0x01, 0x01, 0x00, 0x00, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00 }; - var clientInitNN1 = new byte[] { 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x00, 0x00, 0x00, 0x02, 0x9A, 0x01, 0x00, 0x01, 0x7F, 0x00, 0x01, 0x01, 0x00, 0x00, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00 }; - var clientInitNN2 = new byte[] { 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x00, 0x00, 0x00, 0x02, 0x9A, 0x02, 0x00, 0x01, 0x7F, 0x00, 0x01, 0x01, 0xBB, 0x37, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00 }; - var clientInitNN3 = new byte[] { 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x00, 0x00, 0x00, 0x02, 0x9A, 0x03, 0x00, 0x01, 0x7F, 0x00, 0x01, 0x01, 0xBB, 0x37, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00 }; - - var serverInitGP = new byte[] { 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x00, 0x00, 0x00, 0x02, 0x9A, 0x00, 0x01, 0x01, 0x7F, 0x00, 0x01, 0x01, 0x00, 0x00, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00 }; - var serverInitNN1 = new byte[] { 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x00, 0x00, 0x00, 0x02, 0x9A, 0x01, 0x01, 0x01, 0x7F, 0x00, 0x01, 0x01, 0x00, 0x00, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00 }; - var serverInitNN2 = new byte[] { 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x00, 0x00, 0x00, 0x02, 0x9A, 0x02, 0x01, 0x01, 0x7F, 0x00, 0x01, 0x01, 0xD2, 0xAE, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00 }; - var serverInitNN3 = new byte[] { 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x00, 0x00, 0x00, 0x02, 0x9A, 0x03, 0x01, 0x01, 0x7F, 0x00, 0x01, 0x01, 0xD2, 0xAE, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00 }; - var clientRequests = new List { clientInitGP, clientInitNN1, clientInitNN2, clientInitNN3 }; - var serverRequests = new List { serverInitGP, serverInitNN1, serverInitNN2, serverInitNN3 }; - - - foreach (var request in clientRequests) - { - ((ITestClient)client).TestReceived(request); - } - foreach (var request in serverRequests) - { - ((ITestClient)server).TestReceived(request); - } - // because the process is running in background we need to wait it finish, so we can debug - // Thread.Sleep(10000); - // Console.Read(); - } - - [Fact] - public void NatConePortIncrement() - { - // clean all stuff in database - new RedisClient().Db.Execute("FLUSHDB"); - - var client = MockObject.CreateClient("192.168.1.2", 53935); - var server = MockObject.CreateClient("192.168.1.3", 53935); - - var clientInitGP = new byte[] { 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x00, 0x00, 0x00, 0x02, 0x9A, 0x00, 0x00, 0x01, 0x7F, 0x00, 0x01, 0x01, 0x00, 0x00, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00 }; - var clientInitNN1 = new byte[] { 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x00, 0x00, 0x00, 0x02, 0x9A, 0x01, 0x00, 0x01, 0x7F, 0x00, 0x01, 0x01, 0x00, 0x00, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00 }; - var clientInitNN2 = new byte[] { 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x00, 0x00, 0x00, 0x02, 0x9A, 0x02, 0x00, 0x01, 0x7F, 0x00, 0x01, 0x01, 0xBB, 0x37, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00 }; - var clientInitNN3 = new byte[] { 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x00, 0x00, 0x00, 0x02, 0x9A, 0x03, 0x00, 0x01, 0x7F, 0x00, 0x01, 0x01, 0xBB, 0x37, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00 }; - - var serverInitGP = new byte[] { 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x00, 0x00, 0x00, 0x02, 0x9A, 0x00, 0x01, 0x01, 0x7F, 0x00, 0x01, 0x01, 0x00, 0x00, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00 }; - var serverInitNN1 = new byte[] { 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x00, 0x00, 0x00, 0x02, 0x9A, 0x01, 0x01, 0x01, 0x7F, 0x00, 0x01, 0x01, 0x00, 0x00, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00 }; - var serverInitNN2 = new byte[] { 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x00, 0x00, 0x00, 0x02, 0x9A, 0x02, 0x01, 0x01, 0x7F, 0x00, 0x01, 0x01, 0xD2, 0xAE, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00 }; - var serverInitNN3 = new byte[] { 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x00, 0x00, 0x00, 0x02, 0x9A, 0x03, 0x01, 0x01, 0x7F, 0x00, 0x01, 0x01, 0xD2, 0xAE, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00 }; - var clientRequests = new List { clientInitGP, clientInitNN1, clientInitNN2, clientInitNN3 }; - var serverRequests = new List { serverInitGP, serverInitNN1, serverInitNN2, serverInitNN3 }; - - foreach (var request in clientRequests) - { - ((ITestClient)client).TestReceived(request); - } - foreach (var request in serverRequests) - { - ((ITestClient)server).TestReceived(request); - } - // because the process is running in background we need to wait it finish, so we can debug - // Thread.Sleep(10000); - } - - [Fact] - public void Anno1701() - { - var client1GP = MockObject.CreateClient("31.18.120.193", 21701); - var client1NN1 = MockObject.CreateClient("31.18.120.193", 51463); - var client1NN2 = MockObject.CreateClient("31.18.120.193", 51463); - var client1NN3 = MockObject.CreateClient("31.18.120.193", 51463); - - var client2GP = MockObject.CreateClient("79.209.224.29", 21701); - var client2NN1 = MockObject.CreateClient("79.209.224.29", 51463); - var client2NN2 = MockObject.CreateClient("79.209.224.29", 51463); - var client2NN3 = MockObject.CreateClient("79.209.224.29", 51463); - - - var client3GP = MockObject.CreateClient("79.209.224.29", 1024); - var client3NN1 = MockObject.CreateClient("79.209.224.29", 55111); - var client3NN2 = MockObject.CreateClient("79.209.224.29", 55111); - var client3NN3 = MockObject.CreateClient("79.209.224.29", 55111); - - var requests = new List>() - { - new KeyValuePair(client1GP,new byte[] {0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0x00,0x00,0x1D,0x76,0x00,0x00,0x01,0xC0,0xA8,0x00,0xD5,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}), - new KeyValuePair(client1NN1,new byte[] {0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0x00,0x00,0x1D,0x76,0x01,0x00,0x01,0xC0,0xA8,0x00,0xD5,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}), - new KeyValuePair(client1NN2,new byte[] {0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0x00,0x00,0x1D,0x76,0x02,0x00,0x01,0xC0,0xA8,0x00,0xD5,0x54,0xC5,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}), - new KeyValuePair(client1NN3,new byte[] {0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0x00,0x00,0x1D,0x76,0x03,0x00,0x01,0xC0,0xA8,0x00,0xD5,0x54,0xC5,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}), - - new KeyValuePair(client2GP,new byte[] {0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0x00,0x00,0x1D,0x76,0x00,0x01,0x01,0xC0,0xA8,0x00,0x32,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}), - new KeyValuePair(client2NN1,new byte[] {0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0x00,0x00,0x1D,0x76,0x01,0x01,0x01,0xC0,0xA8,0x00,0x32,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}), - new KeyValuePair(client2NN2,new byte[] {0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0x00,0x00,0x1D,0x76,0x02,0x01,0x01,0xC0,0xA8,0x00,0x32,0x54,0xC5,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}), - new KeyValuePair(client2NN3,new byte[] {0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0x00,0x00,0x1D,0x76,0x03,0x01,0x01,0xC0,0xA8,0x00,0x32,0x54,0xC5,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}), - }; - - foreach (var req in requests) - { - ((ITestClient)req.Key).TestReceived(req.Value); - } - // because the process is running in background we need to wait it finish, so we can debug - Thread.Sleep(10000); - } - - [Fact] - public void Flatout2pc20230519() - { - new RedisClient().FlushDb(); - var client1GP = MockObject.CreateClient("91.43.63.201", 23756); - var client1NN1 = MockObject.CreateClient("91.43.63.201", 64871); - var client1NN2 = MockObject.CreateClient("91.43.63.201", 64871); - - var client2GP = MockObject.CreateClient("91.43.63.201", 1025); - var client2NN1 = MockObject.CreateClient("91.43.63.201", 41159); - var client2NN2 = MockObject.CreateClient("91.43.63.201", 41159); - var requests = new List>() - { - new KeyValuePair(client1GP,new byte[] {0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x02,0x00,0xC8,0xDF,0x69,0x75,0x00,0x00,0x01,0xC0,0xA8,0x00,0x71,0x00,0x00,0x66,0x6C,0x61,0x74,0x6F,0x75,0x74,0x32,0x70,0x63,0x00}), - new KeyValuePair(client1NN1,new byte[] {0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x02,0x00,0xC8,0xDF,0x69,0x75,0x01,0x00,0x01,0xC0,0xA8,0x00,0x71,0x00,0x00,0x66,0x6C,0x61,0x74,0x6F,0x75,0x74,0x32,0x70,0x63,0x00}), - new KeyValuePair(client1NN2,new byte[] {0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x02,0x00,0xC8,0xDF,0x69,0x75,0x02,0x00,0x01,0xC0,0xA8,0x00,0x71,0x00,0x00,0x66,0x6C,0x61,0x74,0x6F,0x75,0x74,0x32,0x70,0x63,0x00}), - new KeyValuePair(client2GP,new byte[] {0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x02,0x00,0xC8,0xDF,0x69,0x75,0x00,0x01,0x01,0xC0,0xA8,0x00,0x3C,0x00,0x00,0x66,0x6C,0x61,0x74,0x6F,0x75,0x74,0x32,0x70,0x63,0x00}), - new KeyValuePair(client2NN1,new byte[] {0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x02,0x00,0xC8,0xDF,0x69,0x75,0x01,0x01,0x01,0xC0,0xA8,0x00,0x3C,0x00,0x00,0x66,0x6C,0x61,0x74,0x6F,0x75,0x74,0x32,0x70,0x63,0x00}), - new KeyValuePair(client2NN1,new byte[] {0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x02,0x00,0xC8,0xDF,0x69,0x75,0x02,0x01,0x01,0xC0,0xA8,0x00,0x3C,0x00,0x00,0x66,0x6C,0x61,0x74,0x6F,0x75,0x74,0x32,0x70,0x63,0x00}) - }; - - foreach (var req in requests) - { - (req.Key as ITestClient).TestReceived(req.Value); - } - Thread.Sleep(10000); - } - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/test/HandlerTest.cs b/src/Servers/NatNegotiation/test/HandlerTest.cs deleted file mode 100644 index f4bc6261d..000000000 --- a/src/Servers/NatNegotiation/test/HandlerTest.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System.Net; -using UniSpy.Server.NatNegotiation.Application; -using UniSpy.Server.NatNegotiation.Contract.Request; -using UniSpy.Server.NatNegotiation.Handler.CmdHandler; -using Xunit; -namespace UniSpy.Server.NatNegotiation.Test -{ - - public class HandlerTest - { - Client _client; - public HandlerTest() - { - _client = MockObject.CreateClient(); - } - [Fact] - public void InitTest() - { - var rawRequest = new byte[] { - 0xfd, 0xfc, 0x1e, 0x66, 0x6a, 0xb2, 0x03, - 0x00, - 0x00, 0x00, 0x03, 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - var request = new InitRequest(rawRequest); - var handler = new InitHandler(_client, request); - handler.Handle(); - } - [Fact] - public void AddressTest() - { - var rawRequest = new byte[] { 0xfd, 0xfc, 0x1e, 0x66, 0x6a, 0xb2, 0x03, 0x0a, 0x00, 0x00, 0x03, 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - var request = new AddressCheckRequest(rawRequest); - var handler = new AddressCheckHandler(_client, request); - handler.Handle(); - } - [Fact] - public void ErtTest() - { - var rawRequest = new byte[] { - 0xfd, 0xfc, 0x1e, 0x66, 0x6a, 0xb2, 0x03, - 0x03, - 0x00, 0x00, 0x03, 0x09, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - var request = new ErtAckRequest(rawRequest); - var handler = new ErtAckHandler(_client, request); - handler.Handle(); - } - [Fact] - public void NatifyTest() - { - var rawRequest = new byte[] { - 0xfd, 0xfc, 0x1e, 0x66, 0x6a, 0xb2, 0x03, - 0x0c, - 0x00, 0x00, 0x03, 0x09, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - var request = new NatifyRequest(rawRequest); - var handler = new NatifyHandler(_client, request); - handler.Handle(); - } - - [Fact] - public void ReportTest() - { - var r1 = new UniSpy.Server.NatNegotiation.Aggregate.Misc.NatReportRecord() - { - ServerId = System.Guid.Empty, - PublicIPAddress = IPAddress.Parse("202.91.34.186"), - PrivateIPAddress = IPAddress.Parse("192.168.1.1") - }; - - var r2 = new UniSpy.Server.NatNegotiation.Aggregate.Misc.NatReportRecord() - { - ServerId = System.Guid.Empty, - PublicIPAddress = IPAddress.Parse("202.91.34.186"), - PrivateIPAddress = IPAddress.Parse("192.168.1.1") - }; - Assert.Equal(r1.PublicIPAddress, r2.PublicIPAddress); - Assert.Equal(r1.PrivateIPAddress, r2.PrivateIPAddress); - Assert.Equal(r1.ServerId, r2.ServerId); - - - // _client.Info.Cookie = - var req = new byte[] { 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x03, 0x0D, 0x00, 0x00, 0x02, 0x9A, 0xCC, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - var request = new ReportRequest(req); - var handler = new ReportHandler(_client, request); - handler.Handle(); - } - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/test/MockObject.cs b/src/Servers/NatNegotiation/test/MockObject.cs deleted file mode 100644 index 41d4fbe96..000000000 --- a/src/Servers/NatNegotiation/test/MockObject.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Net; -using Moq; -using UniSpy.Server.NatNegotiation.Application; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.NatNegotiation.Test -{ - public static class MockObject - { - public static IClient Client = CreateClient(); - - public static Client CreateClient(string ipAddress = "192.168.1.1", int port = 9999) - { - var managerMock = new Mock(); - var connectionMock = new Mock(); - connectionMock.Setup(s => s.RemoteIPEndPoint).Returns(new IPEndPoint(IPAddress.Parse(ipAddress), port)); - connectionMock.Setup(s => s.Manager).Returns(managerMock.Object); - connectionMock.Setup(s => s.ConnectionType).Returns(NetworkConnectionType.Udp); - var serverMock = new NatNegotiation.Application.Server(managerMock.Object); - - return new Client(connectionMock.Object, serverMock); - } - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/test/NatDetectionTest.cs b/src/Servers/NatNegotiation/test/NatDetectionTest.cs deleted file mode 100644 index 6dc31b252..000000000 --- a/src/Servers/NatNegotiation/test/NatDetectionTest.cs +++ /dev/null @@ -1,221 +0,0 @@ -using System.Collections.Generic; -using System.Net; -using UniSpy.Server.NatNegotiation.Enumerate; -using UniSpy.Server.NatNegotiation.Aggregate.Redis; -using UniSpy.Server.NatNegotiation.Handler.CmdHandler; -using Xunit; - -namespace UniSpy.Server.NatNegotiation.Test -{ - public class NatDetectionTest - { - [Fact] - public void PublicIPTest() - { - var list = new List() - { - new NatAddressInfo() - { - PortType = NatPortType.GP, - ClientIndex = NatClientIndex.GameClient, - Cookie = 123, - Version=3, - GameName ="gmtest", - PublicIPEndPoint = IPEndPoint.Parse("10.0.0.1:1"), - PrivateIPEndPoint = IPEndPoint.Parse("10.0.0.1:0") - }, - new NatAddressInfo() - { - PortType = NatPortType.NN1, - ClientIndex = NatClientIndex.GameClient, - Cookie = 123, - Version=3, - GameName ="gmtest", - PublicIPEndPoint = IPEndPoint.Parse("10.0.0.1:2"), - PrivateIPEndPoint = IPEndPoint.Parse("10.0.0.1:0") - }, - new NatAddressInfo() - { - PortType = NatPortType.NN2, - ClientIndex = NatClientIndex.GameClient, - Cookie = 123, - Version=3, - GameName ="gmtest", - PublicIPEndPoint = IPEndPoint.Parse("10.0.0.1:2"), - PrivateIPEndPoint = IPEndPoint.Parse("10.0.0.1:2") - }, - new NatAddressInfo() - { - PortType = NatPortType.NN3, - ClientIndex = NatClientIndex.GameClient, - Cookie = 123, - Version=3, - GameName ="gmtest", - PublicIPEndPoint = IPEndPoint.Parse("10.0.0.1:2"), - PrivateIPEndPoint = IPEndPoint.Parse("10.0.0.1:2") - } - }; - var initInfo = new NatInitInfo(list); - var prop = AddressCheckHandler.DetermineNatTypeVersion3(initInfo); - - Assert.Equal(NatType.NoNat, prop.NatType); - } - [Fact] - public void FullConeTest() - { - var list = new List() - { - new NatAddressInfo() - { - PortType = NatPortType.GP, - ClientIndex = NatClientIndex.GameClient, - Cookie = 123, - Version=3, - GameName ="gmtest", - PublicIPEndPoint = IPEndPoint.Parse("10.0.0.1:1"), - PrivateIPEndPoint = IPEndPoint.Parse("192.168.1.1:0") - }, - new NatAddressInfo() - { - PortType = NatPortType.NN1, - ClientIndex = NatClientIndex.GameClient, - Cookie = 123, - Version=3, - GameName ="gmtest", - PublicIPEndPoint = IPEndPoint.Parse("10.0.0.1:2"), - PrivateIPEndPoint = IPEndPoint.Parse("192.168.1.1:0") - }, - new NatAddressInfo() - { - PortType = NatPortType.NN2, - ClientIndex = NatClientIndex.GameClient, - Cookie = 123, - Version=3, - GameName ="gmtest", - PublicIPEndPoint = IPEndPoint.Parse("10.0.0.1:2"), - PrivateIPEndPoint = IPEndPoint.Parse("192.168.1.1:2") - }, - new NatAddressInfo() - { - PortType = NatPortType.NN3, - ClientIndex = NatClientIndex.GameClient, - Cookie = 123, - Version=3, - GameName ="gmtest", - PublicIPEndPoint = IPEndPoint.Parse("10.0.0.1:2"), - PrivateIPEndPoint = IPEndPoint.Parse("192.168.1.1:2") - } - }; - var initInfo = new NatInitInfo(list); - var prop = AddressCheckHandler.DetermineNatTypeVersion3(initInfo); - Assert.Equal(NatType.FullCone, prop.NatType); - - } - - [Fact] - public void SymetricTest() - { - var list = new List() - { - new NatAddressInfo() - { - PortType = NatPortType.GP, - ClientIndex = NatClientIndex.GameClient, - Cookie = 123, - Version=3, - GameName ="gmtest", - PublicIPEndPoint = IPEndPoint.Parse("10.0.0.1:1"), - PrivateIPEndPoint = IPEndPoint.Parse("192.168.1.1:1") - }, - new NatAddressInfo() - { - PortType = NatPortType.NN1, - ClientIndex = NatClientIndex.GameClient, - Cookie = 123, - Version=3, - GameName ="gmtest", - PublicIPEndPoint = IPEndPoint.Parse("10.0.0.1:2"), - PrivateIPEndPoint = IPEndPoint.Parse("192.168.1.1:2") - }, - new NatAddressInfo() - { - PortType = NatPortType.NN2, - ClientIndex = NatClientIndex.GameClient, - Cookie = 123, - Version=3, - GameName ="gmtest", - PublicIPEndPoint = IPEndPoint.Parse("10.0.0.1:3"), - PrivateIPEndPoint = IPEndPoint.Parse("192.168.1.1:2") - }, - new NatAddressInfo() - { - PortType = NatPortType.NN3, - ClientIndex = NatClientIndex.GameClient, - Cookie = 123, - Version=3, - GameName ="gmtest", - PublicIPEndPoint = IPEndPoint.Parse("10.0.0.1:4"), - PrivateIPEndPoint = IPEndPoint.Parse("192.168.1.1:2") - } - }; - var initInfo = new NatInitInfo(list); - var prop = AddressCheckHandler.DetermineNatTypeVersion3(initInfo); - Assert.Equal(NatType.Symmetric, prop.NatType); - - } - [Fact] - public void NatStrategyTest() - { - - } - [Fact] - public void SposiriusNetworkTest() - { - var list = new List() - { - new NatAddressInfo() - { - PortType = NatPortType.GP, - ClientIndex = NatClientIndex.GameClient, - Cookie = 123, - Version=3, - GameName ="gmtest", - PublicIPEndPoint = IPEndPoint.Parse("91.52.105.210:51520"), - PrivateIPEndPoint = IPEndPoint.Parse("192.168.0.60:0") - }, - new NatAddressInfo() - { - PortType = NatPortType.NN1, - ClientIndex = NatClientIndex.GameClient, - Cookie = 123, - Version=3, - GameName ="gmtest", - PublicIPEndPoint = IPEndPoint.Parse("91.52.105.210:51521"), - PrivateIPEndPoint = IPEndPoint.Parse("192.168.0.60:0") - },new NatAddressInfo() - { - PortType = NatPortType.NN2, - ClientIndex = NatClientIndex.GameClient, - Cookie = 123, - Version=3, - GameName ="gmtest", - PublicIPEndPoint = IPEndPoint.Parse("91.52.105.210:49832"), - PrivateIPEndPoint = IPEndPoint.Parse("192.168.0.60:49832") - },new NatAddressInfo() - { - PortType = NatPortType.NN3, - ClientIndex = NatClientIndex.GameClient, - Cookie = 123, - Version=3, - GameName ="gmtest", - PublicIPEndPoint = IPEndPoint.Parse("91.52.105.210:49832"), - PrivateIPEndPoint = IPEndPoint.Parse("192.168.0.60:49832") - }, - }; - var initInfo = new NatInitInfo(list); - - var prop = AddressCheckHandler.DetermineNatTypeVersion3(initInfo); - Assert.Equal(NatType.Symmetric, prop.NatType); - } - } -} \ No newline at end of file diff --git a/src/Servers/NatNegotiation/test/RequestTest.cs b/src/Servers/NatNegotiation/test/RequestTest.cs deleted file mode 100644 index 052720468..000000000 --- a/src/Servers/NatNegotiation/test/RequestTest.cs +++ /dev/null @@ -1,87 +0,0 @@ -using UniSpy.Server.NatNegotiation.Enumerate; -using UniSpy.Server.NatNegotiation.Contract.Request; -using Xunit; - -namespace UniSpy.Server.NatNegotiation.Test -{ - public class RequestTest - { - [Fact] - public void InitTest() - { - var rawRequest = new byte[] { - 0xfd, 0xfc, 0x1e, 0x66, 0x6a, 0xb2, 0x03, - 0x00, - 0x00, 0x00, 0x03, 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - var request = new InitRequest(rawRequest); - request.Parse(); - Assert.True(RequestType.Init == request.CommandName); - Assert.True((uint)151191552 == request.Cookie); - Assert.True(NatClientIndex.GameClient == request.ClientIndex); - Assert.True(false == request.UseGamePort); - Assert.True((byte)3 == request.Version); - Assert.True(NatPortType.NN1 == request.PortType); - } - [Fact] - public void AddressTest() - { - var rawRequest = new byte[] { 0xfd, 0xfc, 0x1e, 0x66, 0x6a, 0xb2, 0x03, 0x0a, 0x00, 0x00, 0x03, 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - var request = new AddressCheckRequest(rawRequest); - request.Parse(); - Assert.True(RequestType.AddressCheck == request.CommandName); - Assert.True((uint)151191552 == request.Cookie); - Assert.True(NatClientIndex.GameClient == request.ClientIndex); - Assert.True(false == request.UseGamePort); - Assert.True((byte)3 == request.Version); - Assert.True(NatPortType.NN1 == request.PortType); - } - [Fact] - public void ErtAckTest() - { - var rawRequest = new byte[] { - 0xfd, 0xfc, 0x1e, 0x66, 0x6a, 0xb2, 0x03, - 0x03, - 0x00, 0x00, 0x03, 0x09, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - var request = new ErtAckRequest(rawRequest); - request.Parse(); - Assert.True(RequestType.ErtAck == request.CommandName); - Assert.True((uint)151191552 == request.Cookie); - Assert.True(NatClientIndex.GameClient == request.ClientIndex); - Assert.True((byte)3 == request.Version); - Assert.True(false == request.UseGamePort); - Assert.True(NatPortType.NN1 == request.PortType); - } - [Fact] - public void NatifyTest() - { - var rawRequest = new byte[] { - 0xfd, 0xfc, 0x1e, 0x66, 0x6a, 0xb2, 0x03, - 0x0c, - 0x00, 0x00, 0x03, 0x09, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - var request = new ErtAckRequest(rawRequest); - request.Parse(); - Assert.True(RequestType.NatifyRequest == request.CommandName); - Assert.True((uint)151191552 == request.Cookie); - Assert.True(NatClientIndex.GameClient == request.ClientIndex); - Assert.True((byte)3 == request.Version); - Assert.True(false == request.UseGamePort); - Assert.True(NatPortType.NN1 == request.PortType); - } - [Fact(Skip = "Not implemented")] - public void ReportTest() - { - - } - [Fact] - public void PreInitTest() - { - var raw = new byte[] { 0xfd, 0xfc, 0x1e, 0x66, 0x6a, 0xb2, 0x04, 0x0f, 0xb5, 0xe0, 0x95, 0x2a, 0x00, 0x24, 0x38, 0xb2, 0xb3, 0x5e }; - var request = new PreInitRequest(raw); - request.Parse(); - Assert.True(RequestType.PreInit == request.CommandName); - Assert.True(PreInitState.WaitingForClient == request.State); - } - } -} diff --git a/src/Servers/NatNegotiation/test/UniSpy.Server.NatNegotiation.Test.csproj b/src/Servers/NatNegotiation/test/UniSpy.Server.NatNegotiation.Test.csproj deleted file mode 100644 index 9b6f82b32..000000000 --- a/src/Servers/NatNegotiation/test/UniSpy.Server.NatNegotiation.Test.csproj +++ /dev/null @@ -1,31 +0,0 @@ - - - - net6.0 - false - ..\..\..\..\common\Icon\UniSpy_Logo.ico - - - AnyCPU - ..\..\..\..\build\$(Configuration) - - - ..\..\..\..\build\$(Configuration) - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - \ No newline at end of file diff --git a/src/Servers/PresenceConnectionManager/src/Abstraction/BaseClass/CmdHandlerBase.cs b/src/Servers/PresenceConnectionManager/src/Abstraction/BaseClass/CmdHandlerBase.cs deleted file mode 100755 index 5c7c927f1..000000000 --- a/src/Servers/PresenceConnectionManager/src/Abstraction/BaseClass/CmdHandlerBase.cs +++ /dev/null @@ -1,29 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Application; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass -{ - public abstract class CmdHandlerBase : UniSpy.Server.Core.Abstraction.BaseClass.CmdHandlerBase - { - /// - /// Because all errors are sent by SendGPError() - /// so we if the error code != noerror we send it - /// - protected new Client _client => (Client)base._client; - protected new RequestBase _request => (RequestBase)base._request; - protected new ResultBase _result { get => (ResultBase)base._result; set => base._result = value; } - public CmdHandlerBase(IClient client, IRequest request) : base(client, request) - { - } - - protected override void HandleException(System.Exception ex) - { - if (ex is GPException) - { - _client.Send(ex as IResponse); - } - base.HandleException(ex); - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Abstraction/BaseClass/LoggedInCmdHandlerBase.cs b/src/Servers/PresenceConnectionManager/src/Abstraction/BaseClass/LoggedInCmdHandlerBase.cs deleted file mode 100755 index ebb51db11..000000000 --- a/src/Servers/PresenceConnectionManager/src/Abstraction/BaseClass/LoggedInCmdHandlerBase.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Exception.General; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass -{ - public abstract class LoggedInCmdHandlerBase : CmdHandlerBase - { - public LoggedInCmdHandlerBase(IClient client, IRequest request) : base(client, request) - { - } - protected override void RequestCheck() - { - if(_client.Info.LoginStat!=Enumerate.LoginStatus.Completed) - { - throw new GPException("You are not logged in, please login first."); - } - base.RequestCheck(); - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Abstraction/BaseClass/RequestBase.cs b/src/Servers/PresenceConnectionManager/src/Abstraction/BaseClass/RequestBase.cs deleted file mode 100755 index 0995077f5..000000000 --- a/src/Servers/PresenceConnectionManager/src/Abstraction/BaseClass/RequestBase.cs +++ /dev/null @@ -1,62 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Exception.General; -using System.Collections.Generic; -using System.Linq; -using UniSpy.Server.Core.Extension; -using UniSpy.Server.Core.Misc; - -namespace UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass -{ - public abstract class RequestBase : UniSpy.Server.Core.Abstraction.BaseClass.RequestBase - { - public new string CommandName{ get => (string)base.CommandName; - protected set => base.CommandName = value; } - public int OperationID { get; protected set; } - - public new string RawRequest{ get => (string)base.RawRequest; set => base.RawRequest = value; } - public Dictionary RequestKeyValues { get; protected set; } - - public RequestBase() - { - } - - public RequestBase(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - RequestKeyValues = GameSpyUtils.ConvertToKeyValue(RawRequest); - CommandName = RequestKeyValues.Keys.First(); - - if (RequestKeyValues.ContainsKey("id")) - { - int operationID; - if (!int.TryParse(RequestKeyValues["id"], out operationID)) - { - throw new GPParseException("namespaceid is invalid."); - } - OperationID = operationID; - } - } - - public static string NormalizeRequest(string message) - { - if (message.Contains("login")) - { - message = message.Replace(@"\-", @"\"); - - int pos = message.IndexesOf("\\")[1]; - - if (message.Substring(pos, 2) != "\\\\") - { - message = message.Insert(pos, "\\"); - } - return message; - } - else - { - return message; - } - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Abstraction/BaseClass/ResponseBase.cs b/src/Servers/PresenceConnectionManager/src/Abstraction/BaseClass/ResponseBase.cs deleted file mode 100755 index 4127efd2a..000000000 --- a/src/Servers/PresenceConnectionManager/src/Abstraction/BaseClass/ResponseBase.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass -{ - public abstract class ResponseBase : UniSpy.Server.Core.Abstraction.BaseClass.ResponseBase - { - protected new ResultBase _result => (ResultBase)base._result; - protected new RequestBase _request => (RequestBase)base._request; - public new string SendingBuffer { get => (string)base.SendingBuffer; protected set => base.SendingBuffer = value; } - - public ResponseBase(RequestBase request, ResultBase result) : base(request, result) - { - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Abstraction/BaseClass/ResultBase.cs b/src/Servers/PresenceConnectionManager/src/Abstraction/BaseClass/ResultBase.cs deleted file mode 100755 index e5d822055..000000000 --- a/src/Servers/PresenceConnectionManager/src/Abstraction/BaseClass/ResultBase.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass -{ - public abstract class ResultBase : UniSpy.Server.Core.Abstraction.BaseClass.ResultBase - { - public ResultBase() - { - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Abstraction/Interface/IStorageOperation.cs b/src/Servers/PresenceConnectionManager/src/Abstraction/Interface/IStorageOperation.cs deleted file mode 100644 index 45fafebac..000000000 --- a/src/Servers/PresenceConnectionManager/src/Abstraction/Interface/IStorageOperation.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.PresenceConnectionManager.Contract.Result; -using UniSpy.Server.Core.Database.DatabaseModel; - -namespace UniSpy.Server.PresenceConnectionManager.Abstraction.Interface -{ - public interface IStorageOperation - { - List GetBlockedProfileIds(int profileId, int namespaceId); - List GetFriendProfileIds(int profileId, int namespaceId); - void DeleteFriendByProfileId(int profileId, int targetId, int namespaceId); - (User, Profile, Subprofile) GetUsersInfos(string email, string nickName); - (User, Profile, Subprofile) GetUsersInfos(string uniqueNick, int namespaceId); - (User, Profile, Subprofile) GetUsersInfos(string authToken, int partnerId, int namespaceId); - void UpdateBlockInfo(int targetId, int profileId, int namespaceId); - void UpdateFriendInfo(int targetId, int profileId, int namespaceId); - void UpdateProfileInfo(Profile profile); - GetProfileDataModel GetProfileInfos(int profileId, int namespaceId); - void UpdateUniqueNick(int subProfileId, string uniqueNick); - void UpdateNickName(int profileId, string oldNick, string newNick); - void AddNickName(int userId, int profileId, string newNick); - void UpdateSubProfileInfo(Subprofile subprofile); - bool IsEmailExist(string email); - } -} \ No newline at end of file diff --git a/src/Servers/PresenceConnectionManager/src/Aggregate/Misc/LoginChallengeProof.cs b/src/Servers/PresenceConnectionManager/src/Aggregate/Misc/LoginChallengeProof.cs deleted file mode 100755 index d0bf1776d..000000000 --- a/src/Servers/PresenceConnectionManager/src/Aggregate/Misc/LoginChallengeProof.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Text; -using UniSpy.Server.PresenceConnectionManager.Enumerate; -using UniSpy.Server.Core.Extension; - -namespace UniSpy.Server.PresenceConnectionManager.Structure -{ - public sealed class LoginChallengeProof - { - public const string ServerChallenge = "0000000000"; - public string UserData { get; private set; } - public LoginType LoginType { get; private set; } - public int? PartnerID { get; private set; } - public string Challenge1 { get; private set; } - public string Challenge2 { get; private set; } - public string PasswordHash { get; private set; } - - public LoginChallengeProof(string userData, LoginType loginType, int? partnerID, string challenge1, string challenge2, string passwordHash) - { - UserData = userData; - LoginType = loginType; - PartnerID = partnerID; - Challenge1 = challenge1; - Challenge2 = challenge2; - PasswordHash = passwordHash; - } - - /// - /// Generates an MD5 hash, which is used to verify the connections login information - /// - /// - /// The proof verification MD5 hash string that can be compared to what the _connection sends, - /// to verify that the users entered password matches the specific user data in the database. - /// - public static string GenerateProof(LoginChallengeProof data) - { - string tempUserData = data.UserData; - - // Login types NickEmail and AuthToken don't use partnerID append - if (data.PartnerID is not null) - { - if (data?.PartnerID != (int)GPPartnerID.Gamespy - && data?.LoginType != LoginType.AuthToken) - { - tempUserData = $@"{data.PartnerID}@{data.UserData}"; - } - } - - // Generate our response string - StringBuilder responseString = new StringBuilder(data.PasswordHash); - responseString.Append(' ', 48); // 48 spaces - responseString.Append(tempUserData); - responseString.Append(data.Challenge1); - responseString.Append(data.Challenge2); - responseString.Append(data.PasswordHash); - - string hashString = responseString.ToString().GetMD5Hash(); - - return hashString; - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Aggregate/Misc/SDKRevision.cs b/src/Servers/PresenceConnectionManager/src/Aggregate/Misc/SDKRevision.cs deleted file mode 100755 index fe94c084d..000000000 --- a/src/Servers/PresenceConnectionManager/src/Aggregate/Misc/SDKRevision.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Enumerate; - -namespace UniSpy.Server.PresenceConnectionManager.Aggregate.Misc -{ - public sealed class SdkRevision - { - public SdkRevisionType? SDKRevisionType { get; set; } - public bool IsSDKRevisionValid => SDKRevisionType == 0 ? false : true; - public bool IsSupportGPINewAuthNotification => (SDKRevisionType ^ Enumerate.SdkRevisionType.GPINewAuthNotification) != 0 ? true : false; - public bool IsSupportGPINewRevokeNotification => (SDKRevisionType ^ Enumerate.SdkRevisionType.GPINewRevokeNotification) != 0 ? true : false; - public bool IsSupportGPINewStatusNotification => (SDKRevisionType ^ Enumerate.SdkRevisionType.GPINewStatusNotification) != 0 ? true : false; - public bool IsSupportGPINewListRetrevalOnLogin => (SDKRevisionType ^ Enumerate.SdkRevisionType.GPINewListRetrevalOnLogin) != 0 ? true : false; - public bool IsSupportGPIRemoteAuthIDSNotification => (SDKRevisionType ^ Enumerate.SdkRevisionType.GPIRemoteAuthIDSNotification) != 0 ? true : false; - public bool IsSupportGPINewCDKeyRegistration => (SDKRevisionType ^ Enumerate.SdkRevisionType.GPINewCDKeyRegistration) != 0 ? true : false; - public SdkRevision() - { - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Aggregate/Misc/Status/UserStatus.cs b/src/Servers/PresenceConnectionManager/src/Aggregate/Misc/Status/UserStatus.cs deleted file mode 100755 index 6914d6659..000000000 --- a/src/Servers/PresenceConnectionManager/src/Aggregate/Misc/Status/UserStatus.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Enumerate; - -namespace UniSpy.Server.PresenceConnectionManager.Aggregate.Misc -{ - /// - /// This status class is for old SDK version - /// - public sealed class UserStatus - { - public GPStatusCode CurrentStatus { get; set; } - public string StatusString { get; set; } - public string LocationString { get; set; } - public UserStatus() - { - CurrentStatus = GPStatusCode.Offline; - StatusString = ""; - LocationString = ""; - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Aggregate/Misc/Status/UserStatusInfo.cs b/src/Servers/PresenceConnectionManager/src/Aggregate/Misc/Status/UserStatusInfo.cs deleted file mode 100755 index 1e5362d34..000000000 --- a/src/Servers/PresenceConnectionManager/src/Aggregate/Misc/Status/UserStatusInfo.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace UniSpy.Server.PresenceConnectionManager.Aggregate.Misc -{ - /// - /// This status info class is for new SDK version - /// - public sealed class UserStatusInfo - { - public string StatusState { get; set; } - public string BuddyIP { get; set; } - public string HostIP { get; set; } - public string HostPrivateIP { get; set; } - public int? QueryReportPort { get; set; } - public int? HostPort { get; set; } - public int? SessionFlags { get; set; } - public string RichStatus { get; set; } - public string GameType { get; set; } - public string GameVariant { get; set; } - public string GameMapName { get; set; } - public string QuietModeFlags { get; set; } - public UserStatusInfo() - { - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Aggregate/Redis/UserInfoRedisKey.cs b/src/Servers/PresenceConnectionManager/src/Aggregate/Redis/UserInfoRedisKey.cs deleted file mode 100755 index 21d84963e..000000000 --- a/src/Servers/PresenceConnectionManager/src/Aggregate/Redis/UserInfoRedisKey.cs +++ /dev/null @@ -1,17 +0,0 @@ -// using Newtonsoft.Json; -// using System; -// using UniSpy.Server.Core.Abstraction.BaseClass.Redis; - -// namespace UniSpy.Server.PresenceConnectionManager.Handler.SystemHandler.Redis -// { -// public sealed class UserInfoRedisKey : RedisKey -// { -// [JsonProperty(Order = -2)] -// public Guid ServerID { get; set; } -// public string SessionHashValue { get; set; } -// public UserInfoRedisKey() -// { -// Db = UniSpy.Server.Core.Extensions.DbNumber.GamePresence; -// } -// } -// } \ No newline at end of file diff --git a/src/Servers/PresenceConnectionManager/src/Aggregate/Redis/UserInfoRedisOperator.cs b/src/Servers/PresenceConnectionManager/src/Aggregate/Redis/UserInfoRedisOperator.cs deleted file mode 100755 index 8913ef0b3..000000000 --- a/src/Servers/PresenceConnectionManager/src/Aggregate/Redis/UserInfoRedisOperator.cs +++ /dev/null @@ -1,9 +0,0 @@ -// using UniSpy.Server.PresenceConnectionManager.Structure.Data; -// using UniSpy.Server.Core.Abstraction.BaseClass.Redis; - -// namespace UniSpy.Server.PresenceConnectionManager.Handler.SystemHandler.Redis -// { -// public sealed class UserInfoRedisOperator : UniSpyRedisOperator -// { -// } -// } diff --git a/src/Servers/PresenceConnectionManager/src/Application/Client.cs b/src/Servers/PresenceConnectionManager/src/Application/Client.cs deleted file mode 100644 index 78daaff2d..000000000 --- a/src/Servers/PresenceConnectionManager/src/Application/Client.cs +++ /dev/null @@ -1,38 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Enumerate; -using UniSpy.Server.PresenceConnectionManager.Handler; -using UniSpy.Server.PresenceConnectionManager.Structure; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Logging; -using UniSpy.Server.Core.Encryption; - -namespace UniSpy.Server.PresenceConnectionManager.Application -{ - public sealed class Client : ClientBase - { - public new ITcpConnection Connection => (ITcpConnection)base.Connection; - public new ClientInfo Info { get => (ClientInfo)base.Info; private set => base.Info = value; } - public Client(IConnection connection, IServer server) : base(connection, server) - { - Info = new ClientInfo(); - } - protected override void OnConnected() - { - base.OnConnected(); - // Only send the login challenge once - if (Info.LoginStat != LoginStatus.Connected) - { - Connection.Disconnect(); - // Throw the error - this.LogWarn("The server challenge has already been sent. Cannot send another login challenge."); - } - - Info.LoginStat = LoginStatus.Processing; - string sendingBuffer = $@"\lc\1\challenge\{LoginChallengeProof.ServerChallenge}\id\{1}\final\"; - this.LogNetworkSending(sendingBuffer); - Connection.Send(sendingBuffer); - } - - protected override ISwitcher CreateSwitcher(object buffer) => new CmdSwitcher(this, UniSpyEncoding.GetString((byte[])buffer)); - } -} \ No newline at end of file diff --git a/src/Servers/PresenceConnectionManager/src/Application/ClientInfo.cs b/src/Servers/PresenceConnectionManager/src/Application/ClientInfo.cs deleted file mode 100755 index e92f0652d..000000000 --- a/src/Servers/PresenceConnectionManager/src/Application/ClientInfo.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using UniSpy.Server.PresenceConnectionManager.Enumerate; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Database.DatabaseModel; -using UniSpy.Server.PresenceConnectionManager.Aggregate.Misc; - -namespace UniSpy.Server.PresenceConnectionManager.Application -{ - public sealed class ClientInfo : ClientInfoBase - { - public const ushort SessionKey = 1111; - public const string LoginTicket = "0000000000000000000000__"; - public DateTime CreatedTime { get; private set; } = DateTime.Now; - public Guid UserGuid { get; private set; } - public SdkRevision SdkRevision { get; private set; } = new SdkRevision(); - public UserStatus Status { get; set; } = new UserStatus(); - public UserStatusInfo StatusInfo { get; set; } - public LoginStatus LoginStat { get; set; } = LoginStatus.Connected; - public User UserInfo { get; set; } - public Subprofile SubProfileInfo { get; set; } - public Profile ProfileInfo { get; set; } - public ClientInfo() - { - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Application/ClientManager.cs b/src/Servers/PresenceConnectionManager/src/Application/ClientManager.cs deleted file mode 100644 index e6b49d016..000000000 --- a/src/Servers/PresenceConnectionManager/src/Application/ClientManager.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Linq; -using UniSpy.Server.Core.Abstraction.BaseClass; - -namespace UniSpy.Server.PresenceConnectionManager.Application -{ - public class ClientManager : ClientManagerBase - { - public static Client GetClient(int profileid, int? productid = null, int? namespaceId = null) - { - return (Client)ClientPool.Values.FirstOrDefault( - c => ((ClientInfo)c.Info).SubProfileInfo.ProductId == productid - && ((ClientInfo)c.Info).SubProfileInfo.ProfileId == profileid - && ((ClientInfo)c.Info).SubProfileInfo.NamespaceId == namespaceId); - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceConnectionManager/src/Application/Program.cs b/src/Servers/PresenceConnectionManager/src/Application/Program.cs deleted file mode 100755 index 93599634b..000000000 --- a/src/Servers/PresenceConnectionManager/src/Application/Program.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using UniSpy.Server.Core.Logging; - -namespace UniSpy.Server.PresenceConnectionManager.Application -{ - public class Program - { - static void Main(string[] args) - { - try - { - new ServerLauncher().Start(); - Console.WriteLine("Press < Q > to exit. "); - while (Console.ReadKey().Key != ConsoleKey.Q) { } - } - catch (System.Exception e) - { - LogWriter.LogError(e); - } - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceConnectionManager/src/Application/Server.cs b/src/Servers/PresenceConnectionManager/src/Application/Server.cs deleted file mode 100644 index 0f21664e8..000000000 --- a/src/Servers/PresenceConnectionManager/src/Application/Server.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Net; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Network.Tcp.Server; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.PresenceConnectionManager.Application -{ - public sealed class Server : ServerBase - { - static Server() - { - _name = "PresenceConnectionManager"; - } - public Server() { } - public Server(IConnectionManager manager) : base(manager) { } - protected override IClient CreateClient(IConnection connection) => new Client(connection, this); - protected override IConnectionManager CreateConnectionManager(IPEndPoint endPoint) => new TcpConnectionManager(IPEndPoint.Parse("0.0.0.0:29900")); - } -} \ No newline at end of file diff --git a/src/Servers/PresenceConnectionManager/src/Application/ServerLauncher.cs b/src/Servers/PresenceConnectionManager/src/Application/ServerLauncher.cs deleted file mode 100644 index 333f93dc1..000000000 --- a/src/Servers/PresenceConnectionManager/src/Application/ServerLauncher.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Core.Abstraction.BaseClass.Factory; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.PresenceConnectionManager.Application -{ - public sealed class ServerLauncher : ServerLauncherBase - { - protected override List LaunchNetworkService() => new List { new Server() }; - } -} \ No newline at end of file diff --git a/src/Servers/PresenceConnectionManager/src/Application/StorageOperation.cs b/src/Servers/PresenceConnectionManager/src/Application/StorageOperation.cs deleted file mode 100644 index fca286878..000000000 --- a/src/Servers/PresenceConnectionManager/src/Application/StorageOperation.cs +++ /dev/null @@ -1,283 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.Interface; -using UniSpy.Server.Core.Database.DatabaseModel; -using System.Linq; -using System.Collections.Generic; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; -using UniSpy.Server.PresenceSearchPlayer.Exception.Login; -using UniSpy.Server.PresenceConnectionManager.Contract.Result; - - -namespace UniSpy.Server.PresenceConnectionManager.Application -{ - internal sealed class StorageOperation : IStorageOperation - { - public static IStorageOperation Persistance = new StorageOperation(); - public bool IsEmailExist(string email) - { - using (var db = new UniSpyContext()) - { - var result = from u in db.Users - //According to FSW partnerid is not nessesary - where u.Email == email - select u.UserId; - - if (result.Count() == 0) - { - return false; - } - return true; - } - } - public void DeleteFriendByProfileId(int profileId, int targetId, int namespaceId) - { - using (var db = new UniSpyContext()) - { - var result = db.Friends.Where(f => f.ProfileId == profileId - && f.Targetid == targetId - && f.Namespaceid == namespaceId).FirstOrDefault(); - if (result is not null) - { - db.Friends.Remove(result); - } - else - { - throw new GPDatabaseException("More than one buddy found in database, please check database."); - } - } - } - - public List GetBlockedProfileIds(int profileId, int namespaceId) - { - using (var db = new UniSpyContext()) - { - return db.Blockeds.Where(f => f.ProfileId == profileId - && f.Namespaceid == namespaceId) - .Select(f => f.Targetid).ToList(); - } - - } - public List GetFriendProfileIds(int profileId, int namespaceId) - { - using (var db = new UniSpyContext()) - { - return db.Friends.Where(f => f.ProfileId == profileId - && f.Namespaceid == namespaceId).Select(f => f.Targetid).ToList(); - } - } - - public GetProfileDataModel GetProfileInfos(int profileId, int namespaceId) - { - using (var db = new UniSpyContext()) - { - //we have to make sure the search target has the same namespaceID - var result = from p in db.Profiles - join s in db.Subprofiles on p.ProfileId equals s.ProfileId - join u in db.Users on p.Userid equals u.UserId - where p.ProfileId == profileId - && s.NamespaceId == namespaceId - select new GetProfileDataModel - { - Nick = p.Nick, - ProfileId = p.ProfileId, - UniqueNick = s.Uniquenick, - Email = u.Email, - Firstname = p.Firstname, - Lastname = p.Lastname, - Icquin = p.Icquin, - Homepage = p.Homepage, - Zipcode = p.Zipcode, - Countrycode = p.Countrycode, - Longitude = p.Longitude, - Latitude = p.Latitude, - Location = p.Location, - Birthday = p.Birthday, - Birthmonth = p.Birthmonth, - Birthyear = p.Birthyear, - Sex = (byte)p.Sex, - Publicmask = p.Publicmask, - Aim = p.Aim, - Picture = p.Picture, - Occupationid = p.Occupationid, - Industryid = p.Industryid, - Incomeid = p.Incomeid, - Marriedid = p.Marriedid, - Childcount = p.Childcount, - Interests1 = p.Interests1, - Ownership1 = p.Ownership1, - Connectiontype = p.Connectiontype, - }; - - return result.FirstOrDefault(); - } - } - - public (User, Profile, Subprofile) GetUsersInfos(string email, string nickName) - { - using (var db = new UniSpyContext()) - { - var result = from u in db.Users - join p in db.Profiles on u.UserId equals p.Userid - join n in db.Subprofiles on p.ProfileId equals n.ProfileId - where u.Email == email - && p.Nick == nickName - select new { u, p, n }; - - var info = result.FirstOrDefault(); - if (info is null) - { - throw new GPLoginBadProfileException("email and nick dose not exist"); - } - return (info.u, info.p, info.n); - } - } - - public (User, Profile, Subprofile) GetUsersInfos(string uniqueNick, int namespaceId) - { - - using (var db = new UniSpyContext()) - { - var result = from n in db.Subprofiles - join p in db.Profiles on n.ProfileId equals p.ProfileId - join u in db.Users on p.Userid equals u.UserId - where n.Uniquenick == uniqueNick - && n.NamespaceId == namespaceId - select new { u, p, n }; - - var info = result.FirstOrDefault(); - if (info is null) - { - throw new GPLoginBadUniquenickException($"The uniquenick: {uniqueNick} is invalid."); - } - return (info.u, info.p, info.n); - } - } - - public (User, Profile, Subprofile) GetUsersInfos(string authToken, int partnerId, int namespaceId) - { - using (var db = new UniSpyContext()) - { - var result = from u in db.Users - join p in db.Profiles on u.UserId equals p.Userid - join n in db.Subprofiles on p.ProfileId equals n.ProfileId - where n.Authtoken == authToken - && n.PartnerId == partnerId - && n.NamespaceId == namespaceId - select new { u, p, n }; - - var info = result.FirstOrDefault(); - if (info is null) - { - throw new GPLoginBadPreAuthException("The pre-authentication token is invalid."); - } - return (info.u, info.p, info.n); - } - } - - public void UpdateBlockInfo(int targetId, int profileId, int namespaceId) - { - using (var db = new UniSpyContext()) - { - if (db.Blockeds.Where(b => b.Targetid == targetId - && b.Namespaceid == namespaceId - && b.ProfileId == profileId).Count() == 0) - { - Blocked blocked = new Blocked - { - ProfileId = profileId, - Targetid = targetId, - Namespaceid = namespaceId - }; - db.Blockeds.Update(blocked); - } - } - } - - public void UpdateFriendInfo(int targetId, int profileId, int namespaceId) - { - using (var db = new UniSpyContext()) - { - if (db.Friends.Where(b => b.Targetid == targetId - && b.Namespaceid == namespaceId - && b.ProfileId == profileId).Count() == 0) - { - Friend friend = new Friend - { - ProfileId = profileId, - Targetid = targetId, - Namespaceid = namespaceId - }; - db.Friends.Update(friend); - } - } - } - public void AddNickName(int userId, int profileId, string newNick) - { - using (var db = new UniSpyContext()) - { - - var profiles = new UniSpy.Server.Core.Database.DatabaseModel.Profile - { - ProfileId = profileId, - Nick = newNick, - Userid = userId - }; - - db.Add(profiles); - db.SaveChanges(); - } - } - public void UpdateNickName(int profileId, string oldNick, string newNick) - { - using (var db = new UniSpyContext()) - { - var result = from p in db.Profiles - where p.ProfileId == profileId - && p.Nick == oldNick - select p; - - if (result.Count() != 1) - { - throw new GPDatabaseException("No user infomation found in database."); - } - else - { - result.First().Nick = newNick; - } - - var profile = db.Profiles.Where(p => p.ProfileId == profileId - && p.Nick == oldNick).First(); - profile.Nick = newNick; - db.Profiles.Add(profile); - db.SaveChanges(); - } - } - - public void UpdateProfileInfo(Profile profile) - { - using (var db = new UniSpyContext()) - { - db.Update(profile); - db.SaveChanges(); - } - } - - public void UpdateUniqueNick(int subProfileId, string uniqueNick) - { - using (var db = new UniSpyContext()) - { - var result = db.Subprofiles.FirstOrDefault(s => s.SubProfileId == subProfileId); - result.Uniquenick = uniqueNick; - db.Subprofiles.Update(result); - db.SaveChanges(); - } - } - public void UpdateSubProfileInfo(Subprofile subprofile) - { - using (var db = new UniSpyContext()) - { - db.Subprofiles.Update(subprofile); - db.SaveChanges(); - } - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Request/Buddy/AddBuddyRequest.cs b/src/Servers/PresenceConnectionManager/src/Contract/Request/Buddy/AddBuddyRequest.cs deleted file mode 100755 index c722c9583..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Request/Buddy/AddBuddyRequest.cs +++ /dev/null @@ -1,35 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Request -{ - - public sealed class AddBuddyRequest : RequestBase - { - public int FriendProfileID { get; private set; } - public string Reason { get; private set; } - public AddBuddyRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - - - if (!RequestKeyValues.ContainsKey("sesskey") || !RequestKeyValues.ContainsKey("newprofileid") || !RequestKeyValues.ContainsKey("reason")) - { - throw new GPParseException("addbuddy request is invalid."); - } - - int friendPID; - if (!int.TryParse(RequestKeyValues["newprofileid"], out friendPID)) - { - throw new GPParseException("newprofileid format is incorrect."); - } - - FriendProfileID = friendPID; - Reason = RequestKeyValues["reason"]; - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Request/Buddy/DelBuddyRequest.cs b/src/Servers/PresenceConnectionManager/src/Contract/Request/Buddy/DelBuddyRequest.cs deleted file mode 100755 index c7f1b351b..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Request/Buddy/DelBuddyRequest.cs +++ /dev/null @@ -1,40 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Request -{ - /// - /// Delete a user from my friend list - /// - - public sealed class DelBuddyRequest : RequestBase - { - //\delbuddy\\sesskey\<>\delprofileid\<>\final\ - /// - /// The target friendId needs to delete - /// - /// - public int TargetId { get; private set; } - public DelBuddyRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - - if (!RequestKeyValues.ContainsKey("delprofileid")) - { - throw new GPParseException("delprofileid is missing."); - } - - int deleteProfileID; - if (!int.TryParse(RequestKeyValues["delprofileid"], out deleteProfileID)) - { - throw new GPParseException("delprofileid format is incorrect."); - } - - TargetId = deleteProfileID; - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Request/Buddy/InviteToRequest.cs b/src/Servers/PresenceConnectionManager/src/Contract/Request/Buddy/InviteToRequest.cs deleted file mode 100755 index 22423675a..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Request/Buddy/InviteToRequest.cs +++ /dev/null @@ -1,49 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Request -{ - /// - /// Invite a user to a room or a game - /// - - public sealed class InviteToRequest : RequestBase - { - public int ProductId { get; private set; } - public int ProfileId { get; private set; } - public InviteToRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - - if (!RequestKeyValues.ContainsKey("productid")) - { - throw new GPParseException("productid is missing."); - } - - if (!RequestKeyValues.ContainsKey("sesskey")) - { - throw new GPParseException("sesskey is missing."); - - } - - int productID; - if (!int.TryParse(RequestKeyValues["productid"], out productID)) - { - throw new GPParseException("productid format is incorrect."); - } - - ProductId = productID; - - int profileID; - if (!int.TryParse(RequestKeyValues["profileid"], out profileID)) - { - throw new GPParseException("profileid format is incorrect."); - } - ProfileId = profileID; - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Request/Buddy/StatusInfoRequest.cs b/src/Servers/PresenceConnectionManager/src/Contract/Request/Buddy/StatusInfoRequest.cs deleted file mode 100755 index d0ec395ae..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Request/Buddy/StatusInfoRequest.cs +++ /dev/null @@ -1,79 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Aggregate.Misc; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Request -{ - /// - /// Update a user's status information - /// - - public sealed class StatusInfoRequest : RequestBase - { - public bool IsGetStatusInfo { get; set; } - - #region Get buddy status info - public int ProfileId { get; set; } - public int? NamespaceID { get; set; } - #endregion - public UserStatusInfo StatusInfo { get; private set; } - - public StatusInfoRequest() - { - IsGetStatusInfo = true; - } - - public StatusInfoRequest(string rawRequest) : base(rawRequest) - { - IsGetStatusInfo = false; - } - - public override void Parse() - { - base.Parse(); - - if (!RequestKeyValues.ContainsKey("state") - || !RequestKeyValues.ContainsKey("hostIp") - || !RequestKeyValues.ContainsKey("hprivIp") - || !RequestKeyValues.ContainsKey("qport") - || !RequestKeyValues.ContainsKey("hport") - || !RequestKeyValues.ContainsKey("sessflags") - || !RequestKeyValues.ContainsKey("rechStatus") - || !RequestKeyValues.ContainsKey("gameType") - || !RequestKeyValues.ContainsKey("gameVariant") - || !RequestKeyValues.ContainsKey("gameMapName")) - { - throw new GPParseException("StatusInfo request is invalid."); - } - - StatusInfo.StatusState = RequestKeyValues["state"]; - StatusInfo.HostIP = RequestKeyValues["hostIp"]; - StatusInfo.HostPrivateIP = RequestKeyValues["hprivIp"]; - - int qport; - if (!int.TryParse(RequestKeyValues["qport"], out qport)) - { - throw new GPParseException("qport format is incorrect."); - } - StatusInfo.QueryReportPort = qport; - int hport; - if (int.TryParse(RequestKeyValues["hport"], out hport)) - { - throw new GPParseException("hport format is incorrect."); - } - StatusInfo.HostPort = hport; - - int sessflags; - if (!int.TryParse(RequestKeyValues["sessflags"], out sessflags)) - { - throw new GPParseException("sessflags format is incorrect."); - } - StatusInfo.SessionFlags = sessflags; - - StatusInfo.RichStatus = RequestKeyValues["rechStatus"]; - StatusInfo.GameType = RequestKeyValues["gameType"]; - StatusInfo.GameVariant = RequestKeyValues["gameVariant"]; - StatusInfo.GameMapName = RequestKeyValues["gameMapName"]; - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Request/Buddy/StatusRequest.cs b/src/Servers/PresenceConnectionManager/src/Contract/Request/Buddy/StatusRequest.cs deleted file mode 100755 index ec0206b40..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Request/Buddy/StatusRequest.cs +++ /dev/null @@ -1,46 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Aggregate.Misc; -using UniSpy.Server.PresenceConnectionManager.Enumerate; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Request -{ - /// - /// Update a user's status information - /// - - public sealed class StatusRequest : RequestBase - { - public UserStatus Status { get; private set; } - public bool IsGetStatus { get; set; } - public StatusRequest(string rawRequest) : base(rawRequest) - { - Status = new UserStatus(); - IsGetStatus = false; - } - - public override void Parse() - { - base.Parse(); - - if (!RequestKeyValues.ContainsKey("status")) - throw new GPParseException("status is missing."); - - if (!RequestKeyValues.ContainsKey("statstring")) - throw new GPParseException("statstring is missing."); - - if (!RequestKeyValues.ContainsKey("locstring")) - throw new GPParseException("locstring is missing."); - - int statusCode; - if (!int.TryParse(RequestKeyValues["status"], out statusCode)) - { - throw new GPParseException("status format is incorrect."); - } - - Status.CurrentStatus = (GPStatusCode)statusCode; - Status.LocationString = RequestKeyValues["locstring"]; - Status.StatusString = RequestKeyValues["statstring"]; - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Request/General/KeepAliveRequest.cs b/src/Servers/PresenceConnectionManager/src/Contract/Request/General/KeepAliveRequest.cs deleted file mode 100755 index 31c03bdca..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Request/General/KeepAliveRequest.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Request -{ - - public sealed class KeepAliveRequest : RequestBase - { - public KeepAliveRequest(string rawRequest) : base(rawRequest) - { - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Request/General/LoginRequest.cs b/src/Servers/PresenceConnectionManager/src/Contract/Request/General/LoginRequest.cs deleted file mode 100755 index 9e4d49d08..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Request/General/LoginRequest.cs +++ /dev/null @@ -1,184 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Enumerate; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Request -{ - - public sealed class LoginRequest : RequestBase - { - public string UserChallenge { get; private set; } - public string Response { get; private set; } - public string UniqueNick { get; private set; } - public string UserData { get; private set; } - public int? NamespaceID { get; private set; } - public string AuthToken { get; private set; } - public string Nick { get; private set; } - public string Email { get; private set; } - public int? ProductID { get; private set; } - public LoginType? Type { get; private set; } - public SdkRevisionType? SdkRevisionType { get; private set; } - - public LoginRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - - - if (!RequestKeyValues.ContainsKey("challenge")) - throw new GPParseException("challenge is missing"); - - if (!RequestKeyValues.ContainsKey("response")) - { - throw new GPParseException("response is missing"); - } - - UserChallenge = RequestKeyValues["challenge"]; - Response = RequestKeyValues["response"]; - - if (RequestKeyValues.ContainsKey("uniquenick") && RequestKeyValues.ContainsKey("namespaceid")) - { - int namespaceID; - if (!int.TryParse(RequestKeyValues["namespaceid"], out namespaceID)) - { - throw new GPParseException("namespaceid format is incorrect"); - } - Type = LoginType.UniquenickNamespaceID; - UniqueNick = RequestKeyValues["uniquenick"]; - UserData = UniqueNick; - NamespaceID = namespaceID; - } - else if (RequestKeyValues.ContainsKey("authtoken")) - { - Type = LoginType.AuthToken; - AuthToken = RequestKeyValues["authtoken"]; - UserData = AuthToken; - } - else if (RequestKeyValues.ContainsKey("user")) - { - Type = LoginType.NickEmail; - UserData = RequestKeyValues["user"]; - - int Pos = UserData.IndexOf('@'); - if (Pos == -1 || Pos < 1 || (Pos + 1) >= UserData.Length) - { - throw new GPParseException("user format is incorrect"); - } - Nick = UserData.Substring(0, Pos); - Email = UserData.Substring(Pos + 1); - - // we need to get namespaceid for email login - if (RequestKeyValues.ContainsKey("namespaceid")) - { - int namespaceID; - if (!int.TryParse(RequestKeyValues["namespaceid"], out namespaceID)) - { - throw new GPParseException("namespaceid format is incorrect"); - } - NamespaceID = namespaceID; - } - } - else - { - throw new GPParseException("Unknown login method detected."); - } - - ParseOtherData(); - } - - public int? GamePort { get; private set; } - public int? UserID { get; private set; } - public int? ProfileId { get; private set; } - public int? PartnerID { get; private set; } - public string GameName { get; private set; } - public QuietModeType? QuietModeFlags { get; private set; } - public string Firewall { get; private set; } - - private void ParseOtherData() - { - if (RequestKeyValues.ContainsKey("userid")) - { - int userID; - if (!int.TryParse(RequestKeyValues["userid"], out userID)) - { - throw new GPParseException("partnerid format is incorrect"); - } - UserID = userID; - - } - if (RequestKeyValues.ContainsKey("profileid")) - { - int profileID; - if (!int.TryParse(RequestKeyValues["profileid"], out profileID)) - { - throw new GPParseException("profileid format is incorrect"); - } - ProfileId = profileID; - } - if (RequestKeyValues.ContainsKey("partnerid")) - { - int partnerID; - if (!int.TryParse(RequestKeyValues["partnerid"], out partnerID)) - { - throw new GPParseException("partnerid format is incorrect"); - } - PartnerID = partnerID; - } - - //store sdkrevision - if (RequestKeyValues.ContainsKey("sdkrevision")) - { - int sdkRevisionType; - if (!int.TryParse(RequestKeyValues["sdkrevision"], out sdkRevisionType)) - { - throw new GPParseException("sdkrevision format is incorrect"); - } - - SdkRevisionType = (SdkRevisionType)sdkRevisionType; - } - - if (RequestKeyValues.ContainsKey("gamename")) - { - GameName = RequestKeyValues["gamename"]; - } - - if (RequestKeyValues.ContainsKey("port")) - { - int htonGamePort; - if (!int.TryParse(RequestKeyValues["port"], out htonGamePort)) - { - throw new GPParseException("port format is incorrect"); - } - GamePort = htonGamePort; - } - if (RequestKeyValues.ContainsKey("productid")) - { - int productID; - if (!int.TryParse(RequestKeyValues["productid"], out productID)) - { - throw new GPParseException("productid format is incorrect"); - } - ProductID = productID; - } - - if (RequestKeyValues.ContainsKey("firewall")) - { - Firewall = RequestKeyValues["firewall"]; - } - - if (RequestKeyValues.ContainsKey("quiet")) - { - int quiet; - if (!int.TryParse(RequestKeyValues["quiet"], out quiet)) - { - throw new GPParseException("quiet format is incorrect"); - } - - QuietModeFlags = (QuietModeType)quiet; - } - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Request/General/LogoutRequest.cs b/src/Servers/PresenceConnectionManager/src/Contract/Request/General/LogoutRequest.cs deleted file mode 100755 index 8e36d9f0d..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Request/General/LogoutRequest.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Request -{ - - public sealed class LogoutRequest : RequestBase - { - public LogoutRequest(string rawRequest) : base(rawRequest) - { - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Request/Profile/AddBlockRequest.cs b/src/Servers/PresenceConnectionManager/src/Contract/Request/Profile/AddBlockRequest.cs deleted file mode 100755 index 07d187cba..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Request/Profile/AddBlockRequest.cs +++ /dev/null @@ -1,34 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Request -{ - - public sealed class AddBlockRequest : RequestBase - { - public int TargetId; - public AddBlockRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - - if (!RequestKeyValues.ContainsKey("profileid")) - { - throw new GPParseException("profileid is missing"); - - } - - int profileID; - if (!int.TryParse(RequestKeyValues["profileid"], out profileID)) - { - throw new GPParseException("profileid format is incorrect"); - } - - TargetId = profileID; - - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Request/Profile/GetProfileRequest.cs b/src/Servers/PresenceConnectionManager/src/Contract/Request/Profile/GetProfileRequest.cs deleted file mode 100755 index 375dfb001..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Request/Profile/GetProfileRequest.cs +++ /dev/null @@ -1,38 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Request -{ - - public sealed class GetProfileRequest : RequestBase - { - public int ProfileId { get; private set; } - public string SessionKey { get; private set; } - public GetProfileRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - - if (!RequestKeyValues.ContainsKey("profileid")) - { - throw new GPParseException("profileid is missing"); - } - - int profileID; - if (!int.TryParse(RequestKeyValues["profileid"], out profileID)) - { - throw new GPParseException("profileid format is incorrect"); - } - ProfileId = profileID; - - if (!RequestKeyValues.ContainsKey("sesskey")) - { - throw new GPParseException("sesskey is missing"); - } - SessionKey = RequestKeyValues["sesskey"]; - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Request/Profile/NewProfileRequest.cs b/src/Servers/PresenceConnectionManager/src/Contract/Request/Profile/NewProfileRequest.cs deleted file mode 100755 index f8dd8ba58..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Request/Profile/NewProfileRequest.cs +++ /dev/null @@ -1,48 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Request -{ - - public sealed class NewProfileRequest : RequestBase - { - public NewProfileRequest(string rawRequest) : base(rawRequest) - { - } - - public bool IsReplaceNickName { get; private set; } - public string SessionKey { get; private set; } - public string NewNick { get; private set; } - public string OldNick { get; private set; } - public override void Parse() - { - base.Parse(); - - if (!RequestKeyValues.ContainsKey("sesskey")) - { - throw new GPParseException("sesskey is missing"); - } - SessionKey = RequestKeyValues["sesskey"]; - - if (RequestKeyValues.ContainsKey("replace")) - { - if (!RequestKeyValues.ContainsKey("oldnick") && !RequestKeyValues.ContainsKey("nick")) - { - throw new GPParseException("oldnick or nick is missing."); - } - OldNick = RequestKeyValues["oldnick"]; - NewNick = RequestKeyValues["nick"]; - IsReplaceNickName = true; - } - else - { - if (!RequestKeyValues.ContainsKey("nick")) - { - throw new GPParseException("nick is missing."); - } - NewNick = RequestKeyValues["nick"]; - IsReplaceNickName = false; - } - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Request/Profile/RegisterCDKeyRequest.cs b/src/Servers/PresenceConnectionManager/src/Contract/Request/Profile/RegisterCDKeyRequest.cs deleted file mode 100755 index 188b23d31..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Request/Profile/RegisterCDKeyRequest.cs +++ /dev/null @@ -1,32 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Request -{ - - public sealed class RegisterCDKeyRequest : RequestBase - { - public string SessionKey { get; private set; } - public string CDKeyEnc { get; private set; } - public RegisterCDKeyRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - - if (!RequestKeyValues.ContainsKey("sesskey")) - { - throw new GPParseException("sesskey is missing"); - } - SessionKey = RequestKeyValues["sesskey"]; - - if (!RequestKeyValues.ContainsKey("cdkeyenc")) - { - throw new GPParseException("cdkeyenc is missing"); - } - CDKeyEnc = RequestKeyValues["cdkeyenc"]; - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Request/Profile/RegisterNickRequest.cs b/src/Servers/PresenceConnectionManager/src/Contract/Request/Profile/RegisterNickRequest.cs deleted file mode 100755 index 6539e8776..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Request/Profile/RegisterNickRequest.cs +++ /dev/null @@ -1,44 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Request -{ - - public sealed class RegisterNickRequest : RequestBase - { - public string UniqueNick { get; private set; } - public string SessionKey { get; private set; } - public int PartnerId { get; private set; } - public RegisterNickRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - - if (!RequestKeyValues.ContainsKey("sesskey")) - { - throw new GPParseException("sesskey is missing"); - } - SessionKey = RequestKeyValues["sesskey"]; - - if (!RequestKeyValues.ContainsKey("uniquenick")) - { - throw new GPParseException("uniquenick is missing"); - } - UniqueNick = RequestKeyValues["uniquenick"]; - - // PartnerId is optional - if (RequestKeyValues.ContainsKey("partnerid")) - { - int partnerID; - if (!int.TryParse(RequestKeyValues["partnerid"], out partnerID)) - { - throw new GPParseException("partnerid is missing"); - } - PartnerId = partnerID; - } - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Request/Profile/UpdateProfileRequest.cs b/src/Servers/PresenceConnectionManager/src/Contract/Request/Profile/UpdateProfileRequest.cs deleted file mode 100755 index d2caa7215..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Request/Profile/UpdateProfileRequest.cs +++ /dev/null @@ -1,166 +0,0 @@ -using System; -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Enumerate; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; -using UniSpy.Server.Core.Misc; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Request -{ - - public sealed class UpdateProfileRequest : RequestBase - { - public UpdateProfileRequest(string rawRequest) : base(rawRequest) - { - } - - public bool HasPublicMaskFlag { get; private set; } - public PublicMasks PublicMask { get; private set; } - - public string SessionKey { get; private set; } - public int PartnerID { get; private set; } - public string Nick { get; private set; } - public string Uniquenick { get; private set; } - - public bool HasFirstNameFlag { get; private set; } - public string FirstName { get; private set; } - public bool HasLastNameFlag { get; private set; } - public string LastName { get; private set; } - - public bool HasICQFlag { get; private set; } - public int ICQUIN { get; private set; } - - public bool HasHomePageFlag { get; private set; } - public string HomePage { get; private set; } - - public bool HasBirthdayFlag { get; private set; } - public int BirthDay { get; private set; } - public ushort BirthMonth { get; private set; } - public ushort BirthYear { get; private set; } - - public bool HasSexFlag { get; private set; } - public byte Sex { get; private set; } - - public bool HasZipCode { get; private set; } - public string ZipCode { get; private set; } - - public bool HasCountryCode { get; private set; } - public string CountryCode { get; private set; } - - public override void Parse() - { - base.Parse(); - - if (RequestKeyValues.ContainsKey("publicmask")) - { - PublicMasks mask; - if (!Enum.TryParse(RequestKeyValues["publicmask"], out mask)) - { - throw new GPParseException("publicmask format is incorrect"); - } - HasPublicMaskFlag = true; - PublicMask = mask; - } - - if (!RequestKeyValues.ContainsKey("sesskey")) - { - throw new GPParseException("sesskey is missing"); - } - SessionKey = RequestKeyValues["sesskey"]; - - if (RequestKeyValues.ContainsKey("firstname")) - { - FirstName = RequestKeyValues["firstname"]; - HasFirstNameFlag = true; - } - - if (RequestKeyValues.ContainsKey("lastname")) - { - LastName = RequestKeyValues["lastname"]; - HasLastNameFlag = true; - } - - if (RequestKeyValues.ContainsKey("icquin")) - { - int icq; - if (!int.TryParse(RequestKeyValues["icquin"], out icq)) - { - throw new GPParseException("icquin format is incorrect"); - } - HasICQFlag = true; - ICQUIN = icq; - } - - - if (RequestKeyValues.ContainsKey("homepage")) - { - HasHomePageFlag = true; - HomePage = RequestKeyValues["homepage"]; - } - - if (RequestKeyValues.ContainsKey("birthday")) - { - int date; - - if (int.TryParse(RequestKeyValues["birthday"], out date)) - { - int d = ((date >> 24) & 0xFF); - ushort m = (ushort)((date >> 16) & 0xFF); - ushort y = (ushort)(date & 0xFFFF); - - if (GameSpyUtils.IsValidDate(d, m, y)) - { - BirthDay = d; - BirthMonth = m; - BirthYear = y; - } - } - } - if (RequestKeyValues.ContainsKey("sex")) - { - byte sex; - - if (!byte.TryParse(RequestKeyValues["sex"], out sex)) - { - throw new GPParseException("sex format is incorrect"); - } - HasSexFlag = true; - Sex = sex; - } - - if (RequestKeyValues.ContainsKey("zipcode")) - { - HasZipCode = true; - ZipCode = RequestKeyValues["zipcode"]; - } - - if (RequestKeyValues.ContainsKey("countrycode")) - { - HasCountryCode = true; - CountryCode = RequestKeyValues["countrycode"]; - } - - if (RequestKeyValues.ContainsKey("partnerid")) - { - int partnerid; - if (!int.TryParse(RequestKeyValues["partnerid"], out partnerid)) - { - throw new GPParseException("partnerid is incorrect"); - } - PartnerID = partnerid; - } - - if (RequestKeyValues.ContainsKey("nick")) - { - // throw new GPParseException("nickname is missing."); - Nick = RequestKeyValues["nick"]; - } - - if (RequestKeyValues.ContainsKey("uniquenick")) - { - // throw new GPParseException("uniquenick is missing."); - Uniquenick = RequestKeyValues["uniquenick"]; - } - } - } -} - diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Request/Profile/UpdateUIRequest.cs b/src/Servers/PresenceConnectionManager/src/Contract/Request/Profile/UpdateUIRequest.cs deleted file mode 100755 index 72b62160e..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Request/Profile/UpdateUIRequest.cs +++ /dev/null @@ -1,31 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Request -{ - - public sealed class UpdateUiRequest : RequestBase - { - public UpdateUiRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - - if (RequestKeyValues.ContainsKey("")) - { - - } - //cpubrandid - //cpuspeed - //memory - //videocard1ram - //videocard2ram - //connectionid - //connectionspeed - //hasnetwork - //pic - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Response/Buddy/AddBuddyResponse.cs b/src/Servers/PresenceConnectionManager/src/Contract/Response/Buddy/AddBuddyResponse.cs deleted file mode 100755 index 00eba9d24..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Response/Buddy/AddBuddyResponse.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Contract.Request; -using UniSpy.Server.PresenceConnectionManager.Contract.Result; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Response -{ - public sealed class AddBuddyResponse : ResponseBase - { - private new AddBuddyRequest _request => (AddBuddyRequest)base._request; - private new AddBuddyResult _result => (AddBuddyResult)base._result; - public AddBuddyResponse(AddBuddyRequest request, AddBuddyResult result) : base(request, result) - { - } - - public override void Build() - { - // \bm\\f\\date\ - // GPI_BM_MESSAGE: \msg\\ - // GPI_BM_UTM:\msg\\ - // GPI_BM_REQUEST:\msg\|signed|\ - // GPI_BM_AUTH: - // GPI_BM_REVOKE: - // GPI_BM_STATUS:\msg\|s|\ or \msg\|ss||ls||ip||p||qm| - // GPI_BM_INVITE:\msg\|p||l| - // GPI_BM_PING:\msg\\ - throw new NotImplementedException(); - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Response/Buddy/BlockListResponse.cs b/src/Servers/PresenceConnectionManager/src/Contract/Response/Buddy/BlockListResponse.cs deleted file mode 100755 index 2f1812175..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Response/Buddy/BlockListResponse.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Linq; -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Contract.Result; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Response -{ - public sealed class BlockListResponse : ResponseBase - { - private new BlockListResult _result => (BlockListResult)base._result; - - public BlockListResponse(RequestBase request, BlockListResult result) : base(request, result) - { - } - - public override void Build() - { - // \blk\< num in list >\list\< profileid list - comma delimited >\final\ - SendingBuffer = $@"\blk\{_result.ProfileIdList.Count()}\list\"; - foreach (var pid in _result.ProfileIdList) - { - SendingBuffer += $@"{pid}"; - if (pid != _result.ProfileIdList.Last()) - { - SendingBuffer += ","; - } - } - SendingBuffer += @"\final\"; - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Response/Buddy/BuddyListResponse.cs b/src/Servers/PresenceConnectionManager/src/Contract/Response/Buddy/BuddyListResponse.cs deleted file mode 100755 index e71fcc570..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Response/Buddy/BuddyListResponse.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Linq; -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Contract.Result; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Response -{ - public sealed class BuddyListResponse : ResponseBase - { - private new BuddyListResult _result => (BuddyListResult)base._result; - public BuddyListResponse(RequestBase request, BuddyListResult result) : base(request, result) - { - } - public override void Build() - { - // \bdy\< num in list >\list\< profileid list - comma delimited >\final\ - SendingBuffer = $@"\bdy\{_result.ProfileIDList.Count()}\list\"; - foreach (var pid in _result.ProfileIDList) - { - SendingBuffer += $@"{pid}"; - if (pid != _result.ProfileIDList.Last()) - { - SendingBuffer += ","; - } - } - SendingBuffer += @"\final\"; - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Response/Buddy/StatusInfoResponse.cs b/src/Servers/PresenceConnectionManager/src/Contract/Response/Buddy/StatusInfoResponse.cs deleted file mode 100755 index 0343e26fb..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Response/Buddy/StatusInfoResponse.cs +++ /dev/null @@ -1,29 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Contract.Result; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Response -{ - public sealed class StatusInfoResponse : ResponseBase - { - private new StatusInfoResult _result => (StatusInfoResult)base._result; - - public StatusInfoResponse(RequestBase request, StatusInfoResult result) : base(request, result) - { - } - /// - /// \bsi\\state\\profile\\bip\\bport\\hostip\\hprivip\\qport\\hport\\sessflags\\rstatus\\ - /// gameType\\gameVnt\\gameMn\\product\\qmodeflags\ - /// - public override void Build() - { - SendingBuffer = $@"bsi\\state\{_result.StatusInfo.StatusState}\ - profile\{_result.ProfileId}\bip\{_result.StatusInfo.BuddyIP} - hostIp\{_result.StatusInfo}\ - hprivIp\{_result.StatusInfo.HostPrivateIP}\qport\{_result.StatusInfo.QueryReportPort}\ - hport\{_result.StatusInfo.HostPort}\sessflags\{_result.StatusInfo.SessionFlags}\ - rstatus\{_result.StatusInfo.RichStatus}\gameType\{_result.StatusInfo.GameType}\ - gameVnt\{_result.StatusInfo.GameVariant}\gameMn\{_result.StatusInfo.GameMapName}\ - product\{_result.ProductId}\qmodeflags\{_result.StatusInfo.QuietModeFlags}final\"; - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Response/General/KeepAliveResponse.cs b/src/Servers/PresenceConnectionManager/src/Contract/Response/General/KeepAliveResponse.cs deleted file mode 100755 index f711576de..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Response/General/KeepAliveResponse.cs +++ /dev/null @@ -1,16 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Response -{ - public sealed class KeepAliveResponse : ResponseBase - { - public KeepAliveResponse(RequestBase request, ResultBase result) : base(request, result) - { - } - - public override void Build() - { - SendingBuffer = @"\ka\\final\"; - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Response/General/LoginResponse.cs b/src/Servers/PresenceConnectionManager/src/Contract/Response/General/LoginResponse.cs deleted file mode 100755 index c2d00174c..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Response/General/LoginResponse.cs +++ /dev/null @@ -1,36 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Application; -using UniSpy.Server.PresenceConnectionManager.Enumerate; -using UniSpy.Server.PresenceConnectionManager.Contract.Request; -using UniSpy.Server.PresenceConnectionManager.Contract.Result; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Response -{ - public sealed class LoginResponse : ResponseBase - { - private new LoginRequest _request => (LoginRequest)base._request; - private new LoginResult _result => (LoginResult)base._result; - public LoginResponse(LoginRequest request, LoginResult result) : base(request, result) - { - } - - public override void Build() - { - //string checkSumStr = _result.DatabaseResults.Nick + _result.DatabaseResults.UniqueNick + _result.DatabaseResults.NamespaceID; - - //_connection.UserData.SessionKey = _crc.ComputeChecksum(checkSumStr); - - SendingBuffer = @"\lc\2\sesskey\" + ClientInfo.SessionKey; - SendingBuffer += @"\proof\" + _result.ResponseProof; - SendingBuffer += @"\userid\" + _result.DatabaseResults.UserId; - SendingBuffer += @"\profileid\" + _result.DatabaseResults.ProfileId; - - if (_request.Type != LoginType.NickEmail) - { - SendingBuffer += @"\uniquenick\" + _result.DatabaseResults.UniqueNick; - } - SendingBuffer += $@"\lt\{ClientInfo.LoginTicket}"; - SendingBuffer += $@"\id\{_request.OperationID}\final\"; - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Response/General/NewUserResponse.cs b/src/Servers/PresenceConnectionManager/src/Contract/Response/General/NewUserResponse.cs deleted file mode 100755 index 88b35106d..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Response/General/NewUserResponse.cs +++ /dev/null @@ -1,17 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Contract.Request; -using UniSpy.Server.PresenceSearchPlayer.Contract.Result; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Response -{ - public sealed class NewUserResponse : PresenceSearchPlayer.Contract.Response.NewUserResponse - { - public NewUserResponse(NewUserRequest request, NewUserResult result) : base(request, result) - { - } - - public override void Build() - { - SendingBuffer = $@"\nur\\userid\{_result.User.UserId}\profileid\{_result.SubProfile.ProfileId}\id\{_request.OperationID}\final\"; - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Response/Profile/GetProfileResponse.cs b/src/Servers/PresenceConnectionManager/src/Contract/Response/Profile/GetProfileResponse.cs deleted file mode 100755 index 22165e43f..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Response/Profile/GetProfileResponse.cs +++ /dev/null @@ -1,50 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Contract.Result; -using UniSpy.Server.Core.Misc; -using UniSpy.Server.PresenceConnectionManager.Contract.Request; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Response -{ - public sealed class GetProfileResponse : ResponseBase - { - private new GetProfileResult _result => (GetProfileResult)base._result; - public GetProfileResponse(GetProfileRequest request, GetProfileResult result) : base(request, result) - { - } - public override void Build() - { - SendingBuffer = @"\pi\\profileid\" + _result.UserProfile.ProfileId; - SendingBuffer += @"\nick\" + _result.UserProfile.Nick; - SendingBuffer += @"\uniquenick\" + _result.UserProfile.UniqueNick; - SendingBuffer += @"\email\" + _result.UserProfile.Email; - SendingBuffer += @"\firstname\" + _result.UserProfile.Firstname; - SendingBuffer += @"\lastname\" + _result.UserProfile.Lastname; - SendingBuffer += @"\icquin\" + _result.UserProfile.Icquin; - SendingBuffer += @"\homepage\" + _result.UserProfile.Homepage; - SendingBuffer += @"\zipcode\" + _result.UserProfile.Zipcode; - SendingBuffer += @"\countrycode\" + _result.UserProfile.Countrycode; - SendingBuffer += @"\lon\" + _result.UserProfile.Longitude; - SendingBuffer += @"\lat\" + _result.UserProfile.Longitude; - SendingBuffer += @"\loc\" + _result.UserProfile.Location; - - int birthStr = (int)_result.UserProfile.Birthday << 24 | (int)_result.UserProfile.Birthmonth << 16 | (int)_result.UserProfile.Birthyear; - - SendingBuffer += @"\birthday\" + birthStr; - SendingBuffer += @"\sex\" + _result.UserProfile.Sex; - SendingBuffer += @"\publicmask\" + _result.UserProfile.Publicmask; - SendingBuffer += @"\aim\" + _result.UserProfile.Aim; - SendingBuffer += @"\picture\" + _result.UserProfile.Picture; - SendingBuffer += @"\ooc" + _result.UserProfile.Occupationid; - SendingBuffer += @"\ind\" + _result.UserProfile.Industryid; - SendingBuffer += @"\inc\" + _result.UserProfile.Incomeid; - SendingBuffer += @"\mar\" + _result.UserProfile.Marriedid; - SendingBuffer += @"\chc\" + _result.UserProfile.Childcount; - SendingBuffer += @"\i1\" + _result.UserProfile.Interests1; - SendingBuffer += @"\o1\" + _result.UserProfile.Ownership1; - SendingBuffer += @"\conn\" + _result.UserProfile.Connectiontype; - // SUPER NOTE: Please check the Signature of the PID, otherwise when it will be compared with other peers, it will break everything (See gpiPeer.c @ peerSig) - SendingBuffer += @"\sig\+" + GameSpyRandom.GenerateRandomString(10, GameSpyRandom.StringType.Hex); - SendingBuffer += @"\id\" + _request.OperationID + @"\final\"; - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Response/Profile/NewProfileResponse.cs b/src/Servers/PresenceConnectionManager/src/Contract/Response/Profile/NewProfileResponse.cs deleted file mode 100755 index 38dd67128..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Response/Profile/NewProfileResponse.cs +++ /dev/null @@ -1,16 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Response -{ - public sealed class NewProfileResponse : ResponseBase - { - public NewProfileResponse(RequestBase request, ResultBase result) : base(request, result) - { - } - - public override void Build() - { - SendingBuffer = $@"\npr\\profileid\{SendingBuffer}\id\{_request.OperationID}\final\"; - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Response/Profile/RegisterCDKeyResponse.cs b/src/Servers/PresenceConnectionManager/src/Contract/Response/Profile/RegisterCDKeyResponse.cs deleted file mode 100755 index 74865f934..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Response/Profile/RegisterCDKeyResponse.cs +++ /dev/null @@ -1,16 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Response -{ - public sealed class RegisterCDKeyResponse : ResponseBase - { - public RegisterCDKeyResponse(RequestBase request, ResultBase result) : base(request, result) - { - } - - public override void Build() - { - SendingBuffer = @"\rc\\final\"; - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Response/Profile/RegisterNickResponse.cs b/src/Servers/PresenceConnectionManager/src/Contract/Response/Profile/RegisterNickResponse.cs deleted file mode 100755 index b4de59ba4..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Response/Profile/RegisterNickResponse.cs +++ /dev/null @@ -1,16 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Response -{ - public sealed class RegisterNickResponse : ResponseBase - { - public RegisterNickResponse(RequestBase request, ResultBase result) : base(request, result) - { - } - - public override void Build() - { - SendingBuffer = $@"\rn\\id\{_request.OperationID}\final\"; - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Result/Buddy/AddBuddyResult.cs b/src/Servers/PresenceConnectionManager/src/Contract/Result/Buddy/AddBuddyResult.cs deleted file mode 100755 index 98be80050..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Result/Buddy/AddBuddyResult.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Result -{ - public sealed class AddBuddyResult : ResultBase - { - public AddBuddyResult() - { - } - - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Result/Buddy/BlockListResult.cs b/src/Servers/PresenceConnectionManager/src/Contract/Result/Buddy/BlockListResult.cs deleted file mode 100755 index 0cc395c6b..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Result/Buddy/BlockListResult.cs +++ /dev/null @@ -1,14 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using System.Collections.Generic; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Result -{ - public sealed class BlockListResult : ResultBase - { - public List ProfileIdList; - - public BlockListResult() - { - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Result/Buddy/BuddyListResult.cs b/src/Servers/PresenceConnectionManager/src/Contract/Result/Buddy/BuddyListResult.cs deleted file mode 100755 index 47c39a09d..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Result/Buddy/BuddyListResult.cs +++ /dev/null @@ -1,14 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using System.Collections.Generic; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Result -{ - public sealed class BuddyListResult : ResultBase - { - public List ProfileIDList { get; set; } - - public BuddyListResult() - { - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Result/Buddy/StatusInfoResult.cs b/src/Servers/PresenceConnectionManager/src/Contract/Result/Buddy/StatusInfoResult.cs deleted file mode 100755 index 5954dec06..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Result/Buddy/StatusInfoResult.cs +++ /dev/null @@ -1,15 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Aggregate.Misc; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Result -{ - public sealed class StatusInfoResult : ResultBase - { - public int ProfileId { get; set; } - public int ProductId { get; set; } - public UserStatusInfo StatusInfo { get; set; } - public StatusInfoResult() - { - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Result/Buddy/StatusResult.cs b/src/Servers/PresenceConnectionManager/src/Contract/Result/Buddy/StatusResult.cs deleted file mode 100755 index 6c1948087..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Result/Buddy/StatusResult.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Aggregate.Misc; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Result -{ - public sealed class StatusResult : ResultBase - { - public UserStatus Status { get; set; } - public StatusResult() - { - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Result/General/LoginResult.cs b/src/Servers/PresenceConnectionManager/src/Contract/Result/General/LoginResult.cs deleted file mode 100755 index d4a76d6d1..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Result/General/LoginResult.cs +++ /dev/null @@ -1,27 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Result -{ - public sealed class LogInDataModel - { - public int UserId; - public int ProfileId; - public string Nick; - public string Email; - public string UniqueNick; - public string PasswordHash; - public bool EmailVerifiedFlag; - public bool BannedFlag; - public int NamespaceId; - public int SubProfileId; - } - - public sealed class LoginResult : ResultBase - { - public LogInDataModel DatabaseResults { get; set; } - public string ResponseProof { get; set; } - public LoginResult() - { - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Result/PCMDefaultResult.cs b/src/Servers/PresenceConnectionManager/src/Contract/Result/PCMDefaultResult.cs deleted file mode 100755 index 232faaca1..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Result/PCMDefaultResult.cs +++ /dev/null @@ -1,11 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Result -{ - public sealed class PCMDefaultResult : ResultBase - { - public PCMDefaultResult() - { - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Result/Profile/GetProfileResult.cs b/src/Servers/PresenceConnectionManager/src/Contract/Result/Profile/GetProfileResult.cs deleted file mode 100755 index 49aa382a1..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Result/Profile/GetProfileResult.cs +++ /dev/null @@ -1,44 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Result -{ - public sealed class GetProfileDataModel - { - public string Nick; - public int ProfileId; - public string UniqueNick; - public string Email; - public string Firstname; - public string Lastname; - public int? Icquin; - public string Homepage; - public string Zipcode; - public string Countrycode; - public double? Longitude; - public double? Latitude; - public string Location; - public int? Birthday; - public int? Birthmonth; - public int? Birthyear; - public byte? Sex; - public int? Publicmask; - public string Aim; - public int? Picture; - public int? Occupationid; - public int? Industryid; - public int? Incomeid; - public int? Marriedid; - public int? Childcount; - public int? Interests1; - public int? Ownership1; - public int? Connectiontype; - - } - public sealed class GetProfileResult : ResultBase - { - public GetProfileDataModel UserProfile; - public GetProfileResult() - { - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Contract/Result/Profile/NewProfileResult.cs b/src/Servers/PresenceConnectionManager/src/Contract/Result/Profile/NewProfileResult.cs deleted file mode 100755 index 669292841..000000000 --- a/src/Servers/PresenceConnectionManager/src/Contract/Result/Profile/NewProfileResult.cs +++ /dev/null @@ -1,14 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; - -namespace UniSpy.Server.PresenceConnectionManager.Contract.Result -{ - public sealed class NewProfileResult : ResultBase - { - public int ProfileId; - - public NewProfileResult() - { - } - - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Dockerfile b/src/Servers/PresenceConnectionManager/src/Dockerfile deleted file mode 100755 index 1c8a93f5c..000000000 --- a/src/Servers/PresenceConnectionManager/src/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM mcr.microsoft.com/dotnet/runtime:6.0 AS base -WORKDIR /app -EXPOSE 29900 - -FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build -WORKDIR /src -COPY ["src/Servers/PresenceConnectionManager/src/UniSpy.Server.PresenceConnectionManager.csproj", "src/Servers/PresenceConnectionManager/src/"] -COPY ["src/Libraries/Core/src/UniSpy.Server.Core.csproj", "src/Libraries/Core/src/"] -COPY ["src/Servers/PresenceSearchPlayer/src/UniSpy.Server.PresenceSearchPlayer.csproj", "src/Servers/PresenceSearchPlayer/src/"] -RUN dotnet restore "src/Servers/PresenceConnectionManager/src/UniSpy.Server.PresenceConnectionManager.csproj" -COPY . . -WORKDIR "/src/src/Servers/PresenceConnectionManager/src" -RUN dotnet build "UniSpy.Server.PresenceConnectionManager.csproj" -c Release -o /app/build - -FROM build AS publish -RUN dotnet publish "UniSpy.Server.PresenceConnectionManager.csproj" -c Release -o /app/publish - -FROM base AS final -WORKDIR /app -COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "UniSpy.Server.PresenceConnectionManager.dll"] \ No newline at end of file diff --git a/src/Servers/PresenceConnectionManager/src/Enumerate/BuddyMessageType.cs b/src/Servers/PresenceConnectionManager/src/Enumerate/BuddyMessageType.cs deleted file mode 100755 index d45d48f9f..000000000 --- a/src/Servers/PresenceConnectionManager/src/Enumerate/BuddyMessageType.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace UniSpy.Server.PresenceConnectionManager.Enumerate -{ - public enum BuddyMessageType - { - #region response - //BM status - BmMessage = 1, - BmRquest = 2, - BmReply = 3, // only used on the backend - BmAuth = 4, - BmUTM = 5, - BmRevoke = 6, // remote buddy removed from local list - BmStatus = 100, - BmInvite = 101, - BmPing = 102, - #endregion - #region request - BmPong = 103, - BmKeysRequest = 104, - BmKeysReply = 105, - BmFileSendRequest = 200, - BmFileSendReply = 201, - BmFileBegin = 202, - BmFileEnd = 203, - BmFileData = 204, - BmFile_SKIP = 205, - BmFileTransferThrottle = 206, - BmFileTransferCancel = 207, - BmFileTransferKeepAlive = 208, - #endregion - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Enumerate/DisconnectReason.cs b/src/Servers/PresenceConnectionManager/src/Enumerate/DisconnectReason.cs deleted file mode 100755 index 57fd1ceb0..000000000 --- a/src/Servers/PresenceConnectionManager/src/Enumerate/DisconnectReason.cs +++ /dev/null @@ -1,91 +0,0 @@ -namespace UniSpy.Server.PresenceConnectionManager.Enumerate -{ - public enum DisconnectReason : int - { - /// - /// Client sends the "logout" command - /// - NormalLogout, - - /// - /// Keep Alive Packet failed to send (may not work with new async socket code) - /// - KeepAliveFailed, - - /// - /// The client failed to complete the login 15 seconds after creating the connection - /// - LoginTimedOut, - - /// - /// The username sent by the client does not exist - /// - InvalidUsername, - - /// - /// The provided password for the player nick is incorrect - /// - InvalidPassword, - - /// - /// Invalid login query sent by client - /// - InvalidLoginQuery, - - /// - /// Create player failed, username exists already - /// - CreateFailedUsernameExists, - - /// - /// Failed to create new player account due to a database exception - /// - CreateFailedDatabaseError, - - /// - /// A general login failure (check error log) - /// - GeneralError, - - /// - /// The stream disconnected unexpectedly. This can happen if the user clicks the - /// "Quit" button on the top of the main menu instead of the "Logout" button. - /// - Disconnected, - - /// - /// The player was forcefully logged out by console command - /// - ForcedLogout, - - /// - /// A new login detected with the old player _connection still logged in - /// - NewLoginDetected, - - /// - /// Forced server shutdown - /// - ForcedServerShutdown, - - /// - /// The client challenge was already sent by the server for this connection - /// - ClientChallengeAlreadySent, - - /// - /// The player is banned and cannot login - /// - PlayerIsBanned, - - /// - /// The player information is not valid - /// - InvalidPlayer, - - /// - /// The player account is not activated - /// - PlayerIsNotActivated - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Enumerate/FireWallType.cs b/src/Servers/PresenceConnectionManager/src/Enumerate/FireWallType.cs deleted file mode 100755 index f62592725..000000000 --- a/src/Servers/PresenceConnectionManager/src/Enumerate/FireWallType.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace UniSpy.Server.PresenceConnectionManager.Enumerate -{ - public enum FireWallType - { - // Firewall - /////////// - Firewall = 1, - NoFirewall = 0, - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Enumerate/GPBasic.cs b/src/Servers/PresenceConnectionManager/src/Enumerate/GPBasic.cs deleted file mode 100755 index 043eeca46..000000000 --- a/src/Servers/PresenceConnectionManager/src/Enumerate/GPBasic.cs +++ /dev/null @@ -1,201 +0,0 @@ -namespace UniSpy.Server.PresenceConnectionManager.Enumerate -{ - public enum GPBasic : uint - { - // Global States. - ///////////////// - InfoCaching = 0x0100, - Simulation, - InfoChachingBuddyAndBlockOnly, - - // Blocking - /////////// - Blocking = 1, - NonBlocking = 0, - - // Firewall - /////////// - Firewall = 1, - NoFirewall = 0, - - // Check Cache - ////////////// - CheckCache = 1, - DontCheckCache = 0, - - // Is Valid Email. - // PANTS|02.15.00 - ////////////////// - EmailValid = 1, - EmailInvalid = 0, - - // Fatal Error. - /////////////// - Fatal = 1, - NonFatal = 0, - - // Sex - ////// - Male = 0x0500, - Fefamle, - PAT, - - // Profile Search. - ////////////////// - More = 0x0600, - Done, - - // Set Info - /////////// - Nick = 0x0700, - Uniquenick, - Email, - Password, - FirstName, - LastName, - ICQUIN, - HomePage, - ZIPCode, - CountryCode, - Birthday, - Sex, - CPUBrand, - CPUSpeed, - Memory, - VideoCard1String, - VideoCard1RAM, - VideoCard2String, - VideoCard2RAM, - ConnectionID, - ConnectionSpeed, - HasNetwork, - OSString, - AIMName, // PANTS|03.20.01 - PIC, - OccupationID, - IndustryID, - InComeID, - MarriedID, - ChildCount, - Interest1, - - // New Profile. - /////////////// - Replace = 1, - DontReplace = 0, - - // Is Connected. - //////////////// - Connected = 1, - NotConnected = 0, - - // Public mask. - /////////////// - MaskNone = 0x00000000, - MaskHomepage = 0x00000001, - MaskZIPCode = 0x00000002, - MaskContryCode = 0x00000004, - MaskBirthday = 0x00000008, - MaskSex = 0x00000010, - MaskEmail = 0x00000020, - MaskAll = 0xFFFFFFFF, - - // Session flags - ///////////////// - SessIsClosed = 0x00000001, - SessIsOpen = 0x00000002, - SessHasPassword = 0x00000004, - SessIsBehindNAT = 0x00000008, - SessIsRanked = 0x000000010, - - // CPU Brand ID - /////////////// - Intel = 1, - AMD, - CYRIX, - Motorola, - Alpha, - - // Connection ID. - ///////////////// - Modem = 1, - ISDN, - CableModem, - DSL, - Satellite, - Ethernet, - Wireless, - - // Transfer callback type. - // *** the transfer is ended when these types are received - ////////////////////////// - TransferSendRequest = 0x800, // arg->num == numFiles - TransferAccepted, - TransferRejected, // *** - TransferNotAccepting, // *** - TransferNoConnection, // *** - TransferDone, // *** - TransferCancelled, // *** - TransferLostConnection, // *** - TransferError, // *** - TransferThrottle, // arg->num == Bps - FileBegin, - FileProgress, // arg->num == numBytes - FileEnd, - FileDirectory, - FileSkip, - FileFaild, // arg->num == error - - //FILE_FAILED error - /////////////////////// - FileReadError = 0x900, - FileWriteError, - FileDataError, - - // Transfer Side. - ///////////////// - TransferSender = 0xA00, - TansferReciever, - - // UTM send options. - //////////////////// - DontRout = 0xB00, // only send direct - - // Quiet mode flags. - //////////////////// - SlienceNone = 0x00000000, - SlienceMessage = 0x00000001, - SlienceUTMS = 0x00000002, - SlienceList = 0x00000004, // includes requests, auths, and revokes - SlienceAll = 0xFFFFFFFF, - - NewStatusInfoSupported = 0xC00, - NewStatusInfoNotSupported = 0xC01, - } - - /// - /// This enum represents the known Partner IDs, This value is set to 0 when - /// a game is directly connecting to GameSpy, otherwise the Partner ID would be - /// different for any service that uses GameSpy as backend (for example Nintendo - /// Wifi Connection). - /// - public enum GPPartnerID : int - { - /// - /// The client is directly connecting to the Server - /// - Gamespy = 0, - - // Unknown Partner ID from 1 to 9 - // EA partner ID should range here, it was - - /// - /// Unknown usage for this partner id, but it exists in the - /// GameSpy SDK - /// - IGN = 10, - //Nintendo = 11, // Please verify this - } - - -} diff --git a/src/Servers/PresenceConnectionManager/src/Enumerate/GPStatusCode.cs b/src/Servers/PresenceConnectionManager/src/Enumerate/GPStatusCode.cs deleted file mode 100755 index ac52e663f..000000000 --- a/src/Servers/PresenceConnectionManager/src/Enumerate/GPStatusCode.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace UniSpy.Server.PresenceConnectionManager.Enumerate -{ - public enum GPStatusCode - { - // Status - ///////// - Offline = 0, - Online = 1, - Playing = 2, - Staging = 3, - Chatting = 4, - Away = 5, - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Enumerate/GenderType.cs b/src/Servers/PresenceConnectionManager/src/Enumerate/GenderType.cs deleted file mode 100755 index 4f727934e..000000000 --- a/src/Servers/PresenceConnectionManager/src/Enumerate/GenderType.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace UniSpy.Server.PresenceConnectionManager.Enumerate -{ - public enum GenderType : ushort - { - /// - /// Gender is male - /// - Male, - - /// - /// Gender is female - /// - Female, - - /// - /// Unspecified or unknown gender, this is - /// used to mask the gender when the information is queried - /// - Pat - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Enumerate/LoginStatus.cs b/src/Servers/PresenceConnectionManager/src/Enumerate/LoginStatus.cs deleted file mode 100755 index 7bfb2a2fe..000000000 --- a/src/Servers/PresenceConnectionManager/src/Enumerate/LoginStatus.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace UniSpy.Server.PresenceConnectionManager.Enumerate -{ - public enum LoginStatus - { - Connected, - Processing, - Completed, - Disconnected - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Enumerate/LoginType.cs b/src/Servers/PresenceConnectionManager/src/Enumerate/LoginType.cs deleted file mode 100755 index aa7eea2da..000000000 --- a/src/Servers/PresenceConnectionManager/src/Enumerate/LoginType.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace UniSpy.Server.PresenceConnectionManager.Enumerate -{ - /// - /// This enumation defins the supported login method for the users. - /// - public enum LoginType : int - { - /// - /// Login with user combo (nick@email) - /// - NickEmail, - - /// - /// Login with unique nickname - /// - UniquenickNamespaceID, - - /// - /// Pre-authenticated login - /// - AuthToken - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Enumerate/PublicMask.cs b/src/Servers/PresenceConnectionManager/src/Enumerate/PublicMask.cs deleted file mode 100755 index d78513e4e..000000000 --- a/src/Servers/PresenceConnectionManager/src/Enumerate/PublicMask.cs +++ /dev/null @@ -1,53 +0,0 @@ -namespace UniSpy.Server.PresenceConnectionManager.Enumerate -{ - /// - /// This enumerator contains the masks used to hide certain informations. - /// - /// The public mask works by ORing this bytes. - /// - /// If the MASK_HOMEPAGE is ORed with MASK_ZIPCODE both the Homepage - /// and the Zipcode will be showed to the user. - /// - public enum PublicMasks : uint - { - /// - /// Show the essential informations for getting the profile info - /// - None = 0x00000000, - - /// - /// Show the user homepage - /// - Homepage = 0x00000001, - - /// - /// Show the ZIP code - /// - ZipCode = 0x00000002, - - /// - /// Show the country code where the player lives - /// - CountryCode = 0x00000004, - - /// - /// Show the birth date - /// - Birthday = 0x00000008, - - /// - /// Show the gender - /// - Sex = 0x00000010, - - /// - /// Show the Email - /// - Email = 0x00000020, - - /// - /// Show all the informations - /// - All = 0xFFFFFFFF, - }; -} diff --git a/src/Servers/PresenceConnectionManager/src/Enumerate/QuietModeType.cs b/src/Servers/PresenceConnectionManager/src/Enumerate/QuietModeType.cs deleted file mode 100755 index 0809bf11d..000000000 --- a/src/Servers/PresenceConnectionManager/src/Enumerate/QuietModeType.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace UniSpy.Server.PresenceConnectionManager.Enumerate -{ - public enum QuietModeType : uint - { - // Quiet mode flags. - //////////////////// - SlienceNone = 0x00000000, - SlienceMessage = 0x00000001, - SlienceUTMS = 0x00000002, - SlienceList = 0x00000004, // includes requests, auths, and revokes - SlienceAll = 0xFFFFFFFF, - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Enumerate/SDKRevisionType.cs b/src/Servers/PresenceConnectionManager/src/Enumerate/SDKRevisionType.cs deleted file mode 100755 index a22c658ce..000000000 --- a/src/Servers/PresenceConnectionManager/src/Enumerate/SDKRevisionType.cs +++ /dev/null @@ -1,33 +0,0 @@ - -namespace UniSpy.Server.PresenceConnectionManager.Enumerate -{ - public enum SdkRevisionType : int - { - Unknown = 0, - /// - /// Extended message support - /// - GPINewAuthNotification = 1,//1 - /// - /// Remove friend from remote - /// - GPINewRevokeNotification = 1 << 2,//10 - /// - /// New Status Info support - /// - GPINewStatusNotification = 1 << 3,//1000 - /// - /// Buddy List + Block List retrieval on login - /// - GPINewListRetrevalOnLogin = 1 << 4,// - /// - /// Remote Auth logins now return namespaceid/partnerid on login - /// - GPIRemoteAuthIDSNotification = 1 << 5, - /// - /// New CD Key registration style as opposed to using product ids - /// - GPINewCDKeyRegistration = 1 << 6, - - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/AddBuddyHandler.cs b/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/AddBuddyHandler.cs deleted file mode 100755 index 892e38beb..000000000 --- a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/AddBuddyHandler.cs +++ /dev/null @@ -1,28 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Contract.Request; -using UniSpy.Server.PresenceConnectionManager.Contract.Result; -using UniSpy.Server.PresenceConnectionManager.Application; - -namespace UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.Buddy -{ - //\addbuddy\\sesskey\<>\newprofileid\<>\reason\<>\final\ - - public sealed class AddBuddyHandler : LoggedInCmdHandlerBase - { - private new AddBuddyRequest _request => (AddBuddyRequest)base._request; - - public AddBuddyHandler(Client client, AddBuddyRequest request) : base(client, request) - { - _result = new AddBuddyResult(); - } - - protected override void DataOperation() - { - throw new System.NotImplementedException(); - //Check if the friend is online - //if(online) - //else - //store add request to database - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/BlockListHandler.cs b/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/BlockListHandler.cs deleted file mode 100755 index 299856217..000000000 --- a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/BlockListHandler.cs +++ /dev/null @@ -1,30 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Application; -using UniSpy.Server.PresenceConnectionManager.Contract.Response; -using UniSpy.Server.PresenceConnectionManager.Contract.Result; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.Buddy -{ - public sealed class BlockListHandler : LoggedInCmdHandlerBase - { - private new BlockListResult _result { get => (BlockListResult)base._result; set => base._result = value; } - - public BlockListHandler(IClient client) : base(client, null) - { - _result = new BlockListResult(); - } - protected override void RequestCheck() { } - protected override void DataOperation() - { - - _result.ProfileIdList = StorageOperation.Persistance.GetBlockedProfileIds(_client.Info.ProfileInfo.ProfileId, - _client.Info.SubProfileInfo.NamespaceId); - } - - protected override void ResponseConstruct() - { - _response = new BlockListResponse(null, _result); - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/BuddyListHandler.cs b/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/BuddyListHandler.cs deleted file mode 100755 index bbc219db6..000000000 --- a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/BuddyListHandler.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System.Threading.Tasks; -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Application; -using UniSpy.Server.PresenceConnectionManager.Contract.Request; -using UniSpy.Server.PresenceConnectionManager.Contract.Response; -using UniSpy.Server.PresenceConnectionManager.Contract.Result; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.Buddy -{ - public sealed class BuddyListHandler : LoggedInCmdHandlerBase - { - private new BuddyListResult _result { get => (BuddyListResult)base._result; set => base._result = value; } - public BuddyListHandler(IClient client) : base(client, null) - { - _result = new BuddyListResult(); - } - protected override void RequestCheck() { } - protected override void DataOperation() - { - var friendsId = StorageOperation.Persistance.GetFriendProfileIds(_client.Info.ProfileInfo.ProfileId, - _client.Info.SubProfileInfo.NamespaceId); - _result.ProfileIDList = friendsId; - - } - protected override void ResponseConstruct() - { - _response = new BuddyListResponse(_request, _result); - } - protected override void Response() - { - base.Response(); - if (!_client.Info.SdkRevision.IsSupportGPINewStatusNotification) - { - return; - } - - Parallel.ForEach(_result.ProfileIDList, (profileID) => - { - var request = new StatusInfoRequest - { - ProfileId = profileID, - NamespaceID = (int)_client.Info.SubProfileInfo.NamespaceId, - IsGetStatusInfo = true - }; - new StatusInfoHandler(_client, request).Handle(); - }); - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/BuddyStatusInfoHandler.cs b/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/BuddyStatusInfoHandler.cs deleted file mode 100755 index df1c6a2af..000000000 --- a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/BuddyStatusInfoHandler.cs +++ /dev/null @@ -1,24 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.PresenceConnectionManager.Application; - -namespace UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.Buddy -{ - public sealed class BuddyStatusInfoHandler : LoggedInCmdHandlerBase - { - // This is what the message should look like. Its broken up for easy viewing. - // - // "\bsi\\state\\profile\\bip\\bport\\hostip\\hprivip\" - // "\qport\\hport\\sessflags\\rstatus\\gameType\" - // "\gameVnt\\gameMn\\product\\qmodeflags\" - public BuddyStatusInfoHandler(Client client, IRequest request) : base(client, request) - { - throw new System.NotImplementedException(); - } - - protected override void DataOperation() - { - throw new System.NotImplementedException(); - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/DelBuddyHandler.cs b/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/DelBuddyHandler.cs deleted file mode 100755 index b681705a7..000000000 --- a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/DelBuddyHandler.cs +++ /dev/null @@ -1,26 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Application; -using UniSpy.Server.PresenceConnectionManager.Contract.Request; - -namespace UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.Buddy -{ - /// - /// handles dell buddy request,remove friends from friends list - /// - - public sealed class DelBuddyHandler : LoggedInCmdHandlerBase - { - private new DelBuddyRequest _request => (DelBuddyRequest)base._request; - //delete friend in database then send bm_revoke message to friend - public DelBuddyHandler(Client client, DelBuddyRequest request) : base(client, request) - { - } - - protected override void DataOperation() - { - StorageOperation.Persistance.DeleteFriendByProfileId(_client.Info.ProfileInfo.ProfileId, - _request.TargetId, - _client.Info.SubProfileInfo.NamespaceId); - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/InviteToHandler.cs b/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/InviteToHandler.cs deleted file mode 100755 index 28ab82204..000000000 --- a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/InviteToHandler.cs +++ /dev/null @@ -1,35 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Application; -using UniSpy.Server.PresenceConnectionManager.Contract.Request; - -namespace UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.Buddy -{ - /// - /// This function sets which games the local profile can be invited to. - /// - public sealed class InviteToHandler : LoggedInCmdHandlerBase - { - //_connection.SendAsync(@"\pinvite\\sesskey\223\profileid\13\productid\1038\final\"); - private new InviteToRequest _request => (InviteToRequest)base._request; - public InviteToHandler(Client client, InviteToRequest request) : base(client, request) - { - } - - protected override void DataOperation() - { - var client = ClientManager.GetClient(_request.ProfileId, _request.ProductId); - - //user is offline - if (client is null) - { - return; - } - else - { - - } - //TODO - //parse user to buddy message system - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/StatusHandler.cs b/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/StatusHandler.cs deleted file mode 100755 index a04468198..000000000 --- a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/StatusHandler.cs +++ /dev/null @@ -1,37 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Contract.Request; -using UniSpy.Server.PresenceConnectionManager.Contract.Result; -using UniSpy.Server.PresenceConnectionManager.Application; - -namespace UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.Buddy -{ - /// - /// TODO Status should be stored in redis - /// - - public sealed class StatusHandler : LoggedInCmdHandlerBase - { - private new StatusRequest _request => (StatusRequest)base._request; - private new StatusResult _result { get => (StatusResult)base._result; set => base._result = value; } - - public StatusHandler(Client client, StatusRequest request) : base(client, request) - { - _result = new StatusResult(); - } - - protected override void DataOperation() - { - // set user status - if (_request.IsGetStatus) - { - //TODO check if statushandler need send response - } - else - { - _client.Info.Status.CurrentStatus = _request.Status.CurrentStatus; - _client.Info.Status.StatusString = _request.Status.StatusString; - _client.Info.Status.LocationString = _request.Status.LocationString; - } - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/StatusInfoHandler.cs b/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/StatusInfoHandler.cs deleted file mode 100755 index 51ce14470..000000000 --- a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Buddy/StatusInfoHandler.cs +++ /dev/null @@ -1,54 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Application; -using UniSpy.Server.PresenceConnectionManager.Contract.Request; -using UniSpy.Server.PresenceConnectionManager.Contract.Response; -using UniSpy.Server.PresenceConnectionManager.Contract.Result; - -namespace UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.Buddy -{ - /// - /// TODO Status info should be stored in redis - /// - - public sealed class StatusInfoHandler : LoggedInCmdHandlerBase - { - private new StatusInfoRequest _request => (StatusInfoRequest)base._request; - private new StatusInfoResult _result { get => (StatusInfoResult)base._result; set => base._result = value; } - - public StatusInfoHandler(Client client, StatusInfoRequest request) : base(client, request) - { - _result = new StatusInfoResult(); - } - - protected override void DataOperation() - { - if (_request.IsGetStatusInfo) - { - var result = ClientManager.GetClient(_request.ProfileId, null, _request.NamespaceID); - - if (result is not null) - { - // user is not online we do not need to send status info - _result.StatusInfo = result.Info.StatusInfo; - } - } - else - { - _client.Info.StatusInfo = _request.StatusInfo; - // TODO notify every online friend? - } - } - - protected override void ResponseConstruct() - { - if (_request.IsGetStatusInfo) - { - _response = new StatusInfoResponse(_request, _result); - } - else - { - base.ResponseConstruct(); - } - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/General/KeepAliveHandler.cs b/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/General/KeepAliveHandler.cs deleted file mode 100755 index 8d516c5f0..000000000 --- a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/General/KeepAliveHandler.cs +++ /dev/null @@ -1,26 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Application; -using UniSpy.Server.PresenceConnectionManager.Contract.Request; -using UniSpy.Server.PresenceConnectionManager.Contract.Response; - -namespace UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.General -{ - - public sealed class KeepAliveHandler : CmdHandlerBase - { - public KeepAliveHandler(Client client, KeepAliveRequest request) : base(client, request) - { - } - - protected override void DataOperation() - { - //we need to keep the player cache online - //so that other players can find the player - } - - protected override void ResponseConstruct() - { - _response = new KeepAliveResponse(_request, _result); - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/General/LoginHandler.cs b/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/General/LoginHandler.cs deleted file mode 100755 index 4bde6cb68..000000000 --- a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/General/LoginHandler.cs +++ /dev/null @@ -1,144 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Enumerate; -using UniSpy.Server.PresenceConnectionManager.Contract.Request; -using UniSpy.Server.PresenceConnectionManager.Contract.Response; -using UniSpy.Server.PresenceConnectionManager.Contract.Result; -using UniSpy.Server.PresenceConnectionManager.Structure; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; -using UniSpy.Server.PresenceSearchPlayer.Exception.Login; -using UniSpy.Server.PresenceConnectionManager.Application; - -namespace UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.General -{ - - public sealed class LoginHandler : CmdHandlerBase - { - private new LoginRequest _request => (LoginRequest)base._request; - private new LoginResult _result { get => (LoginResult)base._result; set => base._result = value; } - public LoginHandler(Client client, LoginRequest request) : base(client, request) - { - _result = new LoginResult(); - } - - protected override void DataOperation() - { - try - { - switch (_request.Type) - { - case LoginType.NickEmail: - NickEmailLogin(); - break; - - case LoginType.UniquenickNamespaceID: - UniquenickLogin(); - break; - - case LoginType.AuthToken: - AuthtokenLogin(); - break; - // loginticket - } - _result.DatabaseResults = new LogInDataModel - { - Email = _client.Info.UserInfo.Email, - UserId = _client.Info.UserInfo.UserId, - ProfileId = _client.Info.ProfileInfo.ProfileId, - SubProfileId = _client.Info.SubProfileInfo.SubProfileId, - Nick = _client.Info.ProfileInfo.Nick, - UniqueNick = _client.Info.SubProfileInfo.Uniquenick, - PasswordHash = _client.Info.UserInfo.Password, - EmailVerifiedFlag = (bool)_client.Info.UserInfo.Emailverified, - BannedFlag = (bool)_client.Info.UserInfo.Banned, - NamespaceId = _client.Info.SubProfileInfo.NamespaceId - }; - _client.Info.Status.CurrentStatus = GPStatusCode.Online; - } - catch (System.Exception e) - { - throw new GPDatabaseException(e.Message); - } - - IsChallengeCorrect(); - - if (!_result.DatabaseResults.EmailVerifiedFlag) - { - throw new GPLoginBadProfileException(); - } - - // Check if the user is flagged as banned. - if (_result.DatabaseResults.BannedFlag) - { - throw new GPLoginProfileDeletedException(); - } - - // PartnerID is optional - LoginChallengeProof proofData = new LoginChallengeProof( - _request.UserData, - (LoginType)_request.Type, - (int?)_request.PartnerID, - LoginChallengeProof.ServerChallenge, - _request.UserChallenge, - _result.DatabaseResults.PasswordHash); - - _result.ResponseProof = - LoginChallengeProof.GenerateProof(proofData); - - _client.Info.LoginStat = LoginStatus.Completed; - } - - protected override void ResponseConstruct() - { - _response = new LoginResponse(_request, _result); - } - - protected override void Response() - { - base.Response(); - //Arves is correct we need to check this - // save information to client object - new SdkRevisionHandler(_client, _request).Handle(); - } - - private void NickEmailLogin() - { - //Check email existence - if (!StorageOperation.Persistance.IsEmailExist(_request.Email)) - { - throw new GPLoginBadEmailException($"email: {_request.Email} is invalid."); - } - - (_client.Info.UserInfo, _client.Info.ProfileInfo, _client.Info.SubProfileInfo) = PresenceConnectionManager.Application.StorageOperation.Persistance.GetUsersInfos(_request.Email, _request.Nick); - } - - - private void UniquenickLogin() - { - (_client.Info.UserInfo, _client.Info.ProfileInfo, _client.Info.SubProfileInfo) = PresenceConnectionManager.Application.StorageOperation.Persistance.GetUsersInfos(_request.UniqueNick, (int)_request.NamespaceID); - } - - private void AuthtokenLogin() - { - (_client.Info.UserInfo, _client.Info.ProfileInfo, _client.Info.SubProfileInfo) = PresenceConnectionManager.Application.StorageOperation.Persistance.GetUsersInfos(_request.AuthToken, (int)_request.PartnerID, (int)_request.NamespaceID); - } - - private void IsChallengeCorrect() - { - // PartnerID is optional - LoginChallengeProof proofData = new LoginChallengeProof( - _request.UserData, - (LoginType)_request.Type, - (int?)_request.PartnerID, - _request.UserChallenge, - LoginChallengeProof.ServerChallenge, - _result.DatabaseResults.PasswordHash); - - string response = LoginChallengeProof.GenerateProof(proofData); - - if (_request.Response != response) - { - throw new GPLoginBadPasswordException("The response is not valid, this maybe caused by wrong password."); - } - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/General/LogoutHandler.cs b/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/General/LogoutHandler.cs deleted file mode 100755 index 85f5c0152..000000000 --- a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/General/LogoutHandler.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Application; -using UniSpy.Server.PresenceConnectionManager.Contract.Request; - -namespace UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.General -{ - - public sealed class LogoutHandler : CmdHandlerBase - { - public LogoutHandler(Client client, LogoutRequest request) : base(client, request) - { - } - - protected override void DataOperation() - { - _client.Connection.Disconnect(); - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/General/NewUserHandler.cs b/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/General/NewUserHandler.cs deleted file mode 100755 index 719ee50f5..000000000 --- a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/General/NewUserHandler.cs +++ /dev/null @@ -1,17 +0,0 @@ -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.PresenceConnectionManager.Contract.Response; - - -namespace UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.General -{ - public sealed class NewUserHandler : PresenceSearchPlayer.Handler.CmdHandler.NewUserHandler - { - public NewUserHandler(IClient client, IRequest request) : base(client, request) - { - } - protected override void ResponseConstruct() - { - _response = new NewUserResponse(_request, _result); - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/General/SDKRevisionHandler.cs b/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/General/SDKRevisionHandler.cs deleted file mode 100755 index 7d5f60120..000000000 --- a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/General/SDKRevisionHandler.cs +++ /dev/null @@ -1,26 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Contract.Request; -using UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.Buddy; -using UniSpy.Server.PresenceConnectionManager.Application; - -namespace UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.General -{ - - public sealed class SdkRevisionHandler : CmdHandlerBase - { - private new LoginRequest _request => (LoginRequest)base._request; - public SdkRevisionHandler(Client client, LoginRequest request) : base(client, request) - { - } - protected override void RequestCheck() { } - protected override void DataOperation() - { - if (_client.Info.SdkRevision.IsSupportGPINewListRetrevalOnLogin) - { - //send buddy list and block list - new BuddyListHandler(_client).Handle(); - new BlockListHandler(_client).Handle(); - } - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/AddBlockHandler.cs b/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/AddBlockHandler.cs deleted file mode 100755 index 37e85b721..000000000 --- a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/AddBlockHandler.cs +++ /dev/null @@ -1,30 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Application; -using UniSpy.Server.PresenceConnectionManager.Contract.Request; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.Profile -{ - - public sealed class AddBlockHandler : LoggedInCmdHandlerBase - { - private new AddBlockRequest _request => (AddBlockRequest)base._request; - public AddBlockHandler(Client client, AddBlockRequest request) : base(client, request) - { - } - protected override void RequestCheck() - { - base.RequestCheck(); - if (_client.Info.ProfileInfo.ProfileId == _request.TargetId) - { - throw new GPException("You can not block your self."); - } - } - protected override void DataOperation() - { - StorageOperation.Persistance.UpdateBlockInfo(_request.TargetId, - _client.Info.ProfileInfo.ProfileId, - _client.Info.SubProfileInfo.NamespaceId); - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/GetProfileHandler.cs b/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/GetProfileHandler.cs deleted file mode 100755 index e4b5c0996..000000000 --- a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/GetProfileHandler.cs +++ /dev/null @@ -1,37 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Application; -using UniSpy.Server.PresenceConnectionManager.Contract.Request; -using UniSpy.Server.PresenceConnectionManager.Contract.Response; -using UniSpy.Server.PresenceConnectionManager.Contract.Result; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.Profile -{ - - public sealed class GetProfileHandler : LoggedInCmdHandlerBase - { - // \getprofile\\sesskey\19150\profileid\2\id\2\final\ - private new GetProfileRequest _request => (GetProfileRequest)base._request; - private new GetProfileResult _result { get => (GetProfileResult)base._result; set => base._result = value; } - - public GetProfileHandler(Client client, GetProfileRequest request) : base(client, request) - { - _result = new GetProfileResult(); - } - protected override void DataOperation() - { - _result.UserProfile = StorageOperation.Persistance.GetProfileInfos(_request.ProfileId, _client.Info.SubProfileInfo.NamespaceId); - - if (_result.UserProfile is null) - { - throw new GPDatabaseException($"No profile of profileid:{_request.ProfileId} found in database."); - } - } - - protected override void ResponseConstruct() - { - _response = new GetProfileResponse(_request, _result); - } - } -} - diff --git a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/NewProfileHandler.cs b/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/NewProfileHandler.cs deleted file mode 100755 index 801170879..000000000 --- a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/NewProfileHandler.cs +++ /dev/null @@ -1,48 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Application; -using UniSpy.Server.PresenceConnectionManager.Contract.Request; -using UniSpy.Server.PresenceConnectionManager.Contract.Response; -using UniSpy.Server.PresenceConnectionManager.Contract.Result; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.Profile -{ - - public sealed class NewProfileHandler : Abstraction.BaseClass.CmdHandlerBase - { - private new NewProfileRequest _request => (NewProfileRequest)base._request; - private new NewProfileResult _result { get => (NewProfileResult)base._result; set => base._result = value; } - public NewProfileHandler(Client client, NewProfileRequest request) : base(client, request) - { - _result = new NewProfileResult(); - } - protected override void RequestCheck() - { - base.RequestCheck(); - if (_client.Info.ProfileInfo.Nick != _request.OldNick) - { - throw new GPException("The old nickname is not identical to current nickname."); - } - } - protected override void DataOperation() - { - if (_request.IsReplaceNickName) - { - StorageOperation.Persistance.UpdateNickName(_client.Info.ProfileInfo.ProfileId, - _request.OldNick, - _request.NewNick); - } - else - { - StorageOperation.Persistance.AddNickName(_client.Info.UserInfo.UserId, - _client.Info.ProfileInfo.ProfileId, - _request.NewNick); - } - _result.ProfileId = _client.Info.ProfileInfo.ProfileId; - } - - protected override void ResponseConstruct() - { - _response = new NewProfileResponse(_request, _result); - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/RegisterCDKeyHandler.cs b/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/RegisterCDKeyHandler.cs deleted file mode 100755 index f098f2fbf..000000000 --- a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/RegisterCDKeyHandler.cs +++ /dev/null @@ -1,21 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Application; -using UniSpy.Server.PresenceConnectionManager.Contract.Request; - -namespace UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.Profile -{ - - public sealed class RegisterCDKeyHandler : LoggedInCmdHandlerBase - { - private new RegisterCDKeyRequest _request => (RegisterCDKeyRequest)base._request; - public RegisterCDKeyHandler(Client client, RegisterCDKeyRequest request) : base(client, request) - { - } - - protected override void DataOperation() - { - _client.Info.SubProfileInfo.Cdkeyenc = _request.CDKeyEnc; - StorageOperation.Persistance.UpdateSubProfileInfo(_client.Info.SubProfileInfo); - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/RegisterNickHandler.cs b/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/RegisterNickHandler.cs deleted file mode 100755 index b78f37137..000000000 --- a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/RegisterNickHandler.cs +++ /dev/null @@ -1,42 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.PresenceConnectionManager.Application; -using UniSpy.Server.PresenceConnectionManager.Contract.Request; -using UniSpy.Server.PresenceConnectionManager.Contract.Response; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.Profile -{ - - public sealed class RegisterNickHandler : LoggedInCmdHandlerBase - { - private new RegisterNickRequest _request => (RegisterNickRequest)base._request; - public RegisterNickHandler(Client client, RegisterNickRequest request) : base(client, request) - { - } - protected override void RequestCheck() - { - base.RequestCheck(); - if (_request.UniqueNick == _client.Info.SubProfileInfo.Uniquenick) - { - throw new GPException("new uniquenick is identical to old uniquenick, no update needed"); - } - } - protected override void DataOperation() - { - try - { - StorageOperation.Persistance.UpdateUniqueNick(_client.Info.SubProfileInfo.SubProfileId, - _request.UniqueNick); - } - catch (System.Exception e) - { - throw new GPDatabaseException(e.Message); - } - } - - protected override void ResponseConstruct() - { - _response = new RegisterNickResponse(_request, _result); - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/RemoveBlockHandler.cs b/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/RemoveBlockHandler.cs deleted file mode 100755 index 0b9776313..000000000 --- a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/RemoveBlockHandler.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.PresenceConnectionManager.Application; - -namespace UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.Profile -{ - - public sealed class RemoveBlockHandler : LoggedInCmdHandlerBase - { - public RemoveBlockHandler(Client client, IRequest request) : base(client, request) - { - throw new NotImplementedException(); - } - - protected override void DataOperation() - { - throw new NotImplementedException(); - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/UpdateProfileHandler.cs b/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/UpdateProfileHandler.cs deleted file mode 100755 index 980e74268..000000000 --- a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/UpdateProfileHandler.cs +++ /dev/null @@ -1,62 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Application; -using UniSpy.Server.PresenceConnectionManager.Contract.Request; - -namespace UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.Profile -{ - - public sealed class UpdateProfileHandler : Abstraction.BaseClass.CmdHandlerBase - { - private new UpdateProfileRequest _request => (UpdateProfileRequest)base._request; - public UpdateProfileHandler(Client client, UpdateProfileRequest request) : base(client, request) - { - } - - protected override void DataOperation() - { - var profile = _client.Info.ProfileInfo; - - if (_request.HasPublicMaskFlag) - { - profile.Publicmask = (int)_request.PublicMask; - } - if (_request.HasFirstNameFlag) - { - profile.Firstname = _request.FirstName; - } - if (_request.HasLastNameFlag) - { - profile.Lastname = _request.LastName; - } - if (_request.HasICQFlag) - { - profile.Icquin = _request.ICQUIN; - } - if (_request.HasHomePageFlag) - { - profile.Homepage = _request.HomePage; - } - if (_request.HasBirthdayFlag) - { - profile.Birthday = _request.BirthDay; - profile.Birthmonth = _request.BirthMonth; - profile.Birthyear = _request.BirthYear; - } - if (_request.HasSexFlag) - { - profile.Sex = _request.Sex; - } - - if (_request.HasZipCode) - { - profile.Zipcode = _request.ZipCode; - } - if (_request.HasCountryCode) - { - profile.Countrycode = _request.CountryCode; - } - - StorageOperation.Persistance.UpdateProfileInfo(profile); - } - } -} - diff --git a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/UpdateUserInfoHandler.cs b/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/UpdateUserInfoHandler.cs deleted file mode 100755 index 075ceff58..000000000 --- a/src/Servers/PresenceConnectionManager/src/Handler/CmdHandler/Profile/UpdateUserInfoHandler.cs +++ /dev/null @@ -1,24 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.PresenceConnectionManager.Application; - -namespace UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.Profile -{ - /// - /// Update user information (email) - /// - - public sealed class UpdateUserInfoHandler : LoggedInCmdHandlerBase - { - public UpdateUserInfoHandler(Client client, IRequest request) : base(client, request) - { - //todo find what data is belong to user info - throw new System.NotImplementedException(); - } - - protected override void DataOperation() - { - throw new System.NotImplementedException(); - } - } -} diff --git a/src/Servers/PresenceConnectionManager/src/Handler/CmdSwitcher.cs b/src/Servers/PresenceConnectionManager/src/Handler/CmdSwitcher.cs deleted file mode 100755 index 215b48a38..000000000 --- a/src/Servers/PresenceConnectionManager/src/Handler/CmdSwitcher.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using UniSpy.Server.PresenceConnectionManager.Contract.Request; -using UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.Buddy; -using UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.General; -using UniSpy.Server.PresenceConnectionManager.Handler.CmdHandler.Profile; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.PresenceSearchPlayer.Contract.Request; -using UniSpy.Server.PresenceConnectionManager.Application; - -namespace UniSpy.Server.PresenceConnectionManager.Handler -{ - public sealed class CmdSwitcher : CmdSwitcherBase - { - private new string _rawRequest => (string)base._rawRequest; - private new Client _client => (Client)base._client; - public CmdSwitcher(Client client, string rawRequest) : base(client, rawRequest) - { - } - protected override void ProcessRawRequest() - { - if (_rawRequest[0] != '\\') - { - throw new GPParseException("Request format is invalid"); - } - var rawRequests = _rawRequest.Split(@"\final\", StringSplitOptions.RemoveEmptyEntries); - - foreach (var rawRequest in rawRequests) - { - var name = rawRequest.TrimStart('\\').Split('\\').First(); - _requests.Add(new KeyValuePair(name, rawRequest)); - } - } - - protected override IHandler CreateCmdHandlers(object name, object rawRequest) - { - switch ((string)name) - { - # region General - case "ka": - return new KeepAliveHandler(_client, new KeepAliveRequest((string)rawRequest)); - case "login": - return new LoginHandler(_client, new LoginRequest((string)rawRequest)); - case "logout": - return new LogoutHandler(_client, new LogoutRequest((string)rawRequest)); - case "newuser": - return new NewUserHandler(_client, new NewUserRequest((string)rawRequest)); - #endregion - # region Profile - case "addblock": - return new AddBlockHandler(_client, new AddBlockRequest((string)rawRequest)); - case "getprofile": - return new GetProfileHandler(_client, new GetProfileRequest((string)rawRequest)); - case "newprofile": - return new NewProfileHandler(_client, new NewProfileRequest((string)rawRequest)); - case "registercdkey": - return new RegisterCDKeyHandler(_client, new RegisterCDKeyRequest((string)rawRequest)); - case "registernick": - return new RegisterNickHandler(_client, new RegisterNickRequest((string)rawRequest)); - case "updatepro": - return new UpdateProfileHandler(_client, new UpdateProfileRequest((string)rawRequest)); - case "updateui": - // return new UpdateUserInfoHandler(_client, new UpdateUserInfoRequest((string)rawRequest)); - throw new NotImplementedException(); - - # endregion - # region Buddy - case "addbuddy": - return new AddBuddyHandler(_client, new AddBuddyRequest((string)rawRequest)); - case "delbuddy": - return new DelBuddyHandler(_client, new DelBuddyRequest((string)rawRequest)); - case "bsi": - // return new BuddyStatusInfoHandler(_client, new BuddyStatusInfoRequest((string)rawRequest)); - throw new NotImplementedException(); - case "status": - return new StatusHandler(_client, new StatusRequest((string)rawRequest)); - case "statusinfo": - return new StatusInfoHandler(_client, new StatusInfoRequest((string)rawRequest)); - #endregion - default: - return null; - } - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceConnectionManager/src/UniSpy.Server.PresenceConnectionManager.csproj b/src/Servers/PresenceConnectionManager/src/UniSpy.Server.PresenceConnectionManager.csproj deleted file mode 100755 index 332590493..000000000 --- a/src/Servers/PresenceConnectionManager/src/UniSpy.Server.PresenceConnectionManager.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - - Exe - net6.0 - ..\..\..\..\common\Icon\UniSpy_Logo.ico - Linux - ..\..\..\.. - - - ..\..\..\..\build\$(Configuration) - - - ..\..\..\..\build\$(Configuration) - - - - - - - - - \ No newline at end of file diff --git a/src/Servers/PresenceConnectionManager/test/Buddy/BuddyRequestTest.cs b/src/Servers/PresenceConnectionManager/test/Buddy/BuddyRequestTest.cs deleted file mode 100644 index 88056abc3..000000000 --- a/src/Servers/PresenceConnectionManager/test/Buddy/BuddyRequestTest.cs +++ /dev/null @@ -1,53 +0,0 @@ -using Xunit; -using UniSpy.Server.PresenceConnectionManager.Contract.Request; - -namespace UniSpy.Server.PresenceConnectionManager.Test -{ - public class BuddyRequestTest - { - [Fact] - public void AddBuddy() - { - var request = new AddBuddyRequest(BuddyRequests.AddBuddy); - request.Parse(); - Assert.Equal((int)0, request.FriendProfileID); - Assert.Equal("test", request.Reason); - } - - [Fact] - public void DelBuddy() - { - var request = new DelBuddyRequest(BuddyRequests.DelBuddy); - request.Parse(); - Assert.Equal((int)0, request.TargetId); - } - - [Fact] - public void InviteTo() - { - var request = new InviteToRequest(BuddyRequests.InviteTo); - request.Parse(); - Assert.Equal((int)0, request.ProductId); - Assert.Equal((int)0, request.ProfileId); - } - - // TODO: - /*[Fact] - public void StatusInfo() - { - var request = new StatusInfoRequest(BuddyRequests.StatusInfo); - request.Parse(); - Assert.Equal((int)0, request.ProfileId); - Assert.Equal((int)0, request.NamespaceID); - }*/ - - [Fact] - public void Status() - { - var request = new StatusRequest(BuddyRequests.Status); - request.Parse(); - Assert.Equal("test", request.Status.StatusString); - Assert.Equal("test", request.Status.LocationString); - } - } -} diff --git a/src/Servers/PresenceConnectionManager/test/Buddy/BuddyRequests.cs b/src/Servers/PresenceConnectionManager/test/Buddy/BuddyRequests.cs deleted file mode 100644 index 5c0309cde..000000000 --- a/src/Servers/PresenceConnectionManager/test/Buddy/BuddyRequests.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace UniSpy.Server.PresenceConnectionManager.Test -{ - public static class BuddyRequests - { - public const string AddBuddy = @"\addbuddy\\sesskey\0\newprofileid\0\reason\test\final\"; - - public const string DelBuddy = @"\delbuddy\\sesskey\0\delprofileid\0\final\"; - - public const string InviteTo = @"\inviteto\\sesskey\0\productid\0\profileid\0\final\"; - - //public const string StatusInfo = @"\inviteto\\sesskey\0\productid\0\profileid\0\final\"; - - public const string Status = @"\status\0\statstring\test\locstring\test\final\"; - - } -} diff --git a/src/Servers/PresenceConnectionManager/test/Game/GameTest.cs b/src/Servers/PresenceConnectionManager/test/Game/GameTest.cs deleted file mode 100644 index 04b6a87f2..000000000 --- a/src/Servers/PresenceConnectionManager/test/Game/GameTest.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Encryption; -using Xunit; - -namespace UniSpy.Server.PresenceConnectionManager.Test -{ - public class GameTest - { - [Fact] - public void Civilization4() - { - var rawRequests = new List() - { - @"\newuser\\email\civ4@unispy.org\nick\civ4-tk\passwordenc\JMHGwQ__\productid\10435\gamename\civ4\namespaceid\17\uniquenick\civ4-tk\id\1\final\", - @"\login\\challenge\xMsHUXuWNXL3KMwmhoQZJrP0RVsArCYT\uniquenick\civ4-tk\userid\25\profileid\26\response\7f2c9c6685570ea18b7207d2cbd72452\firewall\1\port\0\productid\10435\gamename\civ4\namespaceid\17\sdkrevision\1\id\1\final\" - }; - foreach (var raw in rawRequests) - { - ((ITestClient)MokeObject.client).TestReceived(UniSpyEncoding.GetBytes(raw)); - } - } - [Fact] - public void ConflictGlobalStorm() - { - var rawRequests = new List() - { - @"\lc\1\challenge\NRNUJLZMLX\id\1\final\", - @"\login\\challenge\KMylyQbZfqzKn9otxx32q4076sOUnKif\user\cgs1@cgs1@rs.de\response\c1a6638bbcfe130e4287bfe4aa792949\port\-15737\productid\10469\gamename\conflictsopc\namespaceid\1\id\1\final\", - @"\inviteto\\sesskey\58366\products\1038\final\" - }; - foreach (var raw in rawRequests) - { - ((ITestClient)MokeObject.client).TestReceived(UniSpyEncoding.GetBytes(raw)); - } - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceConnectionManager/test/General/GeneralRequestTest.cs b/src/Servers/PresenceConnectionManager/test/General/GeneralRequestTest.cs deleted file mode 100644 index 45cbd4742..000000000 --- a/src/Servers/PresenceConnectionManager/test/General/GeneralRequestTest.cs +++ /dev/null @@ -1,106 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Enumerate; -using UniSpy.Server.PresenceConnectionManager.Contract.Request; -using Xunit; - -namespace UniSpy.Server.PresenceConnectionManager.Test -{ - public class GeneralRequestTest - { - //TODO: no keep alive request - /*[Fact] - public void KeepAlive() - { - var request = new KeepAliveRequest(GeneralRequests.KeepAlive); - request.Parse(); - Assert.Equal("xxxx", "xxxx"); - }*/ - - [Fact] - public void LoginAuthtoken() - { - var request = new LoginRequest(GeneralRequests.LoginAuthtoken); - request.Parse(); - Assert.Equal(LoginType.AuthToken, request.Type); - Assert.Equal("xxxx", request.UserChallenge); - Assert.Equal("xxxx", request.AuthToken); - Assert.Equal((int)0, request.UserID); - Assert.Equal((int)0, request.ProfileId); - Assert.Equal((int)0, request.PartnerID); - Assert.Equal("xxxxx", request.Response); - Assert.Equal("1", request.Firewall); - Assert.Equal(request.GamePort, (ushort)0); - Assert.Equal(request.ProductID, (int)0); - Assert.Equal("gmtest", request.GameName); - Assert.Equal((SdkRevisionType)3, request.SdkRevisionType); - Assert.Equal((QuietModeType)0, request.QuietModeFlags); - } - - [Fact] - public void LoginUniquenick() - { - var request = new LoginRequest(GeneralRequests.LoginUniquenick); - request.Parse(); - Assert.Equal(LoginType.UniquenickNamespaceID, request.Type); - Assert.Equal("xxxx", request.UserChallenge); - Assert.Equal("spyguy", request.UniqueNick); - Assert.Equal((int)0, request.NamespaceID); - Assert.Equal((int)0, request.UserID); - Assert.Equal((int)0, request.ProfileId); - Assert.Equal((int)0, request.PartnerID); - Assert.Equal("xxxxx", request.Response); - Assert.Equal("1", request.Firewall); - Assert.Equal((ushort)0, request.GamePort); - Assert.Equal((int)0, request.ProductID); - Assert.Equal("gmtest", request.GameName); - Assert.Equal((SdkRevisionType)3, request.SdkRevisionType); - Assert.Equal((QuietModeType)0, request.QuietModeFlags); - } - - [Fact] - public void LoginUser() - { - var request = new LoginRequest(GeneralRequests.LoginUser); - request.Parse(); - Assert.Equal(LoginType.NickEmail, request.Type); - Assert.Equal("xxxx", request.UserChallenge); - Assert.Equal("spyguy", request.Nick); - Assert.Equal("spyguy@unispy.org", request.Email); - Assert.Equal((int)0, request.NamespaceID); - Assert.Equal((int)0, request.UserID); - Assert.Equal((int)0, request.ProfileId); - Assert.Equal((int)0, request.PartnerID); - Assert.Equal("xxxxx", request.Response); - Assert.Equal("1", request.Firewall); - Assert.Equal((ushort)0, request.GamePort); - Assert.Equal((int)0, request.ProductID); - Assert.Equal("gmtest", request.GameName); - Assert.Equal((SdkRevisionType)3, request.SdkRevisionType); - Assert.Equal((QuietModeType)0, request.QuietModeFlags); - } - - //TODO: no logout request - /*[Fact] - public void Logout() - { - var request = new LogoutRequest(GeneralRequests.Logout); - request.Parse(); - Assert.Equal("xxxx", "xxxx"); - }*/ - - //TODO: passwordenc doesn't work - /*[Fact] - public void NewUser() - { - var request = new NewUserRequest(GeneralRequests.NewUser); - request.Parse(); - Assert.Equal("spyguy@unispy.org", request.Email); - Assert.Equal("spyguy", request.Nick); - Assert.Equal("0000", request.Password); - Assert.Equal((int)0, request.ProductID); - Assert.Equal("gmtest", request.GameName); - Assert.Equal((int)0, request.NamespaceID); - Assert.Equal("spyguy", request.Uniquenick); - Assert.Equal("xxxx", request.CDKeyEnc); - }*/ - } -} diff --git a/src/Servers/PresenceConnectionManager/test/General/GeneralRequests.cs b/src/Servers/PresenceConnectionManager/test/General/GeneralRequests.cs deleted file mode 100644 index bfdcd102b..000000000 --- a/src/Servers/PresenceConnectionManager/test/General/GeneralRequests.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace UniSpy.Server.PresenceConnectionManager.Test -{ - public static class GeneralRequests - { - //public const string KeepAlive = @""; - - public const string LoginAuthtoken = @"\login\\challenge\xxxx\authtoken\xxxx\userid\0\profileid\0\partnerid\0\response\xxxxx\firewall\1\port\0000\productid\0\gamename\gmtest\sdkrevision\3\quiet\0\id\1\final\"; - - public const string LoginUniquenick = @"\login\\challenge\xxxx\uniquenick\spyguy\userid\0\profileid\0\namespaceid\0\partnerid\0\response\xxxxx\firewall\1\port\0000\productid\0\gamename\gmtest\sdkrevision\3\quiet\0\id\1\final\"; - - public const string LoginUser = @"\login\\challenge\xxxx\user\spyguy@spyguy@unispy.org\userid\0\profileid\0\partnerid\0\namespaceid\0\response\xxxxx\firewall\1\port\0000\productid\0\gamename\gmtest\sdkrevision\3\quiet\0\id\1\final\"; - - //public const string Logout = @""; - - //public const string NewUser = @"\newuser\email\spyguy@unispy.org\nick\spyguy\passwordenc\4a7d1ed414474e4033ac29ccb8653d9b\productid\0\gamename\gmtest\namespaceid\0\uniquenick\spyguy\cdkeyenc\xxxx\id\1\final\"; - } -} diff --git a/src/Servers/PresenceConnectionManager/test/MokeObject.cs b/src/Servers/PresenceConnectionManager/test/MokeObject.cs deleted file mode 100644 index 01f2ec6ed..000000000 --- a/src/Servers/PresenceConnectionManager/test/MokeObject.cs +++ /dev/null @@ -1,31 +0,0 @@ -using UniSpy.Server.Core.Abstraction.Interface; -using System.Net; -using Moq; -using UniSpy.Server.PresenceConnectionManager.Application; - -namespace UniSpy.Server.PresenceConnectionManager.Test -{ - public class MokeObject - { - /// - /// PCM test client, create one here, use anywhere - /// - public static IClient client; - static MokeObject() - { - client = CreateClient(); - } - - public static IClient CreateClient(string ipAddress = "192.168.1.1", int port = 9990) - { - var managerMock = new Mock(); - var connectionMock = new Mock(); - connectionMock.Setup(s => s.RemoteIPEndPoint).Returns(new IPEndPoint(IPAddress.Parse(ipAddress), port)); - connectionMock.Setup(s => s.Manager).Returns(managerMock.Object); - connectionMock.Setup(s => s.ConnectionType).Returns(NetworkConnectionType.Tcp); - var serverMock = new PresenceConnectionManager.Application.Server(managerMock.Object); - - return new Client(connectionMock.Object, serverMock); - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceConnectionManager/test/Persist/PersistTest.cs b/src/Servers/PresenceConnectionManager/test/Persist/PersistTest.cs deleted file mode 100644 index 70022877d..000000000 --- a/src/Servers/PresenceConnectionManager/test/Persist/PersistTest.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Xunit; -namespace UniSpy.Server.PresenceConnectionManager.Test.Persist -{ - public class PersistTest - { - [Fact] - public void DatabaseAcessTest() - { - // StorageOperation.Persistance.AddNickName() - // Given - - // When - - // Then - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceConnectionManager/test/Profile/ProfileRequestTest.cs b/src/Servers/PresenceConnectionManager/test/Profile/ProfileRequestTest.cs deleted file mode 100644 index e33722f65..000000000 --- a/src/Servers/PresenceConnectionManager/test/Profile/ProfileRequestTest.cs +++ /dev/null @@ -1,107 +0,0 @@ -using UniSpy.Server.PresenceConnectionManager.Contract.Request; -using Xunit; - -namespace UniSpy.Server.PresenceConnectionManager.Test -{ - public class ProfileRequestTest - { - [Fact] - public void AddBlock() - { - var request = new AddBlockRequest(ProfileRequests.AddBlock); - request.Parse(); - Assert.Equal((int)0, request.TargetId); - } - - [Fact] - public void GetProfile() - { - var request = new GetProfileRequest(ProfileRequests.GetProfile); - request.Parse(); - Assert.Equal((int)0, request.ProfileId); - Assert.Equal("xxxx", request.SessionKey); - } - - [Fact] - public void NewProfile() - { - var request = new NewProfileRequest(ProfileRequests.NewProfile); - request.Parse(); - Assert.Equal("xxxx", request.SessionKey); - Assert.Equal("spyguy", request.NewNick); - } - - [Fact] - public void NewProfileReplace() - { - var request = new NewProfileRequest(ProfileRequests.NewProfileReplace); - request.Parse(); - Assert.Equal("xxxx", request.SessionKey); - Assert.Equal("spyguy2", request.NewNick); - Assert.Equal("spyguy", request.OldNick); - } - - [Fact] - public void RegisterCDKey() - { - var request = new RegisterCDKeyRequest(ProfileRequests.RegisterCDKey); - request.Parse(); - Assert.Equal("xxxx", request.SessionKey); - Assert.Equal("xxxx", request.CDKeyEnc); - } - - [Fact] - public void RegisterNick() - { - var request = new RegisterNickRequest(ProfileRequests.RegisterNick); - request.Parse(); - Assert.Equal("xxxx", request.SessionKey); - Assert.Equal("spyguy", request.UniqueNick); - Assert.Equal((int)0, request.PartnerId); - } - [Fact] - public void UpdateProfile() - { - // Given - var crysisWarsRaw = @"\updatepro\\sesskey\1111\countrycode\DE\birthday\168232912\partnerid\0\final\"; - var request = new UpdateProfileRequest(crysisWarsRaw); - request.Parse(); - // When - - // Then - } - //TODO: publicmasks doesn't work - /*[Fact] - public void UpdatePro() - { - var request = new UpdateProRequest(ProfileRequests.UpdatePro); - request.Parse(); - Assert.Equal(PublicMasks.All, request.PublicMask); - Assert.Equal("xxxx", request.SessionKey); - Assert.Equal("Spy", request.FirstName); - Assert.Equal("Guy", request.LastName); - Assert.Equal((int)0, request.ICQUIN); - Assert.Equal("unispy.org", request.HomePage); - Assert.Equal("00000", request.ZipCode); - Assert.Equal("US", request.CountryCode); - Assert.Equal(20, request.BirthDay); - Assert.Equal(3, request.BirthMonth); - Assert.Equal(1980, request.BirthYear); - Assert.Equal(0, request.Sex); - Assert.Equal((int)0, request.PartnerID); - Assert.Equal("spyguy", request.Nick); - Assert.Equal("spyguy", request.Uniquenick); - }*/ - - //TODO: not implemented - /*[Fact] - public void UpdateUi() - { - var request = new UpdateUiRequest(ProfileRequests.UpdateUi); - request.Parse(); - Assert.Equal("xxxx", request.SessionKey); - Assert.Equal("0000", request.Password); - Assert.Equal("spyguy@unispy.org", request.Email); - }*/ - } -} diff --git a/src/Servers/PresenceConnectionManager/test/Profile/ProfileRequests.cs b/src/Servers/PresenceConnectionManager/test/Profile/ProfileRequests.cs deleted file mode 100644 index 1aa316484..000000000 --- a/src/Servers/PresenceConnectionManager/test/Profile/ProfileRequests.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace UniSpy.Server.PresenceConnectionManager.Test -{ - public static class ProfileRequests - { - public const string AddBlock = @"\addblock\\profileid\0\final\"; - - public const string GetProfile = @"\getprofile\\sesskey\xxxx\profileid\0\final\"; - - public const string NewProfile = @"\newprofile\\sesskey\xxxx\nick\spyguy\id\1\final\"; - - public const string NewProfileReplace = @"\newprofile\\sesskey\xxxx\nick\spyguy2\replace\1\oldnick\spyguy\id\1\final\"; - - public const string RegisterCDKey = @"\registercdkey\\sesskey\xxxx\cdkeyenc\xxxx\id\1\final\"; - - public const string RegisterNick = @"\registernick\\sesskey\xxxx\uniquenick\spyguy\partnerid\0\id\1\final\"; - - //public const string UpdatePro = @"\updatepro\\sesskey\xxxx\firstname\Spy\lastname\Guy\icquin\0\homepage\unispy.org\zipcode\00000\countrycode\US\birthday\335742908\sex\0\aim\spyguy@aim.com\pic\0\occ\0\ind\0\inc\0\mar\0\chc\0\i1\0\nick\spyguy\uniquenick\spyguy\publicmask\0\partnerid\0\final\"; - - //public const string UpdateUi = @"\updateui\\sesskey\xxxx\passwordenc\4a7d1ed414474e4033ac29ccb8653d9b\email\spyguy@unispy.org\final\"; - } -} diff --git a/src/Servers/PresenceConnectionManager/test/UniSpy.Server.PresenceConnectionManager.Test.csproj b/src/Servers/PresenceConnectionManager/test/UniSpy.Server.PresenceConnectionManager.Test.csproj deleted file mode 100644 index 8bc0f33ad..000000000 --- a/src/Servers/PresenceConnectionManager/test/UniSpy.Server.PresenceConnectionManager.Test.csproj +++ /dev/null @@ -1,31 +0,0 @@ - - - - net6.0 - false - ..\..\..\..\common\Icon\UniSpy_Logo.ico - - - AnyCPU - ..\..\..\..\build\$(Configuration) - - - ..\..\..\..\build\$(Configuration) - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Abstraction/BaseClass/CmdHandlerBase.cs b/src/Servers/PresenceSearchPlayer/src/Abstraction/BaseClass/CmdHandlerBase.cs deleted file mode 100755 index d4d165c3e..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Abstraction/BaseClass/CmdHandlerBase.cs +++ /dev/null @@ -1,27 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Exception.General; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass -{ - public abstract class CmdHandlerBase : UniSpy.Server.Core.Abstraction.BaseClass.CmdHandlerBase - { - /// - /// Be careful the return of query function should be List type, - /// the decision formula should use _result.Count==0 - /// - protected new RequestBase _request => (RequestBase)base._request; - protected new ResultBase _result { get => (ResultBase)base._result; set => base._result = value; } - public CmdHandlerBase(IClient client, IRequest request) : base(client, request) - { - } - - protected override void HandleException(System.Exception ex) - { - if (ex is GPException) - { - _client.Send(((GPException)ex)); - } - base.HandleException(ex); - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Abstraction/BaseClass/RequestBase.cs b/src/Servers/PresenceSearchPlayer/src/Abstraction/BaseClass/RequestBase.cs deleted file mode 100755 index c54970adb..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Abstraction/BaseClass/RequestBase.cs +++ /dev/null @@ -1,36 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Exception.General; -using System.Collections.Generic; -using System.Linq; -using UniSpy.Server.Core.Misc; - -namespace UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass -{ - public abstract class RequestBase : UniSpy.Server.Core.Abstraction.BaseClass.RequestBase - { - public Dictionary RequestKeyValues { get; protected set; } - public new string RawRequest{ get => (string)base.RawRequest; - } - public new string CommandName{ get => (string)base.CommandName; - protected set => base.CommandName = value; } - public ushort OperationID { get; protected set; } - public RequestBase(string rawRequest) : base(rawRequest) - { - RequestKeyValues = GameSpyUtils.ConvertToKeyValue(rawRequest); - } - - public override void Parse() - { - CommandName = RequestKeyValues.Keys.First(); - - if (RequestKeyValues.ContainsKey("id")) - { - ushort operationID; - if (!ushort.TryParse(RequestKeyValues["id"], out operationID)) - { - throw new GPParseException("operation id is invalid."); - } - OperationID = operationID; - } - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Abstraction/BaseClass/ResponseBase.cs b/src/Servers/PresenceSearchPlayer/src/Abstraction/BaseClass/ResponseBase.cs deleted file mode 100755 index 6e68b53b6..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Abstraction/BaseClass/ResponseBase.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass -{ - public abstract class ResponseBase : UniSpy.Server.Core.Abstraction.BaseClass.ResponseBase - { - protected new ResultBase _result => (ResultBase)base._result; - protected new RequestBase _request => (RequestBase)base._request; - public new string SendingBuffer { get => (string)base.SendingBuffer; protected set => base.SendingBuffer = value; } - public ResponseBase(RequestBase request, ResultBase result) : base(request, result) - { - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Abstraction/BaseClass/ResultBase.cs b/src/Servers/PresenceSearchPlayer/src/Abstraction/BaseClass/ResultBase.cs deleted file mode 100755 index 61f3cbc51..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Abstraction/BaseClass/ResultBase.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass -{ - public abstract class ResultBase : UniSpy.Server.Core.Abstraction.BaseClass.ResultBase - { - public ResultBase() - { - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Abstraction/Interface/IStorageOperation.cs b/src/Servers/PresenceSearchPlayer/src/Abstraction/Interface/IStorageOperation.cs deleted file mode 100644 index d49957912..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Abstraction/Interface/IStorageOperation.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.PresenceSearchPlayer.Contract.Result; -using UniSpy.Server.Core.Database.DatabaseModel; - -namespace UniSpy.Server.PresenceSearchPlayer.Abstraction.Interface -{ - public interface IStorageOperation - { - int? GetProfileId(string email, string password, string nickName, int? partnerId); - bool VerifyEmail(string email); - bool VerifyEmailAndPassword(string email, string password); - void AddUser(User user); - void AddProfile(Profile profile); - void AddSubProfile(Subprofile subprofile); - void UpdateProfile(Profile profile); - void UpdateSubProfile(Subprofile subProfile); - User GetUser(string email); - Profile GetProfile(int userId, string nickName); - Subprofile GetSubProfile(int profileId, int namespaceId, int productId); - List GetAllNickAndUniqueNick(string email, string password, int namespaceId); - List GetFriendsInfo(int profileId, int namespaceId, string gameName); - List GetMatchedProfileIdInfos(List profileIds, int namespaceId); - List GetMatchedInfosByNick(string nickName); - List GetMatchedInfosByEmail(string email); - List GetMatchedInfosByNickAndEmail(string nickName, string email); - List GetMatchedInfosByUniqueNickAndNamespaceId(string uniqueNick, int namespaceId); - List GetMatchedInfosByNamespaceId(List namespaceIds, string uniqueNick); - bool IsUniqueNickExist(string uniqueNick, int namespaceId, string gameName); - bool IsEmailExist(string email); - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Aggregate/PSPRequestName.cs b/src/Servers/PresenceSearchPlayer/src/Aggregate/PSPRequestName.cs deleted file mode 100755 index d97ebe6bd..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Aggregate/PSPRequestName.cs +++ /dev/null @@ -1,46 +0,0 @@ -namespace UniSpy.Server.PresenceSearchPlayer.Aggregate -{ - public class PSPRequestName - { - /// - /// Search account existance - /// - public const string Search = "search"; - /// - /// Check if the email is existed - /// - public const string Valid = "valid"; - /// - /// Search an user with nick name - /// - public const string Nicks = "nicks"; - /// - /// get the players match search condition - /// - public const string PMatch = "pmatch"; - /// - /// Check if the account is valid and password is correct - /// - public const string Check = "check"; - /// - /// Create a new user - /// - public const string NewUser = "newuser"; - /// - /// Search an user with uniquenick - /// - public const string SearchUnique = "searchunique"; - /// - /// Get the accounts information which match search condition - /// - public const string Others = "others"; - /// - /// search other players friend list to see who is in his list? - /// - public const string OtherList = "otherslist"; - /// - /// search a user with uniquenick and namespaceid - /// - public const string UniqueSearch = "uniquesearch"; - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Application/Client.cs b/src/Servers/PresenceSearchPlayer/src/Application/Client.cs deleted file mode 100644 index 4eaa33c26..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Application/Client.cs +++ /dev/null @@ -1,17 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Handler; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Encryption; - -namespace UniSpy.Server.PresenceSearchPlayer.Application -{ - public sealed class Client : ClientBase - { - public Client(IConnection connection, IServer server) : base(connection, server) - { - Info = new ClientInfo(); - } - - protected override ISwitcher CreateSwitcher(object buffer) => new CmdSwitcher(this, UniSpyEncoding.GetString((byte[])buffer)); - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Application/ClientInfo.cs b/src/Servers/PresenceSearchPlayer/src/Application/ClientInfo.cs deleted file mode 100644 index c6315ffcb..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Application/ClientInfo.cs +++ /dev/null @@ -1,11 +0,0 @@ -using UniSpy.Server.Core.Abstraction.BaseClass; - -namespace UniSpy.Server.PresenceSearchPlayer.Application -{ - public sealed class ClientInfo : ClientInfoBase - { - public ClientInfo( ) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Application/Program.cs b/src/Servers/PresenceSearchPlayer/src/Application/Program.cs deleted file mode 100755 index 302b8abb6..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Application/Program.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using UniSpy.Server.Core.Logging; - -namespace UniSpy.Server.PresenceSearchPlayer.Application -{ - public class Program - { - static void Main(string[] args) - { - try - { - new ServerLauncher().Start(); - Console.WriteLine("Press < Q > to exit. "); - while (Console.ReadKey().Key != ConsoleKey.Q) { } - } - catch (System.Exception e) - { - LogWriter.LogError(e); - } - } - } -} - diff --git a/src/Servers/PresenceSearchPlayer/src/Application/Server.cs b/src/Servers/PresenceSearchPlayer/src/Application/Server.cs deleted file mode 100644 index 51a79de7c..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Application/Server.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Net; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Network.Tcp.Server; - -namespace UniSpy.Server.PresenceSearchPlayer.Application -{ - public sealed class Server : ServerBase - { - static Server() - { - _name = "PresenceSearchPlayer"; - } - public Server() { } - - public Server(IConnectionManager manager) : base(manager) { } - protected override IClient CreateClient(IConnection connection) => new Client(connection, this); - - protected override IConnectionManager CreateConnectionManager(IPEndPoint endPoint) => new TcpConnectionManager(IPEndPoint.Parse("0.0.0.0:29901")); - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Application/ServerLauncher.cs b/src/Servers/PresenceSearchPlayer/src/Application/ServerLauncher.cs deleted file mode 100644 index 2340ed426..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Application/ServerLauncher.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Core.Abstraction.BaseClass.Factory; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.PresenceSearchPlayer.Application -{ - public sealed class ServerLauncher : ServerLauncherBase - { - protected override List LaunchNetworkService() => new List { new Server() }; - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Application/StorageOperation.cs b/src/Servers/PresenceSearchPlayer/src/Application/StorageOperation.cs deleted file mode 100644 index 7534cb224..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Application/StorageOperation.cs +++ /dev/null @@ -1,360 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using UniSpy.Server.PresenceSearchPlayer.Abstraction.Interface; -using UniSpy.Server.PresenceSearchPlayer.Contract.Result; -using UniSpy.Server.Core.Database.DatabaseModel; - -namespace UniSpy.Server.PresenceSearchPlayer.Application -{ - internal sealed class StorageOperation : IStorageOperation - { - public static IStorageOperation Persistance = new StorageOperation(); - public bool VerifyEmail(string email) - { - using (var db = new UniSpyContext()) - { - return db.Users.Where(e => e.Email == email).Count() < 1; - } - } - public bool VerifyEmailAndPassword(string email, string password) - { - using (var db = new UniSpyContext()) - { - return db.Users.Where(u => u.Email == email && u.Password == password).Count() < 1; - } - } - public int? GetProfileId(string email, string password, string nickName, int? partnerId) - { - using (var db = new UniSpyContext()) - { - // Not every game uses PartnerId; optional - var result = from p in db.Profiles - join u in db.Users on p.Userid equals u.UserId - join sp in db.Subprofiles on p.ProfileId equals sp.ProfileId - where u.Email.Equals(email) - && u.Password.Equals(password) - && p.Nick.Equals(nickName) - || sp.PartnerId.Equals(partnerId) - select p.ProfileId; - - if (result.Count() == 1) - { - return result.First(); - } - else - { - return null; - } - } - } - - public void AddSubProfile(Subprofile subProfile) - { - using (var db = new UniSpyContext()) - { - db.Subprofiles.Add(subProfile); - db.SaveChanges(); - } - } - - public void AddProfile(Profile profile) - { - using (var db = new UniSpyContext()) - { - db.Profiles.Add(profile); - db.SaveChanges(); - } - } - public void AddUser(User user) - { - using (var db = new UniSpyContext()) - { - db.Users.Add(user); - db.SaveChanges(); - } - } - public void UpdateProfile(Profile profile) - { - using (var db = new UniSpyContext()) - { - db.Profiles.Update(profile); - db.SaveChanges(); - } - } - public void UpdateSubProfile(Subprofile subprofile) - { - using (var db = new UniSpyContext()) - { - db.Subprofiles.Update(subprofile); - db.SaveChanges(); - } - } - - public User GetUser(string email) - { - using (var db = new UniSpyContext()) - { - return db.Users.Where(u => u.Email == email).Select(u => u).FirstOrDefault(); - } - } - - public Profile GetProfile(int userId, string nickName) - { - using (var db = new UniSpyContext()) - { - return db.Profiles.Where(p => p.Userid == userId && p.Nick == nickName).FirstOrDefault(); - } - } - - public Subprofile GetSubProfile(int profileId, int namespaceId, int productId) - { - using (var db = new UniSpyContext()) - { - return db.Subprofiles.Where(s => - s.ProfileId == profileId && - s.NamespaceId == namespaceId && - s.ProductId == productId).FirstOrDefault(); - } - } - - public List GetAllNickAndUniqueNick(string email, string password, int namespaceId) - { - using (var db = new UniSpyContext()) - { - var result = from u in db.Users - join p in db.Profiles on u.UserId equals p.Userid - join n in db.Subprofiles on p.ProfileId equals n.ProfileId - where u.Email == email - && u.Password == password - && n.NamespaceId == namespaceId - select new NicksDataModel - { - NickName = p.Nick, - UniqueNick = n.Uniquenick - }; - return result.ToList(); - } - } - - public List GetFriendsInfo(int profileId, int namespaceId, string gameName) - { - var dataList = new List(); - using (var db = new UniSpyContext()) - { - var result = from b in db.Friends - where b.ProfileId == profileId && b.Namespaceid == namespaceId - select b.Targetid; - - foreach (var info in result) - { - var b = from p in db.Profiles - join n in db.Subprofiles on p.ProfileId equals n.ProfileId - join u in db.Users on p.Userid equals u.UserId - where n.NamespaceId == namespaceId - && n.ProfileId == info && n.Gamename == gameName - select new OthersDatabaseModel - { - ProfileId = p.ProfileId, - Nick = p.Nick, - Uniquenick = n.Uniquenick, - Lastname = p.Lastname, - Firstname = p.Firstname, - Userid = u.UserId, - Email = u.Email - }; - - dataList.Add(b.First()); - } - } - return dataList; - } - - public List GetMatchedProfileIdInfos(List profileIds, int namespaceId) - { - var dataList = new List(); - using (var db = new UniSpyContext()) - { - foreach (var pid in profileIds) - { - var result = from n in db.Subprofiles - where n.ProfileId == pid - && n.NamespaceId == namespaceId - //select new { uniquenick = n.Uniquenick }; - select new OthersListDatabaseModel - { - ProfileId = n.ProfileId, - Uniquenick = n.Uniquenick - }; - - dataList.Add(result.First()); - } - } - return dataList; - } - - public List GetMatchedInfosByNick(string nickName) - { - using (var db = new UniSpyContext()) - { - var result = from p in db.Profiles - join n in db.Subprofiles on p.ProfileId equals n.ProfileId - join u in db.Users on p.Userid equals u.UserId - where p.Nick == nickName - //&& n.Namespaceid == _request.NamespaceID - select new SearchDataBaseModel - { - ProfileId = n.ProfileId, - Nick = p.Nick, - Uniquenick = n.Uniquenick, - Email = u.Email, - Firstname = p.Firstname, - Lastname = p.Lastname, - NamespaceID = n.NamespaceId - }; - return result.ToList(); - } - - } - - public List GetMatchedInfosByEmail(string email) - { - - using (var db = new UniSpyContext()) - - { - var result = from p in db.Profiles - join n in db.Subprofiles on p.ProfileId equals n.ProfileId - join u in db.Users on p.Userid equals u.UserId - where u.Email == email - select new SearchDataBaseModel - { - ProfileId = n.ProfileId, - Nick = p.Nick, - Uniquenick = n.Uniquenick, - Email = u.Email, - Firstname = p.Firstname, - Lastname = p.Lastname, - NamespaceID = n.NamespaceId - }; - return result.ToList(); - } - - } - - public List GetMatchedInfosByNickAndEmail(string nickName, string email) - { - using (var db = new UniSpyContext()) - { - var result = from p in db.Profiles - join n in db.Subprofiles on p.ProfileId equals n.ProfileId - join u in db.Users on p.Userid equals u.UserId - where p.Nick == nickName && u.Email == email - //&& n.Namespaceid == _request.NamespaceID - //&& n.Gamename == _request.GameName - //&& n.Partnerid == _request.PartnerID - select new SearchDataBaseModel - { - ProfileId = n.ProfileId, - Nick = p.Nick, - Uniquenick = n.Uniquenick, - Email = u.Email, - Firstname = p.Firstname, - Lastname = p.Lastname, - NamespaceID = n.NamespaceId - }; - return result.ToList(); - } - } - - public List GetMatchedInfosByUniqueNickAndNamespaceId(string uniqueNick, int namespaceId) - { - - using (var db = new UniSpyContext()) - { - var result = from p in db.Profiles - join n in db.Subprofiles on p.ProfileId equals n.ProfileId - join u in db.Users on p.Userid equals u.UserId - where n.Uniquenick == uniqueNick - && n.NamespaceId == namespaceId - //&& n.Gamename == _request.GameName - //&& n.Partnerid == _request.PartnerID - select new SearchDataBaseModel - { - ProfileId = n.ProfileId, - Nick = p.Nick, - Uniquenick = n.Uniquenick, - Email = u.Email, - Firstname = p.Firstname, - Lastname = p.Lastname, - NamespaceID = n.NamespaceId - }; - return result.ToList(); - } - - } - - public List GetMatchedInfosByNamespaceId(List namespaceIds, string uniqueNick) - { - using (var db = new UniSpyContext()) - { - var dataList = new List(); - foreach (var nsId in namespaceIds) - { - var result = from p in db.Profiles - join n in db.Subprofiles on p.ProfileId equals n.ProfileId - join u in db.Users on p.Userid equals u.UserId - where n.Uniquenick == uniqueNick - && n.NamespaceId == nsId - select new SearchUniqueDatabaseModel - { - ProfileId = n.ProfileId, - Nick = p.Nick, - Uniquenick = n.Uniquenick, - Email = u.Email, - Firstname = p.Firstname, - Lastname = p.Lastname, - NamespaceID = n.NamespaceId - }; - dataList.Add(result.First()); - } - return dataList; - } - } - - public bool IsUniqueNickExist(string uniqueNick, int namespaceId, string gameName) - { - using (var db = new UniSpyContext()) - { - var result = from p in db.Profiles - join n in db.Subprofiles on p.ProfileId equals n.ProfileId - where n.Uniquenick == uniqueNick - && n.NamespaceId == namespaceId - && n.Gamename == gameName - select p.ProfileId; - - if (result.Count() != 0) - { - return true; - } - - return false; - } - } - public bool IsEmailExist(string email) - { - using (var db = new UniSpyContext()) - { - var result = from u in db.Users - //According to FSW partnerid is not nessesary - where u.Email == email - select u.UserId; - - if (result.Count() == 0) - { - return false; - } - return true; - } - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Request/CheckRequest.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Request/CheckRequest.cs deleted file mode 100755 index eff8f7e75..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Request/CheckRequest.cs +++ /dev/null @@ -1,42 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; -using UniSpy.Server.Core.Misc; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Request -{ - - public sealed class CheckRequest : RequestBase - { - // \check\\nick\\email\\partnerid\0\passenc\\gamename\gmtest\final\ - public CheckRequest(string rawRequest) : base(rawRequest) - { - } - - public string Nick { get; private set; } - public string Password { get; private set; } - public string Email { get; private set; } - public int? PartnerId { get; private set; } - public override void Parse() - { - base.Parse(); - Password = PasswordEncoder.ProcessPassword(RequestKeyValues); - if (!RequestKeyValues.ContainsKey("nick") || !RequestKeyValues.ContainsKey("email") || Password is null) - { - throw new GPParseException("check request is incompelete."); - } - - if (!GameSpyUtils.IsEmailFormatCorrect(RequestKeyValues["email"])) - { - throw new GPParseException("email format is incorrect"); - } - - Nick = RequestKeyValues["nick"]; - Email = RequestKeyValues["email"]; - - if (RequestKeyValues.ContainsKey("partnerid")) - { - PartnerId = int.Parse(RequestKeyValues["partnerid"]); - } - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Request/NewUserRequest.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Request/NewUserRequest.cs deleted file mode 100755 index ba3bcff4d..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Request/NewUserRequest.cs +++ /dev/null @@ -1,110 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; -using UniSpy.Server.Core.Misc; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Request -{ - - public sealed class NewUserRequest : RequestBase - { - public int ProductID { get; private set; } - public int GamePort { get; private set; } - public string CDKey { get; private set; } - public bool HasGameNameFlag { get; private set; } - public bool HasProductIDFlag { get; private set; } - public bool HasCDKeyEncFlag { get; private set; } - public bool HasPartnerIDFlag { get; private set; } - public bool HasGamePortFlag { get; private set; } - public string Nick { get; private set; } - public string Email { get; private set; } - public string Password { get; private set; } - public string Uniquenick { get; private set; } - public int PartnerID { get; private set; } - public string GameName { get; private set; } - public int NamespaceID { get; private set; } - public NewUserRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - Password = PasswordEncoder.ProcessPassword(RequestKeyValues); - - if (!RequestKeyValues.ContainsKey("nick")) - { - throw new GPParseException("nickname is missing."); - } - if (!RequestKeyValues.ContainsKey("email")) - { - throw new GPParseException("email is missing."); - } - if (!GameSpyUtils.IsEmailFormatCorrect(RequestKeyValues["email"])) - { - throw new GPParseException("email format is incorrect."); - } - Nick = RequestKeyValues["nick"]; - Email = RequestKeyValues["email"]; - - if (RequestKeyValues.ContainsKey("uniquenick") && RequestKeyValues.ContainsKey("namespaceid")) - { - if (RequestKeyValues.ContainsKey("namespaceid")) - { - int namespaceID; - if (!int.TryParse(RequestKeyValues["namespaceid"], out namespaceID)) - { - throw new GPParseException("namespaceid is incorrect."); - } - NamespaceID = namespaceID; - } - Uniquenick = RequestKeyValues["uniquenick"]; - } - ParseOtherInfo(); - } - - private void ParseOtherInfo() - { - //parse other info - if (RequestKeyValues.ContainsKey("partnerid")) - { - int partnerid; - if (!int.TryParse(RequestKeyValues["partnerid"], out partnerid)) - { - throw new GPParseException("partnerid is incorrect."); - } - HasPartnerIDFlag = true; - PartnerID = partnerid; - } - if (RequestKeyValues.ContainsKey("productid")) - { - int productid; - if (!int.TryParse(RequestKeyValues["productid"], out productid)) - { - throw new GPParseException("productid is incorrect."); - } - HasProductIDFlag = true; - ProductID = productid; - } - if (RequestKeyValues.ContainsKey("gamename")) - { - HasGameNameFlag = true; - GameName = RequestKeyValues["gamename"]; - } - if (RequestKeyValues.ContainsKey("port")) - { - int port; - if (!int.TryParse(RequestKeyValues["port"], out port)) - { - throw new GPParseException("port is incorrect."); - } - HasGamePortFlag = true; - GamePort = port; - } - if (RequestKeyValues.ContainsKey("cdkey")) - { - HasCDKeyEncFlag = true; - CDKey = RequestKeyValues["cdkey"]; - } - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Request/NicksRequest.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Request/NicksRequest.cs deleted file mode 100755 index b2d3e5fdb..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Request/NicksRequest.cs +++ /dev/null @@ -1,50 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; -using UniSpy.Server.Core.Misc; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Request -{ - - public sealed class NicksRequest : RequestBase - { - public NicksRequest(string rawRequest) : base(rawRequest) - { - } - - public string Password { get; private set; } - public string Email { get; private set; } - public int NamespaceID { get; private set; } - public bool IsRequireUniqueNicks { get; private set; } - - public override void Parse() - { - base.Parse(); - Password = PasswordEncoder.ProcessPassword(RequestKeyValues); - - if (!RequestKeyValues.ContainsKey("email")) - { - throw new GPParseException("email is missing."); - } - - IsRequireUniqueNicks = true; - - if (RequestKeyValues.ContainsKey("pass")) - { - // Old games might send an error is unique nicknames are sent (like GSA 1.0) - IsRequireUniqueNicks = false; - } - - Email = RequestKeyValues["email"]; - - if (RequestKeyValues.ContainsKey("namespaceid")) - { - int namespaceID; - if (!int.TryParse(RequestKeyValues["namespaceid"], out namespaceID)) - { - throw new GPParseException("namespaceid is incorrect."); - } - NamespaceID = namespaceID; - } - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Request/OthersListRequest.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Request/OthersListRequest.cs deleted file mode 100755 index a0953363b..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Request/OthersListRequest.cs +++ /dev/null @@ -1,50 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; -using System.Collections.Generic; -using System.Linq; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Request -{ - - //request: \otherslist\sesskey\\profileid\\numopids\ - //\opids\|||******\namespaceid\<>\gamename\<>\final\ - - public sealed class OthersListRequest : RequestBase - { - public List ProfileIDs { get; private set; } - public int NamespaceID { get; private set; } - public OthersListRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - - if (!RequestKeyValues.ContainsKey("opids") || !RequestKeyValues.ContainsKey("namespaceid")) - { - throw new GPParseException("opids or namespaceid is missing."); - } - - try - { - ProfileIDs = RequestKeyValues["opids"].TrimStart('|').Split('|').Select(int.Parse).ToList(); - } - catch (System.Exception e) - { - throw new GPParseException("opids is incorrect", e); - } - - if (RequestKeyValues.ContainsKey("namespaceid")) - { - int namespaceID; - if (!int.TryParse(RequestKeyValues["namespaceid"], out namespaceID)) - { - throw new GPParseException("namespaceid is incorrect."); - } - - NamespaceID = namespaceID; - } - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Request/OthersRequest.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Request/OthersRequest.cs deleted file mode 100755 index 09e7c508c..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Request/OthersRequest.cs +++ /dev/null @@ -1,52 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Request -{ - - public sealed class OthersRequest : RequestBase - { - public OthersRequest(string rawRequest) : base(rawRequest) - { - } - - public int ProfileId { get; private set; } - public string GameName { get; private set; } - public int NamespaceID { get; private set; } - public override void Parse() - { - base.Parse(); - - - if (!RequestKeyValues.ContainsKey("gamename")) - { - throw new GPParseException("gamename is missing."); - } - - if (!RequestKeyValues.ContainsKey("profileid") || !RequestKeyValues.ContainsKey("namespaceid")) - { - throw new GPParseException("profileid or namespaceid is missing."); - } - - int profileID = 0; - if (!RequestKeyValues.ContainsKey("profileid") && !int.TryParse(RequestKeyValues["profileid"], out profileID)) - { - throw new GPParseException("profileid is incorrect."); - } - - if (RequestKeyValues.ContainsKey("namespaceid")) - { - int namespaceID; - if (!int.TryParse(RequestKeyValues["namespaceid"], out namespaceID)) - { - throw new GPParseException("namespaceid is incorrect."); - } - - NamespaceID = namespaceID; - } - - ProfileId = profileID; - GameName = RequestKeyValues["gamename"]; - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Request/SearchRequest.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Request/SearchRequest.cs deleted file mode 100755 index f6b87c8ec..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Request/SearchRequest.cs +++ /dev/null @@ -1,118 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Request -{ - public enum SearchRequestType - { - NickSearch, - NickEmailSearch, - UniquenickNamespaceIDSearch, - EmailSearch - } - - - public sealed class SearchRequest : RequestBase - { - public int SkipNum { get; private set; } - public SearchRequestType RequestType { get; private set; } - public string GameName { get; private set; } - public int ProfileId { get; private set; } - public int PartnerID { get; private set; } - public string Email { get; private set; } - public string Nick { get; private set; } - public string Uniquenick { get; private set; } - public int NamespaceID { get; private set; } - public SearchRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - - - if (!RequestKeyValues.ContainsKey("profileid") - && !RequestKeyValues.ContainsKey("nick") - && !RequestKeyValues.ContainsKey("email") - && !RequestKeyValues.ContainsKey("namespaceid") - && !RequestKeyValues.ContainsKey("gamename")) - { - throw new GPParseException(" Search request is incomplete."); - } - - if (RequestKeyValues.ContainsKey("gamename")) - { - GameName = RequestKeyValues["gamename"]; - } - - if (RequestKeyValues.ContainsKey("profileid")) - { - int profileID; - if (!int.TryParse(RequestKeyValues["profileid"], out profileID)) - { - throw new GPParseException("profileid is incorrect."); - - } - ProfileId = profileID; - } - - if (RequestKeyValues.ContainsKey("partnerid")) - { - int partnerID; - if (!int.TryParse(RequestKeyValues["partnerid"], out partnerID)) - { - throw new GPParseException("partnerid is incorrect."); - } - PartnerID = partnerID; - } - - if (RequestKeyValues.ContainsKey("skip")) - { - int skip; - if (!int.TryParse(RequestKeyValues["skip"], out skip)) - { - throw new GPParseException("skip number is incorrect."); - } - SkipNum = skip; - } - - if (RequestKeyValues.ContainsKey("uniquenick") && RequestKeyValues.ContainsKey("namespaceid")) - { - if (RequestKeyValues.ContainsKey("namespaceid")) - { - int namespaceID; - if (!int.TryParse(RequestKeyValues["namespaceid"], out namespaceID)) - { - throw new GPParseException("namespaceid is incorrect."); - } - NamespaceID = namespaceID; - } - RequestType = SearchRequestType.UniquenickNamespaceIDSearch; - - Uniquenick = RequestKeyValues["uniquenick"]; - } - else if (RequestKeyValues.ContainsKey("nick") && RequestKeyValues.ContainsKey("email")) - { - RequestType = SearchRequestType.NickEmailSearch; - Nick = RequestKeyValues["nick"]; - Email = RequestKeyValues["email"]; - } - else if (RequestKeyValues.ContainsKey("nick")) - { - RequestType = SearchRequestType.NickSearch; - Nick = RequestKeyValues["nick"]; - } - else if (RequestKeyValues.ContainsKey("email")) - { - //\search\\sesskey\0\profileid\0\namespaceid\1\email\spyguy@gamespy.cn\gamename\conflictsopc\final\ - Email = RequestKeyValues["email"]; - RequestType = SearchRequestType.EmailSearch; - } - else - { - throw new GPParseException("unknown search request type."); - } - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Request/SearchUniqueRequest.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Request/SearchUniqueRequest.cs deleted file mode 100755 index b01d1cebe..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Request/SearchUniqueRequest.cs +++ /dev/null @@ -1,45 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; -using System.Collections.Generic; -using System.Linq; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Request -{ - - public sealed class SearchUniqueRequest : RequestBase - { - public string Uniquenick { get; private set; } - public List NamespaceIds { get; private set; } - public SearchUniqueRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - - if (!RequestKeyValues.ContainsKey("uniquenick") || !RequestKeyValues.ContainsKey("namespaces")) - { - throw new GPParseException("searchunique request is incomplete."); - } - - try - { - Uniquenick = RequestKeyValues["uniquenick"]; - } - catch - { - throw new GPParseException("uniquenick is missing."); - } - - try - { - NamespaceIds = RequestKeyValues["namespaces"].TrimStart(',').Split(',').Select(int.Parse).ToList(); - } - catch - { - throw new GPParseException("namespaces is incorrect."); - } - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Request/UniqueSearchRequest.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Request/UniqueSearchRequest.cs deleted file mode 100755 index 37a724dde..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Request/UniqueSearchRequest.cs +++ /dev/null @@ -1,50 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Request -{ - - - public sealed class UniqueSearchRequest : RequestBase - { - public string PreferredNick { get; private set; } - public int NamespaceID { get; private set; } - public UniqueSearchRequest(string rawRequest) : base(rawRequest) - { - } - - public string GameName { get; private set; } - - public override void Parse() - { - base.Parse(); - - - if (!RequestKeyValues.ContainsKey("preferrednick")) - { - throw new GPParseException("preferrednick is missing."); - } - - PreferredNick = RequestKeyValues["preferrednick"]; - - if (!RequestKeyValues.ContainsKey("gamename")) - { - throw new GPParseException("gamename is missing."); - } - GameName = RequestKeyValues["gamename"]; - - if (!RequestKeyValues.ContainsKey("namespaceid")) - { - throw new GPParseException("namespaceid is missing."); - } - - int namespaceID; - if (!int.TryParse(RequestKeyValues["namespaceid"], out namespaceID)) - { - throw new GPParseException("namespaceid is incorrect."); - } - - NamespaceID = namespaceID; - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Request/ValidRequest.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Request/ValidRequest.cs deleted file mode 100755 index f636289fe..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Request/ValidRequest.cs +++ /dev/null @@ -1,42 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; -using UniSpy.Server.Core.Misc; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Request -{ - - public sealed class ValidRequest : RequestBase - { - public ValidRequest(string rawRequest) : base(rawRequest) - { - } - - public int NamespaceID { get; private set; } - public string Email { get; private set; } - public string GameName { get; private set; } - - public override void Parse() - { - base.Parse(); - - - if (!RequestKeyValues.ContainsKey("email") && !GameSpyUtils.IsEmailFormatCorrect(RequestKeyValues["email"])) - { - throw new GPParseException("valid request is incomplete."); - } - - Email = RequestKeyValues["email"]; - - if (RequestKeyValues.ContainsKey("namespaceid")) - { - int namespaceID; - if (!int.TryParse(RequestKeyValues["namespaceid"], out namespaceID)) - { - throw new GPParseException("namespaceid is incorrect."); - } - - NamespaceID = namespaceID; - } - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Response/CheckResponse.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Response/CheckResponse.cs deleted file mode 100755 index aaafdbe52..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Response/CheckResponse.cs +++ /dev/null @@ -1,26 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Contract.Result; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Response -{ - public sealed class CheckResponse : ResponseBase - { - private new CheckResult _result => (CheckResult)base._result; - - public CheckResponse(RequestBase request, ResultBase result) : base(request, result) - { - } - - public override void Build() - { - if (_result.ProfileId is null) - { - SendingBuffer = $@"\cur\1\final\"; - } - else - { - SendingBuffer = $@"\cur\0\pid\{_result.ProfileId}\final\"; - } - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Response/NewUserResponse.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Response/NewUserResponse.cs deleted file mode 100755 index 40bebee6f..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Response/NewUserResponse.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Contract.Request; -using UniSpy.Server.PresenceSearchPlayer.Contract.Result; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Response -{ - public class NewUserResponse : ResponseBase - { - protected new NewUserRequest _request => (NewUserRequest)base._request; - protected new NewUserResult _result => (NewUserResult)base._result; - public NewUserResponse(NewUserRequest request, NewUserResult result) : base(request, result) - { - } - public override void Build() - { - SendingBuffer = $@"\nur\\pid\{_result.SubProfile.ProfileId}\final\"; - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Response/NicksResponse.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Response/NicksResponse.cs deleted file mode 100755 index 547d28cf6..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Response/NicksResponse.cs +++ /dev/null @@ -1,32 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Contract.Request; -using UniSpy.Server.PresenceSearchPlayer.Contract.Result; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Response -{ - public sealed class NicksResponse : ResponseBase - { - private new NicksRequest _request => (NicksRequest)base._request; - private new NicksResult _result => (NicksResult)base._result; - - public NicksResponse(NicksRequest request, NicksResult result) : base(request, result) - { - } - - public override void Build() - { - SendingBuffer = @"\nr\"; - foreach (var info in _result.DataBaseResults) - { - SendingBuffer += @"\nick\"; - SendingBuffer += info.NickName; - if (_request.IsRequireUniqueNicks) - { - SendingBuffer += @"\uniquenick\"; - SendingBuffer += info.UniqueNick; - } - } - SendingBuffer += @"\ndone\final\"; - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Response/OthersListResponse.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Response/OthersListResponse.cs deleted file mode 100755 index a6eb7391f..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Response/OthersListResponse.cs +++ /dev/null @@ -1,25 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Contract.Result; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Response -{ - public sealed class OthersListResponse : ResponseBase - { - private new OthersListResult _result => (OthersListResult)base._result; - public OthersListResponse(RequestBase request, OthersListResult result) : base(request, result) - { - } - - public override void Build() - { - SendingBuffer = @"\otherslist\"; - foreach (var info in _result.DatabaseResults) - { - SendingBuffer += $@"\o\{info.ProfileId}"; - SendingBuffer += $@"\uniquenick\{info.Uniquenick}"; - } - - SendingBuffer += @"oldone"; - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Response/OthersResponse.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Response/OthersResponse.cs deleted file mode 100755 index 749821d3f..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Response/OthersResponse.cs +++ /dev/null @@ -1,29 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Contract.Result; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Response -{ - public sealed class OthersResponse : ResponseBase - { - private new OthersResult _result => (OthersResult)base._result; - public OthersResponse(RequestBase request, OthersResult result) : base(request, result) - { - } - - public override void Build() - { - SendingBuffer = @"\others\"; - - foreach (var info in _result.DatabaseResults) - { - SendingBuffer += @"\o\" + info.ProfileId; - SendingBuffer += @"\nick\" + info.Nick; - SendingBuffer += @"\uniquenick\" + info.Uniquenick; - SendingBuffer += @"\first\" + info.Firstname; - SendingBuffer += @"\last\" + info.Lastname; - SendingBuffer += @"\email\" + info.Email; - } - SendingBuffer += @"\odone\final\"; - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Response/SearchResponse.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Response/SearchResponse.cs deleted file mode 100755 index f27525567..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Response/SearchResponse.cs +++ /dev/null @@ -1,32 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Contract.Result; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Response -{ - public sealed class SearchResponse : ResponseBase - { - private new SearchResult _result => (SearchResult)base._result; - - public SearchResponse(RequestBase request, SearchResult result) : base(request, result) - { - } - - - public override void Build() - { - SendingBuffer = @"\bsr\"; - foreach (var info in _result.DataBaseResults) - { - SendingBuffer += info.ProfileId.ToString(); - SendingBuffer += @"\nick\" + info.Nick; - SendingBuffer += @"\uniquenick\" + info.Uniquenick; - SendingBuffer += @"\namespaceid\" + info.NamespaceID; - SendingBuffer += @"\firstname\" + info.Firstname; - SendingBuffer += @"\lastname\" + info.Lastname; - SendingBuffer += @"\email\" + info.Email; - } - //TODO check how many user data is allowed send to the client - SendingBuffer += @"\bsrdone\\more\0\final\"; - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Response/SearchUniqueResponse.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Response/SearchUniqueResponse.cs deleted file mode 100755 index 7bce0b6ea..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Response/SearchUniqueResponse.cs +++ /dev/null @@ -1,30 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Contract.Result; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Response -{ - public sealed class SearchUniqueResponse : ResponseBase - { - private new SearchUniqueResult _result => (SearchUniqueResult)base._result; - - public SearchUniqueResponse(RequestBase request, SearchUniqueResult result) : base(request, result) - { - } - - public override void Build() - { - SendingBuffer = @"\bsr"; - foreach (var info in _result.DatabaseResults) - { - SendingBuffer += info.ProfileId.ToString(); - SendingBuffer += @"\nick\" + info.Nick; - SendingBuffer += @"\uniquenick\" + info.Uniquenick; - SendingBuffer += @"\namespaceid\" + info.NamespaceID; - SendingBuffer += @"\firstname\" + info.Firstname; - SendingBuffer += @"\lastname\" + info.Lastname; - SendingBuffer += @"\email\" + info.Email; - } - SendingBuffer += @"\bsrdone\\more\0"; - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Response/UniqueSearchResponse.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Response/UniqueSearchResponse.cs deleted file mode 100755 index cc0eb56ba..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Response/UniqueSearchResponse.cs +++ /dev/null @@ -1,28 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Contract.Request; -using UniSpy.Server.PresenceSearchPlayer.Contract.Result; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Response -{ - public sealed class UniqueSearchResponse : ResponseBase - { - private new UniqueSearchRequest _request => (UniqueSearchRequest)base._request; - private new UniqueSearchResult _result => (UniqueSearchResult)base._result; - public UniqueSearchResponse(UniqueSearchRequest request, UniqueSearchResult result) : base(request, result) - { - } - - - public override void Build() - { - if (_result.IsUniquenickExist) - { - SendingBuffer = @"\us\1\nick\Choose another name\usdone\final\"; - } - else - { - SendingBuffer = $@"\us\1\nick\{_request.PreferredNick}\usdone\final\"; - } - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Response/ValidResponse.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Response/ValidResponse.cs deleted file mode 100755 index 5f893547a..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Response/ValidResponse.cs +++ /dev/null @@ -1,27 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Contract.Request; -using UniSpy.Server.PresenceSearchPlayer.Contract.Result; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Response -{ - public sealed class ValidResponse : ResponseBase - { - private new ValidResult _result => (ValidResult)base._result; - private new ValidRequest _request => (ValidRequest)base._request; - public ValidResponse(RequestBase request, ValidResult result) : base(request, result) - { - } - - public override void Build() - { - if (_result.IsAccountValid) - { - SendingBuffer = @"\vr\1\final\"; - } - else - { - SendingBuffer = @"\vr\0\final\"; - } - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Result/CheckResult.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Result/CheckResult.cs deleted file mode 100755 index 4bc894f1e..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Result/CheckResult.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Result -{ - public sealed class CheckResult : ResultBase - { - public int? ProfileId { get; set; } - public CheckResult() - { - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Result/NewUserResult.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Result/NewUserResult.cs deleted file mode 100755 index b299143b0..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Result/NewUserResult.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.Core.Database.DatabaseModel; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Result -{ - public sealed class NewUserResult : ResultBase - { - public User User; - public Profile Profile; - public Subprofile SubProfile; - public NewUserResult() { } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Result/NicksResult.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Result/NicksResult.cs deleted file mode 100755 index 0849aff9c..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Result/NicksResult.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using System.Collections.Generic; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Result -{ - public sealed class NicksDataModel - { - public string NickName; - public string UniqueNick; - } - - public sealed class NicksResult : ResultBase - { - public List DataBaseResults { get; set; } - public bool IsRequireUniqueNicks { get; set; } - public NicksResult() - { - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Result/OthersListResult.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Result/OthersListResult.cs deleted file mode 100755 index ca993ed6d..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Result/OthersListResult.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using System.Collections.Generic; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Result -{ - public sealed class OthersListDatabaseModel - { - public int ProfileId; - public string Uniquenick; - } - public sealed class OthersListResult : ResultBase - { - public List DatabaseResults; - public OthersListResult() - { - DatabaseResults = new List(); - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Result/OthersResult.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Result/OthersResult.cs deleted file mode 100755 index ea825483f..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Result/OthersResult.cs +++ /dev/null @@ -1,24 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using System.Collections.Generic; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Result -{ - public sealed class OthersDatabaseModel - { - public int ProfileId; - public string Nick; - public string Uniquenick; - public string Lastname; - public string Firstname; - public int Userid; - public string Email; - } - - public sealed class OthersResult : ResultBase - { - public List DatabaseResults { get; set; } - public OthersResult() - { - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Result/PSPDefaultResult.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Result/PSPDefaultResult.cs deleted file mode 100755 index 540099ce0..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Result/PSPDefaultResult.cs +++ /dev/null @@ -1,11 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Result -{ - public sealed class PSPDefaultResult : ResultBase - { - public PSPDefaultResult() - { - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Result/SearchResult.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Result/SearchResult.cs deleted file mode 100755 index 0b26f5de9..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Result/SearchResult.cs +++ /dev/null @@ -1,25 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using System.Collections.Generic; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Result -{ - public sealed class SearchDataBaseModel - { - public int ProfileId; - public string Nick; - public string Uniquenick; - public string Email; - public string Firstname; - public string Lastname; - public int NamespaceID; - } - - public sealed class SearchResult : ResultBase - { - public List DataBaseResults; - public SearchResult() - { - DataBaseResults = new List(); - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Result/SearchUniqueResult.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Result/SearchUniqueResult.cs deleted file mode 100755 index 80655dce1..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Result/SearchUniqueResult.cs +++ /dev/null @@ -1,24 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using System.Collections.Generic; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Result -{ - public sealed class SearchUniqueDatabaseModel - { - public int ProfileId; - public string Nick; - public string Uniquenick; - public string Email; - public string Firstname; - public string Lastname; - public int NamespaceID; - } - - public sealed class SearchUniqueResult : ResultBase - { - public List DatabaseResults { get; set; } - public SearchUniqueResult() - { - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Result/UniqueSearchResult.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Result/UniqueSearchResult.cs deleted file mode 100755 index bd62ff6a3..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Result/UniqueSearchResult.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Result -{ - public sealed class UniqueSearchResult : ResultBase - { - public bool IsUniquenickExist; - public UniqueSearchResult() - { - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Contract/Result/ValidResult.cs b/src/Servers/PresenceSearchPlayer/src/Contract/Result/ValidResult.cs deleted file mode 100755 index 2c05c5f6e..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Contract/Result/ValidResult.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; - -namespace UniSpy.Server.PresenceSearchPlayer.Contract.Result -{ - public sealed class ValidResult : ResultBase - { - public bool IsAccountValid; - public ValidResult() - { - IsAccountValid = false; - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Dockerfile b/src/Servers/PresenceSearchPlayer/src/Dockerfile deleted file mode 100755 index 9b32fe7d1..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM mcr.microsoft.com/dotnet/runtime:6.0 AS base -WORKDIR /app -EXPOSE 29901 - -FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build -WORKDIR /src -COPY ["src/Servers/PresenceSearchPlayer/src/UniSpy.Server.PresenceSearchPlayer.csproj", "src/Servers/PresenceSearchPlayer/src/"] -COPY ["src/Libraries/Core/src/UniSpy.Server.Core.csproj", "src/Libraries/Core/src/"] -RUN dotnet restore "src/Servers/PresenceSearchPlayer/src/UniSpy.Server.PresenceSearchPlayer.csproj" -COPY . . -WORKDIR "/src/src/Servers/PresenceSearchPlayer/src" -RUN dotnet build "UniSpy.Server.PresenceSearchPlayer.csproj" -c Release -o /app/build - -FROM build AS publish -RUN dotnet publish "UniSpy.Server.PresenceSearchPlayer.csproj" -c Release -o /app/publish - -FROM base AS final -WORKDIR /app -COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "UniSpy.Server.PresenceSearchPlayer.dll"] \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Enumerator/GPEnum.cs b/src/Servers/PresenceSearchPlayer/src/Enumerator/GPEnum.cs deleted file mode 100755 index 68c1cbd22..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Enumerator/GPEnum.cs +++ /dev/null @@ -1,208 +0,0 @@ -namespace UniSpy.Server.PresenceSearchPlayer.Enumerate -{ - public enum GPEnum : uint - { - // Callbacks - //////////// - Error = 0, - RecvBuddyRequest, - RecvBuddyStatus, - RecvBuddyMessage, - RecvBuddyUTM, - RecvGameInvite, - TransferCallback, - RecvBuddyAuth, - RecvBuddyRevoke, - - // Global States. - ///////////////// - InfoCaching = 0x0100, - Simulation, - InfoChachingBuddyAndBlockOnly, - - // Blocking - /////////// - Blocking = 1, - NonBlocking = 0, - - // Firewall - /////////// - Firewall = 1, - NoFirewall = 0, - - // Check Cache - ////////////// - CheckCache = 1, - DontCheckCache = 0, - - // Is Valid Email. - // PANTS|02.15.00 - ////////////////// - EmailValid = 1, - EmailInvalid = 0, - - // Fatal Error. - /////////////// - Fatal = 1, - NonFatal = 0, - - // Sex - ////// - Male = 0x0500, - Fefamle, - PAT, - - // Profile Search. - ////////////////// - More = 0x0600, - Done, - - // Set Info - /////////// - Nick = 0x0700, - Uniquenick, - Email, - Password, - FirstName, - LastName, - ICQUIN, - HomePage, - ZIPCode, - CountryCode, - Birthday, - Sex, - CPUBrand, - CPUSpeed, - Memory, - VideoCard1String, - VideoCard1RAM, - VideoCard2String, - VideoCard2RAM, - ConnectionID, - ConnectionSpeed, - HasNetwork, - OSString, - AIMName, // PANTS|03.20.01 - PIC, - OccupationID, - IndustryID, - InComeID, - MarriedID, - ChildCount, - Interest1, - - // New Profile. - /////////////// - Replace = 1, - DontReplace = 0, - - // Is Connected. - //////////////// - Connected = 1, - NotConnected = 0, - - // Public mask. - /////////////// - MaskNone = 0x00000000, - MaskHomepage = 0x00000001, - MaskZIPCode = 0x00000002, - MaskContryCode = 0x00000004, - MaskBirthday = 0x00000008, - MaskSex = 0x00000010, - MaskEmail = 0x00000020, - MaskAll = 0xFFFFFFFF, - - // Status - ///////// - Offline = 0, - Online = 1, - Playing = 2, - Staging = 3, - Chatting = 4, - Away = 5, - - // Session flags - ///////////////// - SessIsClosed = 0x00000001, - SessIsOpen = 0x00000002, - SessHasPassword = 0x00000004, - SessIsBehindNAT = 0x00000008, - SessIsRanked = 0x000000010, - - - // CPU Brand ID - /////////////// - Intel = 1, - AMD, - CYRIX, - Motorola, - Alpha, - - // Connection ID. - ///////////////// - Modem = 1, - ISDN, - CableModem, - DSL, - Satellite, - Ethernet, - Wireless, - - // Transfer callback type. - // *** the transfer is ended when these types are received - ////////////////////////// - TransferSendRequest = 0x800, // arg->num == numFiles - TransferAccepted, - TransferRejected, // *** - TransferNotAccepting, // *** - TransferNoConnection, // *** - TransferDone, // *** - TransferCancelled, // *** - TransferLostConnection, // *** - TransferError, // *** - TransferThrottle, // arg->num == Bps - FileBegin, - FileProgress, // arg->num == numBytes - FileEnd, - FileDirectory, - FileSkip, - FileFaild, // arg->num == error - - // FILE_FAILED error - /////////////////////// - FileReadError = 0x900, - FileWriteError, - FileDataError, - - // Transfer Side. - ///////////////// - TransferSender = 0xA00, - TansferReciever, - - // UTM send options. - //////////////////// - DontRout = 0xB00, // only send direct - - // Quiet mode flags. - //////////////////// - SlienceNone = 0x00000000, - SlienceMessage = 0x00000001, - SlienceUTMS = 0x00000002, - SlienceList = 0x00000004, // includes requests, auths, and revokes - SlienceAll = 0xFFFFFFFF, - - NewStatusInfoSupported = 0xC00, - NewStatusInfoNotSupported = 0xC01 - } - - public enum GPSPResult : int - { - NoError, - MemoryError, - ParameterError, - NetworkError, - ServerError, - MISCError, - Count - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Enumerator/GPErrorCode.cs b/src/Servers/PresenceSearchPlayer/src/Enumerator/GPErrorCode.cs deleted file mode 100755 index c215495ad..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Enumerator/GPErrorCode.cs +++ /dev/null @@ -1,142 +0,0 @@ -namespace UniSpy.Server.PresenceSearchPlayer.Enumerate -{ - public enum GPErrorCode : int - { - // General. - /////////// - General = 0x0000, - Parse, - NotLoggedIn, - BadSessionKey, - DatabaseError, - Network, - ForcedDisconnect, - ConnectionClose, - UdpLayer, - - // Login. - ///////// - Login = 0x0100, - LoginTimeOut, - LoginBadNick, - LoginBadEmail, - LoginBadPassword, - LoginBadProfile, - LoginProfileDeleted, - LoginConnectionFailed, - LoginServerAuthFaild, - LoginBadUniquenick, - LoginBadPreAuth, - LoginBadLoginTicket, - LoginTicketExpired, - // Newuser. - /////////// - NewUser = 0x0200, - NewUserBadNick, - NewUserBadPasswords, - NewUserUniquenickInvalid, - NewUserUniquenickInUse, - - // Updateui. - //////////// - UpdateUI = 0x0300, - UpdateUIBadEmail, - - // Newprofile. - ////////////// - NewProfile = 0x0400, - NewProfileBadNick, - NewProfileBadOldNick, - - // Updatepro. - ///////////// - UpdatePro = 0x0500, - UpdateProBadNick, - - // Addbuddy. - //////////// - AddBuddy = 0x0600, - AddBuddyBadForm, - AddBuddyBadNew, - AddBuddyAlreadyBuddy, - - // Authadd. - /////////// - AuthAdd = 0x0700, - AuthAddBadForm, - AuthAddBadSig, - - // Status. - ////////// - Status = 0x0800, - - // Bm. - ////// - Bm = 0x0900, - BmNotBuddy, - BmExtInfoNotSupported, - BmBuddyOffline, - - // Getprofile. - ////////////// - GetProfile = 0x0A00, - GetProfileBadProfile, - - // Delbuddy. - //////////// - DelBuddy = 0x0B00, - DelBuddyNotBuddy, - - // Delprofile. - ///////////// - DelProfile = 0x0C00, - DelProfileLastProfile, - - // Search. - ////////// - Search = 0x0D00, - SearchConnectionFailed, - SearchTimeOut, - - // Check. - ///////// - Check = 0x0E00, - CheckBadMail, - CheckBadNick, - CheckBadPassword, - - // Revoke. - ////////// - Revoke = 0x0F00, - RevokeNotBuddy, - - // Registeruniquenick. - ////////////////////// - RegisterUniquenick = 0x1000, - RegisterUniquenickTaken, - RegisterUniquenickReserved, - RegisterUniquenickBadNamespace, - - // Register UniSpy.Server.CDkey. - ////////////////// - RegisterCDKey = 0x1100, - RegisterCDKeyBadKey, - RegisterCDKeyAlreadySet, - RegisterCDKeyAlreadyTaken, - - // AddBlock. - //////////// - AddBlock = 0x1200, - AddBlockAlreadyBlocked, - - // RemoveBlock. - /////////////// - RemoveBlock = 0x1300, - RemoveBlockNotBlocked, - - - // RetroSpy self defined NoError code - /////////////// - NoError = 0xffff, - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Enumerator/NewUserStatus.cs b/src/Servers/PresenceSearchPlayer/src/Enumerator/NewUserStatus.cs deleted file mode 100755 index 829d2da42..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Enumerator/NewUserStatus.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace UniSpy.Server.PresenceSearchPlayer.Entity.Enumerator -{ - public enum NewUserStatus - { - CheckAccount, - AccountNotExist, - AccountExist, - CheckProfile, - ProfileNotExist, - ProfileExist, - CheckSubProfile, - SubProfileNotExist, - SubProfileExist - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/AddBuddy/GPAddBuddyAlreadyBuddyException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/AddBuddy/GPAddBuddyAlreadyBuddyException.cs deleted file mode 100755 index 03c28d5fb..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/AddBuddy/GPAddBuddyAlreadyBuddyException.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.AddBuddy -{ - public class GPAddBuddyAlreadyBuddyException : GPException - { - public GPAddBuddyAlreadyBuddyException() : base("The buddy you are adding is already in your buddy list!", GPErrorCode.AddBlockAlreadyBlocked) - { - } - - public GPAddBuddyAlreadyBuddyException(string message) : base(message, GPErrorCode.AddBuddyAlreadyBuddy) - { - } - - public GPAddBuddyAlreadyBuddyException(string message, System.Exception innerException) : base(message, GPErrorCode.AddBuddyAlreadyBuddy, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/AddBuddy/GPAddBuddyBadFormException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/AddBuddy/GPAddBuddyBadFormException.cs deleted file mode 100755 index da4e92ec5..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/AddBuddy/GPAddBuddyBadFormException.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.AddBuddy -{ - public class GPAddBuddyBadFormException : GPException - { - public GPAddBuddyBadFormException() : base("Add buddy format invalid!", GPErrorCode.AddBuddyBadForm) - { - } - - public GPAddBuddyBadFormException(string message) : base(message, GPErrorCode.AddBuddyBadForm) - { - } - - public GPAddBuddyBadFormException(string message, System.Exception innerException) : base(message, GPErrorCode.AddBuddyBadForm, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/AddBuddy/GPAddBuddyBadNewException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/AddBuddy/GPAddBuddyBadNewException.cs deleted file mode 100755 index a862ee3bf..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/AddBuddy/GPAddBuddyBadNewException.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.AddBuddy -{ - public class GPAddBuddyBadNewException : GPException - { - public GPAddBuddyBadNewException() : base("The buddy name provided is invalid!", GPErrorCode.AddBuddyBadNew) - { - } - - public GPAddBuddyBadNewException(string message) : base(message, GPErrorCode.AddBuddyBadNew) - { - } - - public GPAddBuddyBadNewException(string message, System.Exception innerException) : base(message, GPErrorCode.AddBuddyBadNew, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/AddBuddy/GPAddBuddyException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/AddBuddy/GPAddBuddyException.cs deleted file mode 100755 index d11c3acd1..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/AddBuddy/GPAddBuddyException.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.AddBuddy -{ - public class GPAddBuddyException : GPException - { - public GPAddBuddyException() : base("Unknown error occur at add buddy!", GPErrorCode.AddBuddy) - { - } - - public GPAddBuddyException(string message) : base(message, GPErrorCode.AddBuddy) - { - } - - public GPAddBuddyException(string message, System.Exception innerException) : base(message, GPErrorCode.AddBuddy, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/AuthAdd/GPAuthAddBadFormException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/AuthAdd/GPAuthAddBadFormException.cs deleted file mode 100755 index efc2f4567..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/AuthAdd/GPAuthAddBadFormException.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.AuthAdd -{ - public class GPAuthAddBadFormException : GPException - { - public GPAuthAddBadFormException() : base("The authentication is in bad form!", GPErrorCode.AuthAddBadForm) - { - } - - public GPAuthAddBadFormException(string message) : base(message, GPErrorCode.AuthAddBadForm) - { - } - - public GPAuthAddBadFormException(string message, System.Exception innerException) : base(message, GPErrorCode.AuthAddBadForm, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/AuthAdd/GPAuthAddBadSigExceptiion.cs b/src/Servers/PresenceSearchPlayer/src/Exception/AuthAdd/GPAuthAddBadSigExceptiion.cs deleted file mode 100755 index 2d3004024..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/AuthAdd/GPAuthAddBadSigExceptiion.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.AuthAdd -{ - public class GPAuthAddBadSigException : GPException - { - public GPAuthAddBadSigException() : base("The signature in authentication is invalid!", GPErrorCode.AuthAddBadSig) - { - } - - public GPAuthAddBadSigException(string message) : base(message, GPErrorCode.AuthAddBadSig) - { - } - - public GPAuthAddBadSigException(string message, System.Exception innerException) : base(message, GPErrorCode.AuthAddBadSig, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/AuthAdd/GPAuthAddException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/AuthAdd/GPAuthAddException.cs deleted file mode 100755 index aac9e6a16..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/AuthAdd/GPAuthAddException.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.AuthAdd -{ - public class GPAuthAddException : GPException - { - public GPAuthAddException() : base("The adding of authentication failed!", GPErrorCode.AuthAdd) - { - } - - public GPAuthAddException(string message) : base(message, GPErrorCode.AuthAdd) - { - } - - public GPAuthAddException(string message, System.Exception innerException) : base(message, GPErrorCode.AuthAdd, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/BuddyMsg/GPBuddyMsgException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/BuddyMsg/GPBuddyMsgException.cs deleted file mode 100755 index c64e19d9c..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/BuddyMsg/GPBuddyMsgException.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.BM -{ - public class GPBuddyMsgException : GPException - { - public GPBuddyMsgException() : base("Unknown error occur when processing buddy message!", GPErrorCode.Bm) - { - } - - public GPBuddyMsgException(string message) : base(message, GPErrorCode.Bm) - { - } - - public GPBuddyMsgException(string message, System.Exception innerException) : base(message, GPErrorCode.Bm, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/BuddyMsg/GPBuddyMsgExtInfoNotSupportedException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/BuddyMsg/GPBuddyMsgExtInfoNotSupportedException.cs deleted file mode 100755 index 72783b882..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/BuddyMsg/GPBuddyMsgExtInfoNotSupportedException.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception -{ - public class GPBuddyMsgExtInfoNotSupportedException : GPException - { - public GPBuddyMsgExtInfoNotSupportedException() : base("Buddy message is not supported.", GPErrorCode.BmExtInfoNotSupported) - { - } - - public GPBuddyMsgExtInfoNotSupportedException(string message) : base(message, GPErrorCode.BmExtInfoNotSupported) - { - } - - public GPBuddyMsgExtInfoNotSupportedException(string message, System.Exception innerException) : base(message, GPErrorCode.BmExtInfoNotSupported, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/BuddyMsg/GPBuddyMsgNotBuddyException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/BuddyMsg/GPBuddyMsgNotBuddyException.cs deleted file mode 100755 index 61d722575..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/BuddyMsg/GPBuddyMsgNotBuddyException.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.BM -{ - public class GPBuddyMsgNotBuddyException : GPException - { - public GPBuddyMsgNotBuddyException() : base("The message receiver is not your buddy!", GPErrorCode.BmNotBuddy) - { - } - - public GPBuddyMsgNotBuddyException(string message) : base(message, GPErrorCode.BmNotBuddy) - { - } - - public GPBuddyMsgNotBuddyException(string message, System.Exception innerException) : base(message, GPErrorCode.BmNotBuddy, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/Check/CheckException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/Check/CheckException.cs deleted file mode 100755 index 3bdeaa1cf..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/Check/CheckException.cs +++ /dev/null @@ -1,24 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceSearchPlayer.Aggregate.Exception -{ - public class CheckException : GPException - { - public CheckException() : this("There was an error checking the user account.", GPErrorCode.Check) - { - } - - public CheckException(string message, GPErrorCode errorCode) : base(message, errorCode) - { - } - - public CheckException(string message, GPErrorCode errorCode, System.Exception innerException) : base(message, errorCode, innerException) - { - } - public override void Build() - { - SendingBuffer = $@"\cur\{(int)ErrorCode}\final\"; ; - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/General/GPBadSessionKeyException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/General/GPBadSessionKeyException.cs deleted file mode 100755 index 8acb6aab6..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/General/GPBadSessionKeyException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.General -{ - public class GPBadSessionKeyException : GPException - { - public GPBadSessionKeyException() : base("Your connection key is not valid!", GPErrorCode.BadSessionKey) - { - } - - public GPBadSessionKeyException(string message) : base(message, GPErrorCode.BadSessionKey) - { - } - - public GPBadSessionKeyException(string message, System.Exception innerException) : base(message, GPErrorCode.BadSessionKey, innerException) - { - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/General/GPConnectionCloseException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/General/GPConnectionCloseException.cs deleted file mode 100755 index fa8e67586..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/General/GPConnectionCloseException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.General -{ - public class GPConnectionCloseException : GPException - { - public GPConnectionCloseException() : base("Client connection accidently closed!", GPErrorCode.ConnectionClose) - { - } - - public GPConnectionCloseException(string message) : base(message, GPErrorCode.ConnectionClose) - { - } - - public GPConnectionCloseException(string message, System.Exception innerException) : base(message, GPErrorCode.ConnectionClose, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/General/GPDatabaseException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/General/GPDatabaseException.cs deleted file mode 100755 index eb2b3f6b5..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/General/GPDatabaseException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.General -{ - public class GPDatabaseException : GPException - { - public GPDatabaseException() : base("Database error!", GPErrorCode.DatabaseError) - { - } - - public GPDatabaseException(string message) : base(message, GPErrorCode.DatabaseError) - { - } - - public GPDatabaseException(string message, System.Exception innerException) : base(message, GPErrorCode.DatabaseError, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/General/GPException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/General/GPException.cs deleted file mode 100755 index 5d006133d..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/General/GPException.cs +++ /dev/null @@ -1,39 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.General -{ - public class GPException : UniSpy.Exception, IResponse - { - public GPErrorCode ErrorCode { get; private set; } - public string SendingBuffer { get; protected set; } - object IResponse.SendingBuffer => SendingBuffer; - - public GPException() : this("General Error!", GPErrorCode.General) - { - } - - public GPException(string message) : this(message, GPErrorCode.General) - { - } - - public GPException(string message, System.Exception innerException) : this(message, GPErrorCode.General, innerException) - { - } - - public GPException(string message, GPErrorCode errorCode) : base(message) - { - ErrorCode = errorCode; - } - - public GPException(string message, GPErrorCode errorCode, System.Exception innerException) : base(message, innerException) - { - ErrorCode = errorCode; - } - - public virtual void Build() - { - SendingBuffer = $@"\error\\err\{(int)ErrorCode}\fatal\\errmsg\{this.Message}\final\"; - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/General/GPForcedDisconnectException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/General/GPForcedDisconnectException.cs deleted file mode 100755 index 925f34608..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/General/GPForcedDisconnectException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.General -{ - public class GPForcedDisconnectException : GPException - { - public GPForcedDisconnectException() : base("Client is forced to disconnect!", GPErrorCode.ForcedDisconnect) - { - } - - public GPForcedDisconnectException(string message) : base(message, GPErrorCode.ForcedDisconnect) - { - } - - public GPForcedDisconnectException(string message, System.Exception innerException) : base(message, GPErrorCode.ForcedDisconnect, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/General/GPNetworkException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/General/GPNetworkException.cs deleted file mode 100755 index faea36192..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/General/GPNetworkException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.General -{ - public class GPNetworkException : GPException - { - public GPNetworkException() : base("Unknown network error!", GPErrorCode.Network) - { - } - - public GPNetworkException(string message) : base(message, GPErrorCode.Network) - { - } - - public GPNetworkException(string message, System.Exception innerException) : base(message, GPErrorCode.Network, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/General/GPNotLoggedInException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/General/GPNotLoggedInException.cs deleted file mode 100755 index 7a7d8e9b6..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/General/GPNotLoggedInException.cs +++ /dev/null @@ -1,18 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; -namespace UniSpy.Server.PresenceSearchPlayer.Exception.General -{ - public class GPNotLoggedInException : GPException - { - public GPNotLoggedInException() : base("You are not logged in, please login first!", GPErrorCode.NotLoggedIn) - { - } - - public GPNotLoggedInException(string message) : base(message, GPErrorCode.NotLoggedIn) - { - } - - public GPNotLoggedInException(string message, System.Exception innerException) : base(message, GPErrorCode.NotLoggedIn, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/General/GPParseException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/General/GPParseException.cs deleted file mode 100755 index f2b3c40ad..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/General/GPParseException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.General -{ - public class GPParseException : GPException - { - public GPParseException() : base("Request parsing error!", GPErrorCode.Parse) - { - } - - public GPParseException(string message) : base(message, GPErrorCode.Parse) - { - } - - public GPParseException(string message, System.Exception innerException) : base(message, GPErrorCode.Parse, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/General/GPUdpLayerException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/General/GPUdpLayerException.cs deleted file mode 100755 index b51536de8..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/General/GPUdpLayerException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.General -{ - public class GPUdpLayerException : GPException - { - public GPUdpLayerException() : base("Unkown UDP layer error!", GPErrorCode.UdpLayer) - { - } - - public GPUdpLayerException(string message) : base(message, GPErrorCode.UdpLayer) - { - } - - public GPUdpLayerException(string message, System.Exception innerException) : base(message, GPErrorCode.UdpLayer, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginBadEmailException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginBadEmailException.cs deleted file mode 100755 index 09b733235..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginBadEmailException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.Login -{ - public class GPLoginBadEmailException : GPLoginException - { - public GPLoginBadEmailException() : base("Email provided is invalid!", GPErrorCode.LoginBadEmail) - { - } - - public GPLoginBadEmailException(string message) : base(message, GPErrorCode.LoginBadEmail) - { - } - - public GPLoginBadEmailException(string message, System.Exception innerException) : base(message, GPErrorCode.LoginBadEmail, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginBadLoginTicketException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginBadLoginTicketException.cs deleted file mode 100755 index 9466b08e0..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginBadLoginTicketException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.Login -{ - public class GPLoginBadLoginTicketException : GPLoginException - { - public GPLoginBadLoginTicketException() : base("The login ticket is invalid!", GPErrorCode.LoginBadLoginTicket) - { - } - - public GPLoginBadLoginTicketException(string message) : base(message, GPErrorCode.LoginBadLoginTicket) - { - } - - public GPLoginBadLoginTicketException(string message, System.Exception innerException) : base(message, GPErrorCode.LoginBadLoginTicket, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginBadNickException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginBadNickException.cs deleted file mode 100755 index 16e36d6bf..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginBadNickException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.Login -{ - public class GPLoginBadNickException : GPLoginException - { - public GPLoginBadNickException() : base("Nickname is in valid!", GPErrorCode.LoginBadNick) - { - } - - public GPLoginBadNickException(string message) : base(message, GPErrorCode.LoginBadNick) - { - } - - public GPLoginBadNickException(string message, System.Exception innerException) : base(message, GPErrorCode.LoginBadNick, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginBadPasswordException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginBadPasswordException.cs deleted file mode 100755 index f6f773987..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginBadPasswordException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.Login -{ - public class GPLoginBadPasswordException : GPLoginException - { - public GPLoginBadPasswordException() : base("Password provided is invalid!", GPErrorCode.LoginBadPassword) - { - } - - public GPLoginBadPasswordException(string message) : base(message, GPErrorCode.LoginBadPassword) - { - } - - public GPLoginBadPasswordException(string message, System.Exception innerException) : base(message, GPErrorCode.LoginBadPassword, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginBadPreAuthException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginBadPreAuthException.cs deleted file mode 100755 index 82d98e6b6..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginBadPreAuthException.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.Login -{ - public class GPLoginBadPreAuthException : GPException - { - public GPLoginBadPreAuthException() : base("Login pre-authentication failed.", GPErrorCode.LoginBadPreAuth) - { - } - - public GPLoginBadPreAuthException(string message) : base(message, GPErrorCode.LoginBadPreAuth) - { - } - - public GPLoginBadPreAuthException(string message, System.Exception innerException) : base(message, GPErrorCode.LoginBadPreAuth, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginBadProfileException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginBadProfileException.cs deleted file mode 100755 index 13c16b648..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginBadProfileException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.Login -{ - public class GPLoginBadProfileException : GPLoginException - { - public GPLoginBadProfileException() : base("User profile is damaged!", GPErrorCode.LoginBadProfile) - { - } - - public GPLoginBadProfileException(string message) : base(message, GPErrorCode.LoginBadProfile) - { - } - - public GPLoginBadProfileException(string message, System.Exception innerException) : base(message, GPErrorCode.LoginBadProfile, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginBadUniquenickException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginBadUniquenickException.cs deleted file mode 100755 index 8c4f08e54..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginBadUniquenickException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.Login -{ - public class GPLoginBadUniquenickException : GPLoginException - { - public GPLoginBadUniquenickException() : base("The uniquenick provided is invalid!", GPErrorCode.LoginBadUniquenick) - { - } - - public GPLoginBadUniquenickException(string message) : base(message, GPErrorCode.LoginBadUniquenick) - { - } - - public GPLoginBadUniquenickException(string message, System.Exception innerException) : base(message, GPErrorCode.LoginBadUniquenick, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginConnectionFailedException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginConnectionFailedException.cs deleted file mode 100755 index f2b7c45b7..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginConnectionFailedException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.Login -{ - public class GPLoginConnectionFailedException : GPLoginException - { - public GPLoginConnectionFailedException() : base("Login connection failed.", GPErrorCode.LoginConnectionFailed) - { - } - - public GPLoginConnectionFailedException(string message) : base(message, GPErrorCode.LoginConnectionFailed) - { - } - - public GPLoginConnectionFailedException(string message, System.Exception innerException) : base(message, GPErrorCode.LoginConnectionFailed, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginException.cs deleted file mode 100755 index 1bd6c6986..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginException.cs +++ /dev/null @@ -1,28 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.Login -{ - public class GPLoginException : GPException - { - public GPLoginException() : base("Unknown login error!", GPErrorCode.Login) - { - } - - public GPLoginException(string message) : base(message, GPErrorCode.Login) - { - } - - public GPLoginException(string message, System.Exception innerException) : base(message, GPErrorCode.Login, innerException) - { - } - - public GPLoginException(string message, GPErrorCode errorCode) : base(message, errorCode) - { - } - - public GPLoginException(string message, GPErrorCode errorCode, System.Exception innerException) : base(message, errorCode, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginProfileDeletedException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginProfileDeletedException.cs deleted file mode 100755 index 294df1973..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginProfileDeletedException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.Login -{ - public class GPLoginProfileDeletedException : GPLoginException - { - public GPLoginProfileDeletedException() : base("User's profile has been deleted!", GPErrorCode.LoginProfileDeleted) - { - } - - public GPLoginProfileDeletedException(string message) : base(message, GPErrorCode.LoginProfileDeleted) - { - } - - public GPLoginProfileDeletedException(string message, System.Exception innerException) : base(message, GPErrorCode.LoginProfileDeleted, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginServerAuthFailedException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginServerAuthFailedException.cs deleted file mode 100755 index f40fddd31..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginServerAuthFailedException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.Login -{ - public class GPLoginServerAuthFailedException : GPLoginException - { - public GPLoginServerAuthFailedException() : base("Login server authentication failed!", GPErrorCode.LoginServerAuthFaild) - { - } - - public GPLoginServerAuthFailedException(string message) : base(message) - { - } - - public GPLoginServerAuthFailedException(string message, System.Exception innerException) : base(message, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginTicketExpiredException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginTicketExpiredException.cs deleted file mode 100755 index 69538be86..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginTicketExpiredException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.Login -{ - public class GPLoginTicketExpiredException : GPLoginException - { - public GPLoginTicketExpiredException() : base("The login ticket have expired!", GPErrorCode.LoginTicketExpired) - { - } - - public GPLoginTicketExpiredException(string message) : base(message, GPErrorCode.LoginTicketExpired) - { - } - - public GPLoginTicketExpiredException(string message, System.Exception innerException) : base(message, GPErrorCode.LoginTicketExpired, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginTimeOutException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginTimeOutException.cs deleted file mode 100755 index 07cc27b1a..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/Login/GPLoginTimeOutException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.Login -{ - public class GPLoginTimeOutException : GPLoginException - { - public GPLoginTimeOutException() : base("Login timeout!", GPErrorCode.LoginTimeOut) - { - } - - public GPLoginTimeOutException(string message) : base(message, GPErrorCode.LoginTimeOut) - { - } - - public GPLoginTimeOutException(string message, System.Exception innerException) : base(message, GPErrorCode.LoginTimeOut, innerException) - { - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/NewProfile/GPNewProfileBadNickException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/NewProfile/GPNewProfileBadNickException.cs deleted file mode 100755 index 1d45e1c41..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/NewProfile/GPNewProfileBadNickException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.NewProfile -{ - public class GPNewProfileBadNickException : GPNewProfileException - { - public GPNewProfileBadNickException() : base("Nickname is invalid at creating new profile!", GPErrorCode.NewProfileBadNick) - { - } - - public GPNewProfileBadNickException(string message) : base(message, GPErrorCode.NewProfileBadNick) - { - } - - public GPNewProfileBadNickException(string message, System.Exception innerException) : base(message, GPErrorCode.NewProfileBadNick, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/NewProfile/GPNewProfileBadOldNick.cs b/src/Servers/PresenceSearchPlayer/src/Exception/NewProfile/GPNewProfileBadOldNick.cs deleted file mode 100755 index 5865aee81..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/NewProfile/GPNewProfileBadOldNick.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.NewProfile -{ - public class GPNewProfileBadOldNickException : GPNewProfileException - { - public GPNewProfileBadOldNickException() : base("There is an already exist nickname!", GPErrorCode.NewProfileBadOldNick) - { - } - - public GPNewProfileBadOldNickException(string message) : base(message, GPErrorCode.NewProfileBadOldNick) - { - } - - public GPNewProfileBadOldNickException(string message, System.Exception innerException) : base(message, GPErrorCode.NewProfileBadOldNick, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/NewProfile/GPNewProfileException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/NewProfile/GPNewProfileException.cs deleted file mode 100755 index b93fb0b19..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/NewProfile/GPNewProfileException.cs +++ /dev/null @@ -1,28 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.NewProfile -{ - public class GPNewProfileException : GPException - { - public GPNewProfileException() : base("An unknown error occur when creating new profile!", GPErrorCode.NewProfile) - { - } - - public GPNewProfileException(string message) : base(message, GPErrorCode.NewProfile) - { - } - - public GPNewProfileException(string message, System.Exception innerException) : base(message, GPErrorCode.NewProfile, innerException) - { - } - - public GPNewProfileException(string message, GPErrorCode errorCode) : base(message, errorCode) - { - } - - public GPNewProfileException(string message, GPErrorCode errorCode, System.Exception innerException) : base(message, errorCode, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/NewUser/GPNewUserBadNickException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/NewUser/GPNewUserBadNickException.cs deleted file mode 100755 index 90b021671..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/NewUser/GPNewUserBadNickException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.NewUser -{ - public class GPNewUserBadNickException : GPNewUserException - { - public GPNewUserBadNickException() : base("The nickname provided is invalid!", GPErrorCode.NewUserBadNick) - { - } - - public GPNewUserBadNickException(string message) : base(message, GPErrorCode.NewUserBadNick) - { - } - - public GPNewUserBadNickException(string message, System.Exception innerException) : base(message, GPErrorCode.NewUserBadNick, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/NewUser/GPNewUserBadPasswordException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/NewUser/GPNewUserBadPasswordException.cs deleted file mode 100755 index 3152ecfdc..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/NewUser/GPNewUserBadPasswordException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.NewUser -{ - public class GPNewUserBadPasswordException : GPNewUserException - { - public GPNewUserBadPasswordException() : base("Password is invalid!", GPErrorCode.NewUserBadPasswords) - { - } - - public GPNewUserBadPasswordException(string message) : base(message, GPErrorCode.NewUserBadPasswords) - { - } - - public GPNewUserBadPasswordException(string message, System.Exception innerException) : base(message, GPErrorCode.NewUserBadPasswords, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/NewUser/GPNewUserException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/NewUser/GPNewUserException.cs deleted file mode 100755 index cf0c75ae6..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/NewUser/GPNewUserException.cs +++ /dev/null @@ -1,30 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.NewUser -{ - public class GPNewUserException : GPException - { - public GPNewUserException() : this("There was an unknown error creating user account.", GPErrorCode.NewUser) - { - } - public GPNewUserException(string message) : base(message, GPErrorCode.NewUser) - { - } - public GPNewUserException(string message, System.Exception innerException) : base(message, GPErrorCode.NewUser, innerException) - { - } - - public GPNewUserException(string message, GPErrorCode errorCode) : base(message, errorCode) - { - } - - public GPNewUserException(string message, GPErrorCode errorCode, System.Exception innerException) : base(message, errorCode, innerException) - { - } - public override void Build() - { - SendingBuffer = $@"\nur\{(int)ErrorCode}\final\"; - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/NewUser/GPNewUserUniquenickInUseException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/NewUser/GPNewUserUniquenickInUseException.cs deleted file mode 100755 index 56c415c0f..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/NewUser/GPNewUserUniquenickInUseException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.NewUser -{ - public class GPNewUserUniquenickInUseException : GPNewUserException - { - public GPNewUserUniquenickInUseException() : base("Uniquenick is in use!", GPErrorCode.NewUserUniquenickInUse) - { - } - - public GPNewUserUniquenickInUseException(string message) : base(message, GPErrorCode.NewUserUniquenickInUse) - { - } - - public GPNewUserUniquenickInUseException(string message, System.Exception innerException) : base(message, GPErrorCode.NewUserUniquenickInUse, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/NewUser/GPNewUserUniquenickInvalidException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/NewUser/GPNewUserUniquenickInvalidException.cs deleted file mode 100755 index 5232fe9e9..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/NewUser/GPNewUserUniquenickInvalidException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.NewUser -{ - public class GPNewUserUniquenickInvalidException : GPNewUserException - { - public GPNewUserUniquenickInvalidException() : base("Uniquenick is invalid!", GPErrorCode.NewUserUniquenickInvalid) - { - } - - public GPNewUserUniquenickInvalidException(string message) : base(message, GPErrorCode.NewUserUniquenickInvalid) - { - } - - public GPNewUserUniquenickInvalidException(string message, System.Exception innerException) : base(message, GPErrorCode.NewUserUniquenickInvalid, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/Status/GPStatusException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/Status/GPStatusException.cs deleted file mode 100755 index dd8071271..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/Status/GPStatusException.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.Status -{ - public class GPStatusException : GPException - { - public GPStatusException() : base("Unknown error happen when processing player status", GPErrorCode.Status) - { - } - - public GPStatusException(string message) : base(message, GPErrorCode.Status) - { - } - - public GPStatusException(string message, System.Exception innerException) : base(message, GPErrorCode.Status, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/UpdatePro/GPUpdateProBadNickException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/UpdatePro/GPUpdateProBadNickException.cs deleted file mode 100755 index a6e53462f..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/UpdatePro/GPUpdateProBadNickException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.UpdatePro -{ - public class GPUpdateProBadNickException : GPUpdateProException - { - public GPUpdateProBadNickException() : base("Nickname is invalid for updating profile!", GPErrorCode.UpdateProBadNick) - { - } - - public GPUpdateProBadNickException(string message) : base(message, GPErrorCode.UpdateProBadNick) - { - } - - public GPUpdateProBadNickException(string message, System.Exception innerException) : base(message, GPErrorCode.UpdateProBadNick, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/UpdatePro/GPUpdateProException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/UpdatePro/GPUpdateProException.cs deleted file mode 100755 index f6bfc60cf..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/UpdatePro/GPUpdateProException.cs +++ /dev/null @@ -1,28 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.UpdatePro -{ - public class GPUpdateProException : GPException - { - public GPUpdateProException() : base("Update profile unknown error!", GPErrorCode.UpdatePro) - { - } - - public GPUpdateProException(string message) : base(message, GPErrorCode.UpdatePro) - { - } - - public GPUpdateProException(string message, System.Exception innerException) : base(message, GPErrorCode.UpdatePro, innerException) - { - } - - public GPUpdateProException(string message, GPErrorCode errorCode) : base(message, errorCode) - { - } - - public GPUpdateProException(string message, GPErrorCode errorCode, System.Exception innerException) : base(message, errorCode, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/UpdateUI/GPUpdateUIBadEmailException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/UpdateUI/GPUpdateUIBadEmailException.cs deleted file mode 100755 index 11e1c5cc6..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/UpdateUI/GPUpdateUIBadEmailException.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.UpdateUI -{ - public class GPUpdateUIBadEmailException : GPUpdateUIException - { - public GPUpdateUIBadEmailException() : base("Email is invalid!", GPErrorCode.UpdateUIBadEmail) - { - } - - public GPUpdateUIBadEmailException(string message) : base(message, GPErrorCode.UpdateUIBadEmail) - { - } - - public GPUpdateUIBadEmailException(string message, System.Exception innerException) : base(message, GPErrorCode.UpdateUIBadEmail, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Exception/UpdateUI/GPUpdateUIException.cs b/src/Servers/PresenceSearchPlayer/src/Exception/UpdateUI/GPUpdateUIException.cs deleted file mode 100755 index e8ae0d7b2..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Exception/UpdateUI/GPUpdateUIException.cs +++ /dev/null @@ -1,28 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Enumerate; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; - -namespace UniSpy.Server.PresenceSearchPlayer.Exception.UpdateUI -{ - public class GPUpdateUIException : GPException - { - public GPUpdateUIException() : base("Update user info unknown error!", GPErrorCode.UpdateUI) - { - } - - public GPUpdateUIException(string message) : base(message, GPErrorCode.UpdateUI) - { - } - - public GPUpdateUIException(string message, System.Exception innerException) : base(message, GPErrorCode.UpdateUI, innerException) - { - } - - public GPUpdateUIException(string message, GPErrorCode errorCode) : base(message, errorCode) - { - } - - public GPUpdateUIException(string message, GPErrorCode errorCode, System.Exception innerException) : base(message, errorCode, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/CheckHandler.cs b/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/CheckHandler.cs deleted file mode 100755 index f78dd45dc..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/CheckHandler.cs +++ /dev/null @@ -1,43 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Application; -using UniSpy.Server.PresenceSearchPlayer.Enumerate; -using UniSpy.Server.PresenceSearchPlayer.Aggregate.Exception; -using UniSpy.Server.PresenceSearchPlayer.Contract.Request; -using UniSpy.Server.PresenceSearchPlayer.Contract.Response; -using UniSpy.Server.PresenceSearchPlayer.Contract.Result; - -namespace UniSpy.Server.PresenceSearchPlayer.Handler.CmdHandler -{ - - public sealed class CheckHandler : CmdHandlerBase - { - // \check\\nick\\email\\partnerid\0\passenc\\gamename\gmtest\final\ - //\cur\pid\\final - //check is request recieved correct and convert password into our MD5 type - private new CheckRequest _request => (CheckRequest)base._request; - private new CheckResult _result { get => (CheckResult)base._result; set => base._result = value; } - public CheckHandler(Client client, CheckRequest request) : base(client, request) - { - _result = new CheckResult(); - } - - protected override void DataOperation() - { - if (StorageOperation.Persistance.VerifyEmail(_request.Email)) - { - throw new CheckException("No account exists with the provided email address.", GPErrorCode.CheckBadMail); - } - - if (StorageOperation.Persistance.VerifyEmailAndPassword(_request.Email, _request.Password)) - { - throw new CheckException("No account exists with the provided email address.", GPErrorCode.CheckBadPassword); - } - _result.ProfileId = StorageOperation.Persistance.GetProfileId(_request.Email, _request.Password, _request.Nick, _request.PartnerId); - } - - protected override void ResponseConstruct() - { - _response = new CheckResponse(_request, _result); - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/NewUserHandler.cs b/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/NewUserHandler.cs deleted file mode 100755 index ee4910c2d..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/NewUserHandler.cs +++ /dev/null @@ -1,145 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Application; -using UniSpy.Server.PresenceSearchPlayer.Entity.Enumerator; -using UniSpy.Server.PresenceSearchPlayer.Exception.NewUser; -using UniSpy.Server.PresenceSearchPlayer.Contract.Request; -using UniSpy.Server.PresenceSearchPlayer.Contract.Response; -using UniSpy.Server.PresenceSearchPlayer.Contract.Result; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Database.DatabaseModel; - -namespace UniSpy.Server.PresenceSearchPlayer.Handler.CmdHandler -{ - - public class NewUserHandler : CmdHandlerBase - { - protected new NewUserRequest _request => (NewUserRequest)base._request; - protected new NewUserResult _result { get => (NewUserResult)base._result; set => base._result = value; } - - public NewUserHandler(IClient client, IRequest request) : base(client, request) - { - _result = new NewUserResult(); - } - - protected override void DataOperation() - { - DatabaseOperationByType(); - UpdateOtherInfo(); - } - - private void UpdateOtherInfo() - { - if (_request.HasPartnerIDFlag) - { - _result.SubProfile.PartnerId = _request.PartnerID; - } - - if (_request.HasProductIDFlag) - { - _result.SubProfile.ProductId = _request.ProductID; - } - - if (_request.HasGameNameFlag) - { - _result.SubProfile.Gamename = _request.GameName; - } - - if (_request.HasGamePortFlag) - { - _result.SubProfile.Port = _request.GamePort; - } - - if (_request.HasCDKeyEncFlag) - { - _result.SubProfile.Cdkeyenc = _request.CDKey; - } - StorageOperation.Persistance.UpdateSubProfile(_result.SubProfile); - } - - private void DatabaseOperationByType() - { - - switch (NewUserStatus.CheckAccount) - { - case NewUserStatus.CheckAccount: - var user = StorageOperation.Persistance.GetUser(_request.Email); - if (user is null) - { - goto case NewUserStatus.AccountNotExist; - } - else - { - _result.User = user; - goto case NewUserStatus.AccountExist; - } - - case NewUserStatus.AccountNotExist: - _result.User = new User { Email = _request.Email, Password = _request.Password }; - StorageOperation.Persistance.AddUser(_result.User); - goto case NewUserStatus.CheckProfile; - - case NewUserStatus.AccountExist: - - if (_result.User.Password != _request.Password) - { - throw new GPNewUserBadPasswordException("password is incorrect when creating new user."); - } - else - { - goto case NewUserStatus.CheckProfile; - } - - case NewUserStatus.CheckProfile: - var profile = StorageOperation.Persistance.GetProfile(_result.User.UserId, _request.Nick); - if (profile is null) - { - goto case NewUserStatus.ProfileNotExist; - } - else - { - _result.Profile = profile; - goto case NewUserStatus.ProfileExist; - } - - case NewUserStatus.ProfileNotExist: - _result.Profile = new Profile { Userid = _result.User.UserId, Nick = _request.Nick }; - StorageOperation.Persistance.AddProfile(_result.Profile); - goto case NewUserStatus.CheckSubProfile; - - case NewUserStatus.ProfileExist: - //we do nothing here - - case NewUserStatus.CheckSubProfile: - var subProfile = StorageOperation.Persistance.GetSubProfile(_result.Profile.ProfileId, _request.NamespaceID, _request.ProductID); - if (subProfile is null) - { - goto case NewUserStatus.SubProfileNotExist; - } - else - { - _result.SubProfile = subProfile; - goto case NewUserStatus.SubProfileExist; - } - - case NewUserStatus.SubProfileNotExist: - //we create subprofile and return - _result.SubProfile = new Subprofile - { - ProfileId = _result.Profile.ProfileId, - Uniquenick = _request.Uniquenick, - NamespaceId = _request.NamespaceID - }; - StorageOperation.Persistance.AddSubProfile(_result.SubProfile); - break; - - case NewUserStatus.SubProfileExist: - throw new GPNewUserUniquenickInUseException("unique nick is in use."); - } - } - - protected override void ResponseConstruct() - { - _response = new NewUserResponse(_request, _result); - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/NicksHandler.cs b/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/NicksHandler.cs deleted file mode 100755 index d87823d9e..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/NicksHandler.cs +++ /dev/null @@ -1,46 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; -using UniSpy.Server.PresenceSearchPlayer.Contract.Request; -using UniSpy.Server.PresenceSearchPlayer.Contract.Response; -using UniSpy.Server.PresenceSearchPlayer.Contract.Result; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.PresenceSearchPlayer.Application; - -/////////////////////////Finished?///////////////////////////////// -namespace UniSpy.Server.PresenceSearchPlayer.Handler.CmdHandler -{ - /// - /// Uses a email and namespaceid to find all nick in this account - /// - - public sealed class NicksHandler : CmdHandlerBase - { - private new NicksResult _result { get => (NicksResult)base._result; set => base._result = value; } - private new NicksRequest _request => (NicksRequest)base._request; - public NicksHandler(IClient client, IRequest request) : base(client, request) - { - _result = new NicksResult(); - } - - protected override void DataOperation() - { - try - { - _result.DataBaseResults = StorageOperation.Persistance.GetAllNickAndUniqueNick(_request.Email, - _request.Password, - _request.NamespaceID); - - //we store data in strong type so we can use in next step - } - catch (System.Exception e) - { - throw new GPDatabaseException($"Unknown error occurs in database operation.", e); - } - } - - protected override void ResponseConstruct() - { - _response = new NicksResponse(_request, _result); - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/OthersHandler.cs b/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/OthersHandler.cs deleted file mode 100755 index 90c604ae4..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/OthersHandler.cs +++ /dev/null @@ -1,42 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; -using UniSpy.Server.PresenceSearchPlayer.Contract.Request; -using UniSpy.Server.PresenceSearchPlayer.Contract.Response; -using UniSpy.Server.PresenceSearchPlayer.Contract.Result; -using UniSpy.Server.PresenceSearchPlayer.Application; - -namespace UniSpy.Server.PresenceSearchPlayer.Handler.CmdHandler -{ - - /// - /// Get buddy's information - /// - - public sealed class OthersHandler : CmdHandlerBase - { - private new OthersRequest _request => (OthersRequest)base._request; - private new OthersResult _result { get => (OthersResult)base._result; set => base._result = value; } - public OthersHandler(Client client, OthersRequest request) : base(client, request) - { - _result = new OthersResult(); - } - - protected override void DataOperation() - { - try - { - - _result.DatabaseResults = StorageOperation.Persistance.GetFriendsInfo(_request.ProfileId, _request.NamespaceID, _request.GameName); - } - catch (System.Exception e) - { - throw new GPDatabaseException("Unknown error occurs in database operation.", e); - } - } - - protected override void ResponseConstruct() - { - _response = new OthersResponse(_request, _result); - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/OthersListHandler.cs b/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/OthersListHandler.cs deleted file mode 100755 index 0bfd7a719..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/OthersListHandler.cs +++ /dev/null @@ -1,40 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; -using UniSpy.Server.PresenceSearchPlayer.Contract.Request; -using UniSpy.Server.PresenceSearchPlayer.Contract.Response; -using UniSpy.Server.PresenceSearchPlayer.Contract.Result; -using UniSpy.Server.PresenceSearchPlayer.Application; - -namespace UniSpy.Server.PresenceSearchPlayer.Handler.CmdHandler -{ - - - public sealed class OthersListHandler : CmdHandlerBase - { - private new OthersListRequest _request => (OthersListRequest)base._request; - - private new OthersListResult _result { get => (OthersListResult)base._result; set => base._result = value; } - - public OthersListHandler(Client client, OthersListRequest request) : base(client, request) - { - _result = new OthersListResult(); - } - - protected override void DataOperation() - { - try - { - _result.DatabaseResults = StorageOperation.Persistance.GetMatchedProfileIdInfos(_request.ProfileIDs, _request.NamespaceID); - } - catch (System.Exception e) - { - throw new GPDatabaseException("Unknown error occurs in database operation.", e); - } - } - - protected override void ResponseConstruct() - { - _response = new OthersListResponse(_request, _result); - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/PmatchHandler.cs b/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/PmatchHandler.cs deleted file mode 100755 index e3def1cfe..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/PmatchHandler.cs +++ /dev/null @@ -1,52 +0,0 @@ -//using UniSpy.Server.Core.Common; -//using UniSpy.Server.PresenceSearchPlayer.Enumerate; -//using System; -//using System.Collections.Generic; - -//namespace UniSpy.Server.PresenceSearchPlayer.Handler.CommandHandler.Pmatch -//{ -// /// -// /// Search the all players in specific game -// /// -// public class PmatchHandler:GPSPHandlerBase -// { - -// public PmatchHandler(string rawRequest) :base(rawRequest) -// { -// } - -// //pmath\\sesskey\\profileid\\productid\\ - -// protected override void CheckRequest(GPSPSession connection) -// { -// base.CheckRequest(connection); -// if (!KeyValues.ContainsKey("sesskey") || !KeyValues.ContainsKey("profileid") || !KeyValues.ContainsKey("productid")) -// { -// _errorCode = GPErrorCode.Parse; -// } -// } - -// protected override void DataBaseOperation(GPSPSession connection) -// { -// _result = PmatchQuery.PlayerMatch(Convert.Toint16(KeyValues["productid"])); -// } - -// protected override void ConstructResponse(GPSPSession connection) -// { -// if(_result.Count==0) -// { -// _sendingBuffer= @"\psrdone\final\"; -// return; -// } -// foreach (Dictionary player in _result) -// { -// _sendingBuffer += @"\psr\" + player["profileid"]; -// _sendingBuffer += @"\status\" + player["statstring"]; -// _sendingBuffer += @"\nick\" + player["nick"]; -// _sendingBuffer += @"\statuscode\" + player["status"]; -// } -// -// _sendingBuffer += @"\psrdone\final\"; -// } -// } -//} diff --git a/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/SearchHandler.cs b/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/SearchHandler.cs deleted file mode 100755 index ce6782d0d..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/SearchHandler.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Contract.Request; -using UniSpy.Server.PresenceSearchPlayer.Contract.Response; -using UniSpy.Server.PresenceSearchPlayer.Contract.Result; -using System.Linq; -using UniSpy.Server.PresenceSearchPlayer.Application; - - -//last one we search with email this may get few profile so we can not return GPErrorCode -//SearchWithEmail(client,dict ); -//\search\\sesskey\0\profileid\0\namespaceid\1\partnerid\0\nick\mycrysis\uniquenick\xiaojiuwo\email\koujiangheng@live.cn\gamename\gmtest\final\ -//\bsrdone\more\\final\ -//string sendingbuffer = -//"\\bsr\\1\\nick\\mycrysis\\uniquenick\\1\\namespaceid\\0\\firstname\\jiangheng\\lastname\\kou\\email\\koujiangheng@live.cn\\bsrdone\\0\\final\\"; -//client.Stream.SendAsync(sendingbuffer); -//\more\\final\ -//\search\sesskey\0\profileid\0\namespaceid\0\nick\gbr359_jordips\gamename\gbrome\final\ - -namespace UniSpy.Server.PresenceSearchPlayer.Handler.CmdHandler -{ - - public sealed class SearchHandler : CmdHandlerBase - { - private new SearchRequest _request => (SearchRequest)base._request; - private new SearchResult _result { get => (SearchResult)base._result; set => base._result = value; } - public SearchHandler(Client client, SearchRequest request) : base(client, request) - { - _result = new SearchResult(); - } - protected override void DataOperation() - { - //TODO verify the search condition whether needed namespaceid!!!!! - List result; - switch (_request.RequestType) - { - case SearchRequestType.NickSearch: - result = StorageOperation.Persistance.GetMatchedInfosByNick(_request.Nick); - break; - case SearchRequestType.NickEmailSearch: - result = StorageOperation.Persistance.GetMatchedInfosByNickAndEmail(_request.Nick, - _request.Email); - break; - case SearchRequestType.UniquenickNamespaceIDSearch: - result = StorageOperation.Persistance.GetMatchedInfosByUniqueNickAndNamespaceId(_request.Uniquenick, - _request.NamespaceID); - break; - case SearchRequestType.EmailSearch: - result = StorageOperation.Persistance.GetMatchedInfosByEmail(_request.Email); - break; - default: - result = null; - break; - } - if (result is null) - { - return; - } - _result.DataBaseResults = result.ToList(); - } - - protected override void ResponseConstruct() - { - _response = new SearchResponse(_request, _result); - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/SearchUniqueHandler.cs b/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/SearchUniqueHandler.cs deleted file mode 100755 index 10a94854c..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/SearchUniqueHandler.cs +++ /dev/null @@ -1,39 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; -using UniSpy.Server.PresenceSearchPlayer.Contract.Request; -using UniSpy.Server.PresenceSearchPlayer.Contract.Response; -using UniSpy.Server.PresenceSearchPlayer.Contract.Result; -using UniSpy.Server.PresenceSearchPlayer.Application; - -namespace UniSpy.Server.PresenceSearchPlayer.Handler.CmdHandler -{ - /// - /// Search with uniquenick and namespace - /// - - public sealed class SearchUniqueHandler : CmdHandlerBase - { - private new SearchUniqueRequest _request => (SearchUniqueRequest)base._request; - private new SearchUniqueResult _result { get => (SearchUniqueResult)base._result; set => base._result = value; } - public SearchUniqueHandler(Client client, SearchUniqueRequest request) : base(client, request) - { - _result = new SearchUniqueResult(); - } - protected override void DataOperation() - { - try - { - _result.DatabaseResults = StorageOperation.Persistance.GetMatchedInfosByNamespaceId(_request.NamespaceIds, _request.Uniquenick); - } - catch (System.Exception e) - { - throw new GPDatabaseException("Unknown error occurs in database operation.", e); - } - } - - protected override void ResponseConstruct() - { - _response = new SearchUniqueResponse(_request, _result); - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/UniqueSearchHandler.cs b/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/UniqueSearchHandler.cs deleted file mode 100755 index d5550c3b3..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/UniqueSearchHandler.cs +++ /dev/null @@ -1,38 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; -using UniSpy.Server.PresenceSearchPlayer.Contract.Request; -using UniSpy.Server.PresenceSearchPlayer.Contract.Response; -using UniSpy.Server.PresenceSearchPlayer.Contract.Result; -using UniSpy.Server.PresenceSearchPlayer.Application; - -namespace UniSpy.Server.PresenceSearchPlayer.Handler.CmdHandler -{ - - public sealed class UniqueSearchHandler : CmdHandlerBase - { - private new UniqueSearchRequest _request => (UniqueSearchRequest)base._request; - private new UniqueSearchResult _result { get => (UniqueSearchResult)base._result; set => base._result = value; } - public UniqueSearchHandler(Client client, UniqueSearchRequest request) : base(client, request) - { - _result = new UniqueSearchResult(); - } - protected override void DataOperation() - { - try - { - _result.IsUniquenickExist = StorageOperation.Persistance.IsUniqueNickExist(_request.PreferredNick, - _request.NamespaceID, - _request.GameName); - } - catch (System.Exception e) - { - throw new GPDatabaseException("Unknown error occurs in database operation.", e); - } - } - - protected override void ResponseConstruct() - { - _response = new UniqueSearchResponse(_request, _result); - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/ValidHandler.cs b/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/ValidHandler.cs deleted file mode 100755 index 159a594d7..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Handler/CmdHandler/ValidHandler.cs +++ /dev/null @@ -1,37 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Abstraction.BaseClass; -using UniSpy.Server.PresenceSearchPlayer.Exception.General; -using UniSpy.Server.PresenceSearchPlayer.Contract.Request; -using UniSpy.Server.PresenceSearchPlayer.Contract.Response; -using UniSpy.Server.PresenceSearchPlayer.Contract.Result; -using UniSpy.Server.PresenceSearchPlayer.Application; - -namespace UniSpy.Server.PresenceSearchPlayer.Handler.CmdHandler -{ - - public sealed class ValidHandler : CmdHandlerBase - { - private new ValidRequest _request => (ValidRequest)base._request; - private new ValidResult _result { get => (ValidResult)base._result; set => base._result = value; } - - public ValidHandler(Client client, ValidRequest request) : base(client, request) - { - _result = new ValidResult(); - } - protected override void DataOperation() - { - try - { - _result.IsAccountValid = StorageOperation.Persistance.IsEmailExist(_request.Email); - } - catch (System.Exception e) - { - throw new GPDatabaseException("Unknown error occurs in database operation.", e); - } - } - - protected override void ResponseConstruct() - { - _response = new ValidResponse(_request, _result); - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/Handler/CmdSwitcher.cs b/src/Servers/PresenceSearchPlayer/src/Handler/CmdSwitcher.cs deleted file mode 100755 index ea591e058..000000000 --- a/src/Servers/PresenceSearchPlayer/src/Handler/CmdSwitcher.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using UniSpy.Server.PresenceSearchPlayer.Contract.Request; -using UniSpy.Server.PresenceSearchPlayer.Handler.CmdHandler; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Logging; -using UniSpy.Server.PresenceSearchPlayer.Application; - -namespace UniSpy.Server.PresenceSearchPlayer.Handler -{ - public sealed class CmdSwitcher : CmdSwitcherBase - { - private new string _rawRequest => (string)base._rawRequest; - private new Client _client => (Client)base._client; - public CmdSwitcher(Client client, string rawRequest) : base(client, rawRequest) - { - } - protected override void ProcessRawRequest() - { - if (_rawRequest[0] != '\\') - { - _client.LogInfo("Invalid request recieved!"); - return; - } - string[] rawRequests = _rawRequest.Split("\\final\\", StringSplitOptions.RemoveEmptyEntries); - foreach (var rawRequest in rawRequests) - { - var name = rawRequest.TrimStart('\\').Split("\\").First(); - _requests.Add(new KeyValuePair(name, rawRequest)); - } - } - - protected override IHandler CreateCmdHandlers(object name, object rawRequest) - { - switch ((string)name) - { - case "check": - return new CheckHandler(_client, new CheckRequest((string)rawRequest)); - case "newuser": - return new NewUserHandler(_client, new NewUserRequest((string)rawRequest)); - case "nicks": - return new NicksHandler(_client, new NicksRequest((string)rawRequest)); - case "others": - return new OthersHandler(_client, new OthersRequest((string)rawRequest)); - case "otherslist": - return new OthersListHandler(_client, new OthersListRequest((string)rawRequest)); - case "pmatch": - // return new PMatchHandler(_client, new PMatchRequest((string)rawRequest)); - throw new NotImplementedException(); - case "search": - return new SearchHandler(_client, new SearchRequest((string)rawRequest)); - case "searchunique": - return new SearchUniqueHandler(_client, new SearchUniqueRequest((string)rawRequest)); - case "uniquesearch": - return new UniqueSearchHandler(_client, new UniqueSearchRequest((string)rawRequest)); - case "valid": - return new ValidHandler(_client, new ValidRequest((string)rawRequest)); - default: - return null; - } - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/src/UniSpy.Server.PresenceSearchPlayer.csproj b/src/Servers/PresenceSearchPlayer/src/UniSpy.Server.PresenceSearchPlayer.csproj deleted file mode 100755 index 8b9381e25..000000000 --- a/src/Servers/PresenceSearchPlayer/src/UniSpy.Server.PresenceSearchPlayer.csproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - Exe - net6.0 - ..\..\..\..\common\Icon\UniSpy_Logo.ico - Linux - ..\..\..\.. - - - ..\..\..\..\build\$(Configuration) - - - ..\..\..\..\build\$(Configuration) - - - - - - - - \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/test/GameTest.cs b/src/Servers/PresenceSearchPlayer/test/GameTest.cs deleted file mode 100644 index c723c4a94..000000000 --- a/src/Servers/PresenceSearchPlayer/test/GameTest.cs +++ /dev/null @@ -1,17 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Handler; -using Xunit; - -namespace UniSpy.Server.PresenceSearchPlayer.Test -{ - public class GameTest - { - [Fact] - public void CheckTest() - { - var raw = @"\check\\nick\spyguy\email\spyguy@gamespy.com\pass\0000\final\"; - var client = MokeObject.CreateClient(); - var switcher = new CmdSwitcher(client, raw); - switcher.Handle(); - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/test/MokeObject.cs b/src/Servers/PresenceSearchPlayer/test/MokeObject.cs deleted file mode 100644 index 66ba41863..000000000 --- a/src/Servers/PresenceSearchPlayer/test/MokeObject.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Net; -using Moq; -using UniSpy.Server.PresenceSearchPlayer.Application; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.PresenceSearchPlayer.Test -{ - public class MokeObject - { - public static IClient Client = CreateClient(); - - public static Client CreateClient(string ipAddress = "192.168.1.1", int port = 9999) - { - var managerMock = new Mock(); - var connectionMock = new Mock(); - connectionMock.Setup(s => s.RemoteIPEndPoint).Returns(new IPEndPoint(IPAddress.Parse(ipAddress), port)); - connectionMock.Setup(s => s.Manager).Returns(managerMock.Object); - connectionMock.Setup(s => s.ConnectionType).Returns(NetworkConnectionType.Tcp); - var serverMock = new PresenceSearchPlayer.Application.Server(managerMock.Object); - - return new Client(connectionMock.Object, serverMock); - } - } -} \ No newline at end of file diff --git a/src/Servers/PresenceSearchPlayer/test/RawRequests.cs b/src/Servers/PresenceSearchPlayer/test/RawRequests.cs deleted file mode 100644 index 93d1cb787..000000000 --- a/src/Servers/PresenceSearchPlayer/test/RawRequests.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace UniSpy.Server.PresenceSearchPlayer.Test -{ - public class RawRequests - { - /// - /// Optional parameter: nick, uniquenick, email, firstname, lastname, icquin, skip - /// - public const string Profile = @"\search\\sesskey\xxxx\profileid\0\namespaceid\0\nick\spyguy\uniquenick\spyguy\email\spyguy@unispy.org\firstname\spy\lastname\guy\icquin\123\skip\0\gamename\gmtest\final\"; - - public const string ProfileUniquenick = @"\searchunique\\sesskey\xxxx\profileid\0\uniquenick\spyguy\namespaces\1,2,3,4,5\gamename\gmtest\final\"; - - public const string IsValid = @"\valid\\email\spyguy@unispy.org\partnerid\1\gamename\gmtest\final\"; - - public const string Nick = @"\nicks\\email\spyguy@unispy.org\passenc\xxxxx\namespaceid\0\partnerid\0\gamename\gmtest\final\"; - - public const string Players = @"\pmatch\\sesskey\123456\profileid\0\productid\0\final\"; - - public const string Check = @"\check\\nick\xiaojiuwo\email\xiaojiuwo@gamespy.com\partnerid\0\passenc\xxxx\gamename\gmtest\final\"; - - /// - /// Optional parameter: cdkey - /// - public const string NewUser = @"\newuser\\nick\xiaojiuwo\email\xiaojiuwo@gamespy.com\passenc\xxxx\productID\0\namespaceid\0\uniquenick\xiaojiuwo\cdkey\xxx-xxx-xxx-xxx\partnerid\0\gamename\gmtest\final\"; - - public const string OthersBuddy = @"\others\\sesskey\123456\profileid\0\namespaceid\0\gamename\gmtest\final\"; - - public const string OthersBuddyList = @"\otherlist\\sesskey\123456\profileid\0\numopids\2\opids\1|2\namespaceid\0\gamename\gmtest\final\"; - - public const string SuggestUnique = @"uniquesearch\\preferrednick\xiaojiuwo\namespaceid\0\gamename\gmtest\final\"; - } -} diff --git a/src/Servers/PresenceSearchPlayer/test/RequestTests.cs b/src/Servers/PresenceSearchPlayer/test/RequestTests.cs deleted file mode 100644 index 8c17fbd9d..000000000 --- a/src/Servers/PresenceSearchPlayer/test/RequestTests.cs +++ /dev/null @@ -1,25 +0,0 @@ -using UniSpy.Server.PresenceSearchPlayer.Contract.Request; -using Xunit; - -namespace UniSpy.Server.PresenceSearchPlayer.Test -{ - public class RequestTests - { - [Fact] - public void NewUserTest() - { - var request = new NewUserRequest(RawRequests.NewUser); - request.Parse(); - Assert.Equal("xiaojiuwo", request.Nick); - Assert.Equal("xiaojiuwo@gamespy.com", request.Email); - // password 'xxx' is decoded and hash to '1e034b66363e5a081874ae022767f685' - Assert.Equal("0d1b08c34858921bc7c662b228acb7ba", request.Password); - Assert.Equal((int)0, request.ProductID); - Assert.Equal((int)0, request.NamespaceID); - Assert.Equal("xiaojiuwo", request.Uniquenick); - Assert.Equal("xxx-xxx-xxx-xxx", request.CDKey); - Assert.Equal((int)0, request.PartnerID); - Assert.Equal("gmtest", request.GameName); - } - } -} diff --git a/src/Servers/PresenceSearchPlayer/test/UniSpy.Server.PresenceSearchPlayer.Test.csproj b/src/Servers/PresenceSearchPlayer/test/UniSpy.Server.PresenceSearchPlayer.Test.csproj deleted file mode 100644 index 56714d7eb..000000000 --- a/src/Servers/PresenceSearchPlayer/test/UniSpy.Server.PresenceSearchPlayer.Test.csproj +++ /dev/null @@ -1,31 +0,0 @@ - - - - net6.0 - false - ..\..\..\..\common\Icon\UniSpy_Logo.ico - - - AnyCPU - ..\..\..\..\build\$(Configuration) - - - ..\..\..\..\build\$(Configuration) - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - \ No newline at end of file diff --git a/src/Servers/QueryReport/src/Aggregate/Redis/PeerRoomInfo.cs b/src/Servers/QueryReport/src/Aggregate/Redis/PeerRoomInfo.cs deleted file mode 100644 index 81284b4e1..000000000 --- a/src/Servers/QueryReport/src/Aggregate/Redis/PeerRoomInfo.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.Collections.Generic; - - -//!fix move this to root namespace -namespace UniSpy.Server.QueryReport.Aggregate.Redis.PeerGroup -{ - public record PeerRoomInfo - { - public Guid? ServerId { get; set; } - public string GameName { get; private set; } - public int? GroupId { get; private set; } - public string RoomName { get; private set; } - public int NumberOfWaitingPlayers - { - get => int.Parse(KeyValues["numwaiting"]); - set => KeyValues["numwaiting"] = value.ToString(); - } - public int MaxNumberOfWaitingPlayers - { - get => int.Parse(KeyValues["maxwaiting"]); - set => KeyValues["maxwaiting"] = value.ToString(); - } - public int NumberOfServers - { - get => int.Parse(KeyValues["numservers"]); - set => KeyValues["numservers"] = value.ToString(); - } - - public int MaxNumberOfPlayers - { - get => int.Parse(KeyValues["maxplayers"]); - set => KeyValues["maxplayers"] = value.ToString(); - } - public string Password => (string)KeyValues["password"]; - public int NumberOfGames - { - get => int.Parse(KeyValues["numgames"]); - set => KeyValues["numgames"] = value.ToString(); - } - public int NumberOfPlayers - { - get => int.Parse(KeyValues["numplayers"]); - set => KeyValues["numplayers"] = value.ToString(); - } - public int NumberOfPlayingPlayers - { - get => int.Parse(KeyValues["numplaying"]); - set => KeyValues["numplaying"] = value.ToString(); - } - public Dictionary KeyValues { get; private set; } = new Dictionary(); - public PeerRoomInfo(string gameName, int groupId, string roomName) - { - // this is the default value that every game needed - GameName = gameName; - GroupId = groupId; - RoomName = roomName; - KeyValues.Add("groupid", groupId.ToString()); - KeyValues.Add("hostname", roomName); - KeyValues.Add("numwaiting", "0"); - KeyValues.Add("maxwaiting", "200"); - KeyValues.Add("numservers", "0"); - KeyValues.Add("numplayers", "0"); - KeyValues.Add("maxplayers", "200"); - KeyValues.Add("password", ""); - KeyValues.Add("numgames", "0"); - KeyValues.Add("numplaying", "0"); - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/Application/Client.cs b/src/Servers/QueryReport/src/Application/Client.cs deleted file mode 100644 index d33a6acbd..000000000 --- a/src/Servers/QueryReport/src/Application/Client.cs +++ /dev/null @@ -1,21 +0,0 @@ -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.QueryReport.V2.Handler; - -namespace UniSpy.Server.QueryReport.Application -{ - public sealed class Client : ClientBase - { - public Client(IConnection connection, IServer server) : base(connection, server) - { - IsLogRaw = true; - // launch redis channel - Info = new ClientInfo(); - } - - public new ClientInfo Info { get => (ClientInfo)base.Info; private set => base.Info = value; } - - - protected override ISwitcher CreateSwitcher(object buffer) => new CmdSwitcher(this, (byte[])buffer); - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/Application/ClientInfo.cs b/src/Servers/QueryReport/src/Application/ClientInfo.cs deleted file mode 100644 index 33ed03644..000000000 --- a/src/Servers/QueryReport/src/Application/ClientInfo.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.Core.Abstraction.BaseClass; - -namespace UniSpy.Server.QueryReport.Application -{ - public sealed class ClientInfo : ClientInfoBase - { - public uint? InstantKey { get; set; } - public string GameSecretKey { get; set; } - public ClientInfo() - { - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/Application/Program.cs b/src/Servers/QueryReport/src/Application/Program.cs deleted file mode 100755 index 961d065a4..000000000 --- a/src/Servers/QueryReport/src/Application/Program.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using UniSpy.Server.Core.Logging; - -namespace UniSpy.Server.QueryReport.Application -{ - public class Program - { - static void Main(string[] args) - { - try - { - new ServerLauncher().Start(); - Console.WriteLine("Press < Q > to exit. "); - while (Console.ReadKey().Key != ConsoleKey.Q) { } - } - catch (System.Exception e) - { - LogWriter.LogError(e); - } - } - } -} diff --git a/src/Servers/QueryReport/src/Application/Server.cs b/src/Servers/QueryReport/src/Application/Server.cs deleted file mode 100644 index cd47fe407..000000000 --- a/src/Servers/QueryReport/src/Application/Server.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Net; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Network.Udp.Server; - -namespace UniSpy.Server.QueryReport.Application -{ - public sealed class Server : ServerBase - { - static Server() - { - _name = "QueryReport"; - } - public Server() { } - - public Server(IConnectionManager manager) : base(manager) { } - - public override void Start() - { - base.Start(); - V2.Application.StorageOperation.NatNegChannel.Subscribe(); - } - protected override IClient CreateClient(IConnection connection) => new Client(connection, this); - - protected override IConnectionManager CreateConnectionManager(IPEndPoint endPoint) => new UdpConnectionManager(endPoint); - - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/Application/ServerLauncher.cs b/src/Servers/QueryReport/src/Application/ServerLauncher.cs deleted file mode 100644 index 695fb2fa5..000000000 --- a/src/Servers/QueryReport/src/Application/ServerLauncher.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Core.Abstraction.BaseClass.Factory; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.QueryReport.Application -{ - public sealed class ServerLauncher : ServerLauncherBase - { - protected override List LaunchNetworkService() => new List { new Server() }; - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/Application/StorageOperation.cs b/src/Servers/QueryReport/src/Application/StorageOperation.cs deleted file mode 100644 index 39b264810..000000000 --- a/src/Servers/QueryReport/src/Application/StorageOperation.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using UniSpy.Server.Core.Database.DatabaseModel; -using UniSpy.Server.QueryReport.Aggregate.Redis.Channel; - -namespace UniSpy.Server.QueryReport.Application -{ - public class StorageOperation - { - /// - /// The peer group list in memory - /// - public static readonly Dictionary> PeerGroupList = QueryReport.V2.Application.StorageOperation.Persistance.GetAllGroupList(); - public static QueryReport.Aggregate.Redis.Channel.RedisClient _chatChannelRedisClient = new QueryReport.Aggregate.Redis.Channel.RedisClient(); - public static bool UpdateChannel(ChannelInfo channel) => _chatChannelRedisClient.SetValue(channel); - public static void RemoveChannel(ChannelInfo channel) => _chatChannelRedisClient.DeleteKeyValue(channel); - public static List GetPeerStagingChannel(string gameName, int groupId) - { - var stagingName = $"{PeerRoom.StagingRoomPrefix}!{gameName}!*"; - var groupName = $"{PeerRoom.GroupRoomPrefix}!{groupId}"; - var stagingRooms = QueryReport.Application.StorageOperation._chatChannelRedisClient.Context.Where(c => c.Name == stagingName && c.PreviousJoinedChannel == groupName).ToList(); - return stagingRooms; - } - public static List GetPeerGroupChannel(int groupId) - { - var groupName = $"{PeerRoom.GroupRoomPrefix}!{groupId}"; - var groupRooms = QueryReport.Application.StorageOperation._chatChannelRedisClient.Context.Where(c => c.Name == groupName).ToList(); - return groupRooms; - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/Dockerfile b/src/Servers/QueryReport/src/Dockerfile deleted file mode 100755 index a9b0c8e75..000000000 --- a/src/Servers/QueryReport/src/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM mcr.microsoft.com/dotnet/runtime:6.0 AS base -WORKDIR /app -EXPOSE 27900/udp - -FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build -WORKDIR /src -COPY ["src/Servers/QueryReport/src/UniSpy.Server.QueryReport.csproj", "src/Servers/QueryReport/src/"] -COPY ["src/Libraries/Core/src/UniSpy.Server.Core.csproj", "src/Libraries/Core/src/"] -RUN dotnet restore "src/Servers/QueryReport/src/UniSpy.Server.QueryReport.csproj" -COPY . . -WORKDIR "/src/src/Servers/QueryReport/src" -RUN dotnet build "UniSpy.Server.QueryReport.csproj" -c Release -o /app/build - -FROM build AS publish -RUN dotnet publish "UniSpy.Server.QueryReport.csproj" -c Release -o /app/publish - -FROM base AS final -WORKDIR /app -COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "UniSpy.Server.QueryReport.dll"] \ No newline at end of file diff --git a/src/Servers/QueryReport/src/Exception/Exception.cs b/src/Servers/QueryReport/src/Exception/Exception.cs deleted file mode 100755 index 1f042f547..000000000 --- a/src/Servers/QueryReport/src/Exception/Exception.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace UniSpy.Server.QueryReport -{ - public sealed class Exception : UniSpy.Exception - { - public Exception() - { - } - - public Exception(string message) : base(message) - { - } - - public Exception(string message, System.Exception innerException) : base(message, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/UniSpy.Server.QueryReport.csproj b/src/Servers/QueryReport/src/UniSpy.Server.QueryReport.csproj deleted file mode 100755 index 8b9381e25..000000000 --- a/src/Servers/QueryReport/src/UniSpy.Server.QueryReport.csproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - Exe - net6.0 - ..\..\..\..\common\Icon\UniSpy_Logo.ico - Linux - ..\..\..\.. - - - ..\..\..\..\build\$(Configuration) - - - ..\..\..\..\build\$(Configuration) - - - - - - - - \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V1/Abstraction/BaseClass/CmdHandlerBase.cs b/src/Servers/QueryReport/src/V1/Abstraction/BaseClass/CmdHandlerBase.cs deleted file mode 100644 index 88bb30cde..000000000 --- a/src/Servers/QueryReport/src/V1/Abstraction/BaseClass/CmdHandlerBase.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.QueryReport.Application; - -namespace UniSpy.Server.QueryReport.V1.Abstraction.BaseClass -{ - public abstract class CmdHandlerBase : UniSpy.Server.Core.Abstraction.BaseClass.CmdHandlerBase - { - protected new Client _client => (Client)base._client; - public CmdHandlerBase(Client client, RequestBase request) : base(client, request) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V1/Abstraction/BaseClass/RequestBase.cs b/src/Servers/QueryReport/src/V1/Abstraction/BaseClass/RequestBase.cs deleted file mode 100644 index 554dc3e81..000000000 --- a/src/Servers/QueryReport/src/V1/Abstraction/BaseClass/RequestBase.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using UniSpy.Server.Core.Misc; - -namespace UniSpy.Server.QueryReport.V1.Abstraction.BaseClass -{ - public abstract class RequestBase : UniSpy.Server.Core.Abstraction.BaseClass.RequestBase - { - public new string RawRequest { get => (string)base.RawRequest; protected set => base.RawRequest = value; } - public new string CommandName { get => (string)base.CommandName; protected set => base.CommandName = value; } - public Dictionary KeyValues { get; private set; } - public RequestBase(string rawRequest) : base(rawRequest) - { - } - public override void Parse() - { - KeyValues = GameSpyUtils.ConvertToKeyValue(RawRequest); - CommandName = KeyValues.Keys.First(); - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V1/Abstraction/BaseClass/ResponseBase.cs b/src/Servers/QueryReport/src/V1/Abstraction/BaseClass/ResponseBase.cs deleted file mode 100644 index f3a2eed23..000000000 --- a/src/Servers/QueryReport/src/V1/Abstraction/BaseClass/ResponseBase.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace UniSpy.Server.QueryReport.V1.Abstraction.BaseClass -{ - public abstract class ResponseBase : UniSpy.Server.Core.Abstraction.BaseClass.ResponseBase - { - public new string SendingBuffer { get => (string)base.SendingBuffer; protected set => base.SendingBuffer = value; } - public ResponseBase(RequestBase request, ResultBase result) : base(request, result) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V1/Abstraction/BaseClass/ResultBase.cs b/src/Servers/QueryReport/src/V1/Abstraction/BaseClass/ResultBase.cs deleted file mode 100644 index b2e93529c..000000000 --- a/src/Servers/QueryReport/src/V1/Abstraction/BaseClass/ResultBase.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace UniSpy.Server.QueryReport.V1.Abstraction.BaseClass -{ - public abstract class ResultBase : UniSpy.Server.Core.Abstraction.BaseClass.ResultBase - { - public ResultBase() - { - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V1/Abstraction/Interface/IStorageOperation.cs b/src/Servers/QueryReport/src/V1/Abstraction/Interface/IStorageOperation.cs deleted file mode 100644 index 6ba73d1c9..000000000 --- a/src/Servers/QueryReport/src/V1/Abstraction/Interface/IStorageOperation.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; -using System.Net; -using UniSpy.Server.QueryReport.V1.Aggregation.Redis; - -namespace UniSpy.Server.QueryReport.V1.Abstraction.Interface -{ - public interface IStorageOperation - { - List GetServersInfo(string gameName); - string GetGameSecretKey(string gameName); - GameServerInfo GetServerInfo(IPEndPoint endPoint); - void UpdateServerInfo(GameServerInfo info); - void RemoveServerInfo(IPEndPoint endPoint); - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V1/Aggregation/Enctype0.cs b/src/Servers/QueryReport/src/V1/Aggregation/Enctype0.cs deleted file mode 100644 index 3c3576dbb..000000000 --- a/src/Servers/QueryReport/src/V1/Aggregation/Enctype0.cs +++ /dev/null @@ -1,17 +0,0 @@ -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.QueryReport.V1.Aggregate -{ - public class Enctype0 : ICryptography - { - public byte[] Decrypt(byte[] data) - { - throw new System.NotImplementedException(); - } - - public byte[] Encrypt(byte[] data) - { - throw new System.NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V1/Aggregation/Redis/GameServerInfo.cs b/src/Servers/QueryReport/src/V1/Aggregation/Redis/GameServerInfo.cs deleted file mode 100644 index 5ba020292..000000000 --- a/src/Servers/QueryReport/src/V1/Aggregation/Redis/GameServerInfo.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net; -using Newtonsoft.Json; -using UniSpy.LinqToRedis; -using UniSpy.Server.Core.Config; -using UniSpy.Server.Core.Extension.Redis; -using UniSpy.Server.Core.Misc; - -namespace UniSpy.Server.QueryReport.V1.Aggregation.Redis -{ - public record GameServerInfo : UniSpy.Server.Core.Abstraction.BaseClass.RedisKeyValueObject - { - [RedisKey] - public Guid? ServerID { get; set; } - [RedisKey] - [JsonConverter(typeof(IPAddresConverter))] - public IPAddress HostIPAddress { get; set; } - [RedisKey] - public int? HostPort { get; set; } - [JsonIgnore] - public IPEndPoint HostIPEndPoint => new IPEndPoint(HostIPAddress, (int)HostPort); - [RedisKey] - public string GameName { get; set; } - public bool IsValidated { get; set; } - /// - /// The key values that contians all the information about this game server - /// - public Dictionary KeyValues { get; set; } - public GameServerInfo() : base(RedisDbNumber.GameServerV1, TimeSpan.FromSeconds(30)) - { - } - } - public class RedisClient : RedisClient - { - public RedisClient() : base(ConfigManager.Config.Redis.RedisConnection) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V1/Application/StorageOperation.cs b/src/Servers/QueryReport/src/V1/Application/StorageOperation.cs deleted file mode 100644 index db46e31a6..000000000 --- a/src/Servers/QueryReport/src/V1/Application/StorageOperation.cs +++ /dev/null @@ -1,56 +0,0 @@ -using UniSpy.Server.Core.Database.DatabaseModel; -using UniSpy.Server.QueryReport.V1.Abstraction.Interface; -using System.Linq; -using UniSpy.Server.QueryReport.V1.Aggregation.Redis; -using System.Net; -using System.Collections.Generic; - -namespace UniSpy.Server.QueryReport.V1.Application -{ - public class StorageOperation : IStorageOperation - { - private static RedisClient _redisClient = new RedisClient(); - public static IStorageOperation Persistance = new StorageOperation(); - public string GetGameSecretKey(string gameName) - { - using (var db = new UniSpyContext()) - { - var result = from p in db.Games - where p.Gamename == gameName - select new { p.Secretkey }; - - if (result.Count() != 1) - { - throw new QueryReport.Exception($"No secret key found for game:{gameName}"); - } - return result.First().Secretkey; - } - } - public List GetServersInfo(string gameName) - { - var result = _redisClient.Context.Where(s => s.GameName == gameName).ToList(); - return result; - } - public GameServerInfo GetServerInfo(IPEndPoint endPoint) - { - var result = _redisClient.Context.Where(s => s.HostIPAddress == endPoint.Address && s.HostPort == endPoint.Port); - if (result.Count() != 1) - { - throw new QueryReport.Exception("Multiple server found in redis."); - } - return result.First(); - } - public void UpdateServerInfo(GameServerInfo info) - { - _ = _redisClient.SetValueAsync(info); - } - public void RemoveServerInfo(IPEndPoint endPoint) - { - var result = _redisClient.Context.Where(s => s.HostIPAddress == endPoint.Address && s.HostPort == endPoint.Port); - foreach (var info in result) - { - _redisClient.DeleteKeyValue(info); - } - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V1/Contract/Request/EchoRequest.cs b/src/Servers/QueryReport/src/V1/Contract/Request/EchoRequest.cs deleted file mode 100644 index a7a5e5f03..000000000 --- a/src/Servers/QueryReport/src/V1/Contract/Request/EchoRequest.cs +++ /dev/null @@ -1,27 +0,0 @@ -using UniSpy.Server.QueryReport.V1.Abstraction.BaseClass; - -namespace UniSpy.Server.QueryReport.V1.Contract.Request -{ - public sealed class EchoRequest : RequestBase - { - public string Validate { get; private set; } - public string GameName { get; private set; } - public EchoRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - if (!KeyValues.ContainsKey("validate")) - { - throw new QueryReport.Exception("validate missing from request."); - } - if (!KeyValues.ContainsKey("gamename")) - { - throw new QueryReport.Exception("gamename missing from request."); - } - - throw new System.NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V1/Contract/Request/HeartbeatRequest.cs b/src/Servers/QueryReport/src/V1/Contract/Request/HeartbeatRequest.cs deleted file mode 100644 index 260c1aba4..000000000 --- a/src/Servers/QueryReport/src/V1/Contract/Request/HeartbeatRequest.cs +++ /dev/null @@ -1,39 +0,0 @@ -using UniSpy.Server.QueryReport.V1.Abstraction.BaseClass; - - -namespace UniSpy.Server.QueryReport.V1.Contract.Request -{ - public sealed class HeartbeatRequest : RequestBase - { - public int QueryReportPort { get; private set; } - public string GameName { get; private set; } - public bool IsStateChanged { get; private set; } - public HeartbeatRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - if (!KeyValues.ContainsKey("heartbeat")) - { - throw new QueryReport.Exception("No query report port found."); - } - if (!int.TryParse(KeyValues["heartbeat"], out var port)) - { - throw new QueryReport.Exception("Query report port invalid."); - } - QueryReportPort = port; - if (!KeyValues.ContainsKey("gamename")) - { - throw new QueryReport.Exception("No gamename found."); - } - GameName = KeyValues["gamename"]; - - if (KeyValues.ContainsKey("statechanged")) - { - IsStateChanged = true; - } - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V1/Contract/Request/ValidateRequest.cs b/src/Servers/QueryReport/src/V1/Contract/Request/ValidateRequest.cs deleted file mode 100644 index 062b30375..000000000 --- a/src/Servers/QueryReport/src/V1/Contract/Request/ValidateRequest.cs +++ /dev/null @@ -1,22 +0,0 @@ - -using UniSpy.Server.QueryReport.V1.Abstraction.BaseClass; - -namespace UniSpy.Server.QueryReport.V1.Contract.Request -{ - public sealed class ValidateRequest : RequestBase - { - public string ValidateKey { get; private set; } - public ValidateRequest(string rawRequest) : base(rawRequest) - { - } - public override void Parse() - { - base.Parse(); - if (!KeyValues.ContainsKey("validate")) - { - throw new QueryReport.Exception("validate request format not correct."); - } - ValidateKey = KeyValues["validate"]; - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V1/Contract/Response/EchoResponse.cs b/src/Servers/QueryReport/src/V1/Contract/Response/EchoResponse.cs deleted file mode 100644 index 91b712bc6..000000000 --- a/src/Servers/QueryReport/src/V1/Contract/Response/EchoResponse.cs +++ /dev/null @@ -1,17 +0,0 @@ - -using UniSpy.Server.QueryReport.V1.Abstraction.BaseClass; - -namespace UniSpy.Server.QueryReport.V1.Contract.Response -{ - public sealed class EchoResponse : ResponseBase - { - public EchoResponse(RequestBase request) : base(request, null) - { - } - - public override void Build() - { - SendingBuffer = $@"/echo/{HeartbeatResponse.Challenge}/final/"; - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V1/Contract/Response/HeartbeatResponse.cs b/src/Servers/QueryReport/src/V1/Contract/Response/HeartbeatResponse.cs deleted file mode 100644 index caa983187..000000000 --- a/src/Servers/QueryReport/src/V1/Contract/Response/HeartbeatResponse.cs +++ /dev/null @@ -1,17 +0,0 @@ -using UniSpy.Server.QueryReport.V1.Abstraction.BaseClass; -using UniSpy.Server.QueryReport.V1.Contract.Request; - -namespace UniSpy.Server.QueryReport.V1.Contract.Response -{ - public sealed class HeartbeatResponse : ResponseBase - { - public const string Challenge = "000000"; - public HeartbeatResponse(HeartbeatRequest request) : base(request, null) - { - } - public override void Build() - { - SendingBuffer = $@"/secure/{Challenge}/final/"; - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V1/Handler/CmdHandler/EchoHandler.cs b/src/Servers/QueryReport/src/V1/Handler/CmdHandler/EchoHandler.cs deleted file mode 100644 index cf129189d..000000000 --- a/src/Servers/QueryReport/src/V1/Handler/CmdHandler/EchoHandler.cs +++ /dev/null @@ -1,22 +0,0 @@ -using UniSpy.Server.QueryReport.Application; -using UniSpy.Server.QueryReport.V1.Abstraction.BaseClass; -using UniSpy.Server.QueryReport.V1.Contract.Request; -using UniSpy.Server.QueryReport.V1.Contract.Response; - -namespace UniSpy.Server.QueryReport.V1.Handler.CmdHandler -{ - /// - /// Keep alive request - /// - public sealed class EchoHandler : CmdHandlerBase - { - private new EchoRequest _request => (EchoRequest)base._request; - public EchoHandler(Client client, EchoRequest request) : base(client, request) - { - } - protected override void ResponseConstruct() - { - _response = new EchoResponse(_request); - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V1/Handler/CmdHandler/HeartbeatHandler.cs b/src/Servers/QueryReport/src/V1/Handler/CmdHandler/HeartbeatHandler.cs deleted file mode 100644 index fc4f44df4..000000000 --- a/src/Servers/QueryReport/src/V1/Handler/CmdHandler/HeartbeatHandler.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Net; -using UniSpy.Server.QueryReport.Application; -using UniSpy.Server.QueryReport.V1.Abstraction.BaseClass; -using UniSpy.Server.QueryReport.V1.Aggregation.Redis; -using UniSpy.Server.QueryReport.V1.Contract.Request; -using UniSpy.Server.QueryReport.V1.Contract.Response; - -namespace UniSpy.Server.QueryReport.V1.Handler.CmdHandler -{ - public sealed class HeartbeatHandler : CmdHandlerBase - { - private new HeartbeatRequest _request => (HeartbeatRequest)base._request; - public HeartbeatHandler(Client client, HeartbeatRequest request) : base(client, request) - { - } - protected override void DataOperation() - { - // _result.Challenge = Challenge; - var gameServerEnd = new IPEndPoint(_client.Connection.RemoteIPEndPoint.Address, _request.QueryReportPort); - _client.Info.GameSecretKey = QueryReport.V1.Application.StorageOperation.Persistance.GetGameSecretKey(_request.GameName); - // _result.Challenge = Challenge; - var info = new GameServerInfo() - { - ServerID = _client.Server.Id, - HostIPAddress = _client.Connection.RemoteIPEndPoint.Address, - // check whether this indicate game port - HostPort = _request.QueryReportPort, - GameName = _request.GameName, - KeyValues = _request.KeyValues - }; - //todo whether we need to update the part that info changed - QueryReport.V1.Application.StorageOperation.Persistance.UpdateServerInfo(info); - } - protected override void ResponseConstruct() - { - _response = new HeartbeatResponse(_request); - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V1/Handler/CmdHandler/ValidateHandler.cs b/src/Servers/QueryReport/src/V1/Handler/CmdHandler/ValidateHandler.cs deleted file mode 100644 index dd4a11df9..000000000 --- a/src/Servers/QueryReport/src/V1/Handler/CmdHandler/ValidateHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.QueryReport.Application; -using UniSpy.Server.QueryReport.V1.Abstraction.BaseClass; -using UniSpy.Server.QueryReport.V1.Contract.Request; - -namespace UniSpy.Server.QueryReport.V1.Handler.CmdHandler -{ - /// - /// After sending heartbeat response, the game server will send validate to qr server to indicate his identity - /// - public sealed class ValidateHandler : CmdHandlerBase - { - public ValidateHandler(Client client, ValidateRequest request) : base(client, request) - { - } - protected override void DataOperation() - { - throw new System.Exception(); - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V1/Handler/CmdSwitcher.cs b/src/Servers/QueryReport/src/V1/Handler/CmdSwitcher.cs deleted file mode 100644 index 6f61a8bc8..000000000 --- a/src/Servers/QueryReport/src/V1/Handler/CmdSwitcher.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Logging; -using UniSpy.Server.Core.Misc; -using UniSpy.Server.QueryReport.Application; - -namespace UniSpy.Server.QueryReport.V1.Handler -{ - public sealed class CmdSwitcher : CmdSwitcherBase - { - private new string _rawRequest => (string)base._rawRequest; - private new Client _client => (Client)base._client; - public CmdSwitcher(Client client, object rawRequest) : base(client, rawRequest) - { - } - - protected override IHandler CreateCmdHandlers(object name, object rawRequest) - { - //todo add v1 support - _client.LogError("todo add v1 support"); - switch ((string)name) - { - case "heartbeat": - case "echo": - case "validate": - default: - return null; - } - } - - protected override void ProcessRawRequest() - { - // qr v1 protocol - var name = GameSpyUtils.GetRequestName(_rawRequest); - _requests.Add(new KeyValuePair(name, _rawRequest)); - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V2/Abstraction/BaseClass/CmdHandlerBase.cs b/src/Servers/QueryReport/src/V2/Abstraction/BaseClass/CmdHandlerBase.cs deleted file mode 100755 index b4e557463..000000000 --- a/src/Servers/QueryReport/src/V2/Abstraction/BaseClass/CmdHandlerBase.cs +++ /dev/null @@ -1,15 +0,0 @@ -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.QueryReport.Application; - -namespace UniSpy.Server.QueryReport.V2.Abstraction.BaseClass -{ - public abstract class CmdHandlerBase : UniSpy.Server.Core.Abstraction.BaseClass.CmdHandlerBase - { - protected new Client _client => (Client)base._client; - protected new RequestBase _request => (RequestBase)base._request; - protected new ResultBase _result { get => (ResultBase)base._result; set => base._result = value; } - protected CmdHandlerBase(IClient client, IRequest request) : base(client, request) - { - } - } -} diff --git a/src/Servers/QueryReport/src/V2/Abstraction/BaseClass/RequestBase.cs b/src/Servers/QueryReport/src/V2/Abstraction/BaseClass/RequestBase.cs deleted file mode 100755 index 36026532c..000000000 --- a/src/Servers/QueryReport/src/V2/Abstraction/BaseClass/RequestBase.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Linq; -using UniSpy.Server.QueryReport.V2.Enumerate; - - -namespace UniSpy.Server.QueryReport.V2.Abstraction.BaseClass -{ - public abstract class RequestBase : UniSpy.Server.Core.Abstraction.BaseClass.RequestBase - { - public static readonly byte[] MagicData = { 0xFE, 0XFD }; - public uint? InstantKey { get; protected set; } - public new RequestType CommandName { get => (RequestType)base.CommandName; set => base.CommandName = value; } - public new byte[] RawRequest { get => (byte[])base.RawRequest; protected set => base.RawRequest = value; } - - public RequestBase(byte[] rawRequest) : base(rawRequest) - { - } - - protected RequestBase() - { - } - - public override void Parse() - { - if (RawRequest.Length < 3) - { - throw new QueryReport.Exception("Query report request is invalid."); - } - CommandName = (RequestType)RawRequest[0]; - var instantKeyBytes = RawRequest.Skip(1).Take(4).ToArray(); - InstantKey = BitConverter.ToUInt32(instantKeyBytes); - } - } -} diff --git a/src/Servers/QueryReport/src/V2/Abstraction/BaseClass/ResponseBase.cs b/src/Servers/QueryReport/src/V2/Abstraction/BaseClass/ResponseBase.cs deleted file mode 100755 index 9c0ca96e2..000000000 --- a/src/Servers/QueryReport/src/V2/Abstraction/BaseClass/ResponseBase.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace UniSpy.Server.QueryReport.V2.Abstraction.BaseClass -{ - public abstract class ResponseBase : UniSpy.Server.Core.Abstraction.BaseClass.ResponseBase - { - protected new RequestBase _request => (RequestBase)base._request; - protected new ResultBase _result => (ResultBase)base._result; - public new byte[] SendingBuffer - { - get => (byte[])base.SendingBuffer; - protected set => base.SendingBuffer = value; - } - public ResponseBase(RequestBase request, ResultBase result) : base(request, result) - { - } - - public override void Build() - { - List data = new List(); - data.AddRange(RequestBase.MagicData); - data.Add((byte)_request.CommandName); - data.AddRange(BitConverter.GetBytes((uint)_request.InstantKey)); - SendingBuffer = data.ToArray(); - } - } -} diff --git a/src/Servers/QueryReport/src/V2/Abstraction/BaseClass/ResultBase.cs b/src/Servers/QueryReport/src/V2/Abstraction/BaseClass/ResultBase.cs deleted file mode 100755 index 05aee3a9b..000000000 --- a/src/Servers/QueryReport/src/V2/Abstraction/BaseClass/ResultBase.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.QueryReport.V2.Enumerate; - -namespace UniSpy.Server.QueryReport.V2.Abstraction.BaseClass -{ - public abstract class ResultBase : UniSpy.Server.Core.Abstraction.BaseClass.ResultBase - { - public PacketType? PacketType { get; protected set; } - public ResultBase() - { - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V2/Abstraction/Interface/IStorageOperation.cs b/src/Servers/QueryReport/src/V2/Abstraction/Interface/IStorageOperation.cs deleted file mode 100644 index 926da73de..000000000 --- a/src/Servers/QueryReport/src/V2/Abstraction/Interface/IStorageOperation.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Collections.Generic; -using System.Net; -using UniSpy.Server.QueryReport.V2.Aggregate.Redis.GameServer; -using UniSpy.Server.QueryReport.V2.Contract.Request; - -namespace UniSpy.Server.QueryReport.V2.Abstraction.Interface -{ - public interface IStorageOperation - { - List GetServerInfos(uint instantKey); - void UpdateGameServer(GameServerInfo info); - void RemoveGameServer(GameServerInfo info); - GameServerInfo GetGameServerInfo(IPEndPoint end); - List GetGameServerInfos(string gameName); - Dictionary> GetAllGroupList(); - public void PublishClientMessage(ClientMessageRequest message); - - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V2/Aggregate/Misc/Encryption.cs b/src/Servers/QueryReport/src/V2/Aggregate/Misc/Encryption.cs deleted file mode 100755 index 00c766a22..000000000 --- a/src/Servers/QueryReport/src/V2/Aggregate/Misc/Encryption.cs +++ /dev/null @@ -1,116 +0,0 @@ -namespace UniSpy.Server.QueryReport.V2.Handler.SystemHandler.Encryption -{ - public class Encryption - { - public static byte GSValFunc(int reg) - { - if (reg < 26) - return (byte)(reg + 'A'); - - if (reg < 52) - return (byte)(reg + 'G'); - - if (reg < 62) - return (byte)(reg - 4); - - if (reg == 62) - return (byte)('+'); - - if (reg == 63) - return (byte)('/'); - - return (0); - } - - public static byte[] GSSecKey(byte[] dst, byte[] src, byte[] key, int enctype) - { - int i, size, keysz; - - byte[] enctmp = new byte[256]; - byte[] tmp = new byte[66]; - byte x, y, z, a, b; - //byte[] p; - byte[] enctype1_data = { - 0x01,0xba,0xfa,0xb2,0x51,0x00,0x54,0x80,0x75,0x16,0x8e,0x8e,0x02,0x08,0x36, - 0xa5,0x2d,0x05,0x0d,0x16,0x52,0x07,0xb4,0x22,0x8c,0xe9,0x09,0xd6,0xb9,0x26, - 0x00,0x04,0x06,0x05,0x00,0x13,0x18,0xc4,0x1e,0x5b,0x1d,0x76,0x74,0xfc,0x50, - 0x51,0x06,0x16,0x00,0x51,0x28,0x00,0x04,0x0a,0x29,0x78,0x51,0x00,0x01,0x11, - 0x52,0x16,0x06,0x4a,0x20,0x84,0x01,0xa2,0x1e,0x16,0x47,0x16,0x32,0x51,0x9a, - 0xc4,0x03,0x2a,0x73,0xe1,0x2d,0x4f,0x18,0x4b,0x93,0x4c,0x0f,0x39,0x0a,0x00, - 0x04,0xc0,0x12,0x0c,0x9a,0x5e,0x02,0xb3,0x18,0xb8,0x07,0x0c,0xcd,0x21,0x05, - 0xc0,0xa9,0x41,0x43,0x04,0x3c,0x52,0x75,0xec,0x98,0x80,0x1d,0x08,0x02,0x1d, - 0x58,0x84,0x01,0x4e,0x3b,0x6a,0x53,0x7a,0x55,0x56,0x57,0x1e,0x7f,0xec,0xb8, - 0xad,0x00,0x70,0x1f,0x82,0xd8,0xfc,0x97,0x8b,0xf0,0x83,0xfe,0x0e,0x76,0x03, - 0xbe,0x39,0x29,0x77,0x30,0xe0,0x2b,0xff,0xb7,0x9e,0x01,0x04,0xf8,0x01,0x0e, - 0xe8,0x53,0xff,0x94,0x0c,0xb2,0x45,0x9e,0x0a,0xc7,0x06,0x18,0x01,0x64,0xb0, - 0x03,0x98,0x01,0xeb,0x02,0xb0,0x01,0xb4,0x12,0x49,0x07,0x1f,0x5f,0x5e,0x5d, - 0xa0,0x4f,0x5b,0xa0,0x5a,0x59,0x58,0xcf,0x52,0x54,0xd0,0xb8,0x34,0x02,0xfc, - 0x0e,0x42,0x29,0xb8,0xda,0x00,0xba,0xb1,0xf0,0x12,0xfd,0x23,0xae,0xb6,0x45, - 0xa9,0xbb,0x06,0xb8,0x88,0x14,0x24,0xa9,0x00,0x14,0xcb,0x24,0x12,0xae,0xcc, - 0x57,0x56,0xee,0xfd,0x08,0x30,0xd9,0xfd,0x8b,0x3e,0x0a,0x84,0x46,0xfa,0x77,0xb8 - }; - - size = src.Length; - - if (size < 1 || size > 65) - { - dst[0] = 0; - return dst; - } - - keysz = key.Length; - - for (i = 0; i < 256; i++) - { - enctmp[i] = (byte)i; - } - - a = 0; b = 0; - - for (i = 0; src[i] != 0; i++) - { - a += (byte)(src[i] + 1); - x = enctmp[a]; - b += x; - y = enctmp[b]; - enctmp[b] = x; - enctmp[a] = y; - tmp[i] = (byte)(src[i] ^ enctmp[(x + y) & 0xff]); - } - - for (size = i; size % 3 != 0; size++) - { - tmp[size] = 0; - } - - if (enctype == 1) - { - for (i = 0; i < size; i++) - { - tmp[i] = enctype1_data[tmp[i]]; - } - } - else if (enctype == 2) - { - for (i = 0; i < size; i++) - { - tmp[i] ^= key[i % keysz]; - } - } - - for (i = 0; i < size; i += 3) - { - x = tmp[i]; - y = tmp[i + 1]; - z = tmp[i + 2]; - - dst[i++] = GSValFunc(x >> 2); - dst[i++] = GSValFunc(((x & 3) << 4) | (y >> 4)); - dst[i++] = GSValFunc(((y & 15) << 2) | (z >> 6)); - dst[i++] = GSValFunc(z & 63); - } - - return dst; - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V2/Aggregate/Misc/NatNegCookie.cs b/src/Servers/QueryReport/src/V2/Aggregate/Misc/NatNegCookie.cs deleted file mode 100755 index 024c16236..000000000 --- a/src/Servers/QueryReport/src/V2/Aggregate/Misc/NatNegCookie.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Net; -using Newtonsoft.Json; -using UniSpy.Server.Core.Misc; - -namespace UniSpy.Server.QueryReport.V2.Aggregate.NatNeg -{ - public record NatNegCookie - { - [JsonConverter(typeof(IPAddresConverter))] - public IPAddress HostIPAddress { get; init; } - public ushort HostPort { get; init; } - [JsonConverter(typeof(IPEndPointConverter))] - public IPEndPoint HeartBeatIPEndPoint { get; init; } - public string GameName { get; init; } - public byte[] NatNegMessage { get; init; } - public uint InstantKey { get; init; } - - public NatNegCookie() - { - } - } -} diff --git a/src/Servers/QueryReport/src/V2/Aggregate/Misc/RegionID.cs b/src/Servers/QueryReport/src/V2/Aggregate/Misc/RegionID.cs deleted file mode 100755 index 0bc63c8d0..000000000 --- a/src/Servers/QueryReport/src/V2/Aggregate/Misc/RegionID.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace UniSpy.Server.QueryReport.V2.Aggregate -{ - public enum RegionID - { - Americas = 1, - NorthAmerica = 2, - Caribbean = 4, - CentralAmerica = 8, - SouthAmerica = 16, - Africa = 32, - CentralAfrica = 64, - EastAfrica = 128, - NorthAfrica = 256, - SouthAfrica = 512, - WestAfrica = 1024, - Asia = 2048, - EastAsia = 4096, - Pacific = 8192, - SouthAsia = 16384, - SouthEastAsia = 32768, - Europe = 65536, - BalticStates = 131072, - CIS = 262144, - EasternEurope = 524288, - MiddleEast = 1048576, - SouthEastEurope = 2097152, - WesternEurope = 4194304 - - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V2/Aggregate/Redis/ChannelInfo.cs b/src/Servers/QueryReport/src/V2/Aggregate/Redis/ChannelInfo.cs deleted file mode 100644 index 6cb6613d4..000000000 --- a/src/Servers/QueryReport/src/V2/Aggregate/Redis/ChannelInfo.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using UniSpy.LinqToRedis; -using UniSpy.Server.Core.Config; -using UniSpy.Server.Core.Extension.Redis; - -namespace UniSpy.Server.QueryReport.Aggregate.Redis.Channel -{ - - public static class PeerRoom - { - /// - /// When game connects to the server, the player will enter the default channel for communicating with other players. - /// - public const string TitleRoomPrefix = "#GSP"; - /// - /// When a player creates their own game and is waiting for others to join they are placed in a separate chat room called the "staging room" - /// Staging rooms have two title seperator like #GSP!xxxx!xxxx - /// - public const string StagingRoomPrefix = "#GSP"; - /// - /// group rooms is used split the list of games into categories (by gametype, skill, region, etc.). In this case, when entering the title room, the user would get a list of group rooms instead of a list of games - /// Group room have one title seperator like #GPG!xxxxxx - /// - public const string GroupRoomPrefix = "#GPG"; - public const char TitleSeperator = '!'; - /// - /// Group room #GPG!622 - /// Staging room #GSP!worms3!Ml4lz344lM - /// Normal room #islanbul - /// - /// - /// - public static PeerRoomType GetRoomType(string channelName) - { - if (IsGroupRoom(channelName)) - { - // var c = StorageOperation.Persistance.IsPeerLobby(channelName); - - return PeerRoomType.Group; - } - else if (IsStagingRoom(channelName)) - { - return PeerRoomType.Staging; - } - else if (IsTitleRoom(channelName)) - { - return PeerRoomType.Title; - } - else - { - return PeerRoomType.Normal; - } - } - private static bool IsStagingRoom(string channelName) - { - var a = channelName.Count(c => c == TitleSeperator) == 2 ? true : false; - var b = channelName.StartsWith(StagingRoomPrefix, StringComparison.CurrentCultureIgnoreCase) ? true : false; - return a && b; - } - private static bool IsTitleRoom(string channelName) - { - var a = channelName.Count(c => c == TitleSeperator) == 1 ? true : false; - var b = channelName.StartsWith(TitleRoomPrefix, StringComparison.CurrentCultureIgnoreCase) ? true : false; - return a && b; - } - private static bool IsGroupRoom(string channelName) - { - - var a = channelName.Count(c => c == TitleSeperator) == 1 ? true : false; - var b = channelName.StartsWith(GroupRoomPrefix, StringComparison.CurrentCultureIgnoreCase) ? true : false; - return a && b; - } - } - public enum PeerRoomType - { - /// - /// The main room for a game. - /// - Title, - /// - /// A room where players meet before starting a game. - /// - Staging, - /// - /// A room which is, in general, for a particular type of gameplay (team, dm, etc.). - /// - Group, - /// - /// The normal room - /// - Normal - } - /// - /// The channel info that stored in redis - /// - public record ChannelInfo : UniSpy.Server.Core.Abstraction.BaseClass.RedisKeyValueObject - { - [RedisKey] - public Guid? ServerId { get; set; } - [RedisKey] - public string Name { get; set; } - [RedisKey] - public string PreviousJoinedChannel { get; set; } - public PeerRoomType? RoomType { get; set; } - public int? GroupId { get; set; } - public string RoomName { get; set; } - public string GameName { get; set; } - public int MaxNumberUser { get; set; } - public DateTime CreateTime { get; set; } - public List Users { get; set; } - public ChannelInfo() : base(RedisDbNumber.ChatChannel, TimeSpan.FromHours(1)) { } - } - public class RedisClient : UniSpy.Server.Core.Abstraction.BaseClass.RedisClient - { - public RedisClient() { } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V2/Aggregate/Redis/GameServerInfo.cs b/src/Servers/QueryReport/src/V2/Aggregate/Redis/GameServerInfo.cs deleted file mode 100644 index 883f7553b..000000000 --- a/src/Servers/QueryReport/src/V2/Aggregate/Redis/GameServerInfo.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net; -using Newtonsoft.Json; -using UniSpy.LinqToRedis; -using UniSpy.Server.QueryReport.V2.Enumerate; -using UniSpy.Server.Core.Config; -using UniSpy.Server.Core.Misc; -using UniSpy.Server.Core.Extension.Redis; -using System.Linq; - -namespace UniSpy.Server.QueryReport.V2.Aggregate.Redis.GameServer -{ - public record GameServerInfo : UniSpy.Server.Core.Abstraction.BaseClass.RedisKeyValueObject - { - [RedisKey] - public Guid? ServerID { get; set; } - [RedisKey] - [JsonConverter(typeof(IPAddresConverter))] - public IPAddress HostIPAddress { get; set; } - [RedisKey] - public uint? InstantKey { get; set; } - [RedisKey] - public string GameName { get; set; } - /// - /// The port for send heartbeat to query report server. - /// When a client want to connect to this game server, Server browser will send natneg message to this port.👌 - /// Must set this as nullable object, otherwise it will have default value - /// - [RedisKey] - public ushort? QueryReportPort { get; set; } - [JsonIgnore] - public IPEndPoint QueryReportIPEndPoint => new IPEndPoint(HostIPAddress, (int)QueryReportPort); - [JsonIgnore] - /// - /// Get the hton bytes of query report port, easy for access - /// - public byte[] QueryReportPortBytes => BitConverter.GetBytes((ushort)QueryReportPort).Reverse().ToArray(); - public DateTime LastPacketReceivedTime { get; set; } - // public IPEndPoint RemoteQueryReportIPEndPoint { get; set; } - public GameServerStatus ServerStatus { get; set; } - public Dictionary ServerData { get; set; } - public List> PlayerData { get; set; } - public List> TeamData { get; set; } - public GameServerInfo() : base(RedisDbNumber.GameServerV2, TimeSpan.FromSeconds(30)) - { - } - } - internal class RedisClient : UniSpy.Server.Core.Abstraction.BaseClass.RedisClient - { - public RedisClient() { } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V2/Aggregate/Redis/HeartBeatChannel.cs b/src/Servers/QueryReport/src/V2/Aggregate/Redis/HeartBeatChannel.cs deleted file mode 100644 index c33f0fc49..000000000 --- a/src/Servers/QueryReport/src/V2/Aggregate/Redis/HeartBeatChannel.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.Core.Extension.Redis; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.QueryReport.V2.Aggregate.Redis.GameServer; - -namespace UniSpy.Server.QueryReport.V2.Aggregate.Redis -{ - public class HeartbeatChannel : RedisChannelBase - { - public HeartbeatChannel() : base(RedisChannelName.HeartbeatChannel) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V2/Aggregate/Redis/NatNegChannel.cs b/src/Servers/QueryReport/src/V2/Aggregate/Redis/NatNegChannel.cs deleted file mode 100644 index a079a10ef..000000000 --- a/src/Servers/QueryReport/src/V2/Aggregate/Redis/NatNegChannel.cs +++ /dev/null @@ -1,29 +0,0 @@ -using UniSpy.Server.QueryReport.V2.Contract.Request; -using UniSpy.Server.QueryReport.V2.Handler.CmdHandler; -using UniSpy.Server.Core.Extension.Redis; -using UniSpy.Server.Core.Extension; -using UniSpy.Server.Core.Logging; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.QueryReport.Application; - -namespace UniSpy.Server.QueryReport.V2.Aggregate.Redis -{ - public sealed class NatNegChannel : RedisChannelBase - { - public NatNegChannel() : base(RedisChannelName.NatNegCookieChannel) - { - } - public override void ReceivedMessage(ClientMessageRequest message) - { - var client = (Client)ClientManagerBase.GetClient(message.TargetIPEndPoint); - if (client is null) - { - LogWriter.LogWarn($"Client:{message.TargetIPEndPoint} not found, we ignore natneg message from SB: {message.ServerBrowserSenderId}"); - return; - } - - client.LogInfo($"Get client message from server browser: {message.ServerBrowserSenderId} [{StringExtensions.ConvertByteToHexString(message.NatNegMessage)}]"); - new ClientMessageHandler(client, message).Handle(); - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V2/Application/StorageOperation.cs b/src/Servers/QueryReport/src/V2/Application/StorageOperation.cs deleted file mode 100644 index 7ac37b6af..000000000 --- a/src/Servers/QueryReport/src/V2/Application/StorageOperation.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.QueryReport.V2.Abstraction.Interface; -using UniSpy.Server.QueryReport.V2.Aggregate.Redis.GameServer; -using System.Linq; -using UniSpy.Server.QueryReport.V2.Aggregate.Redis; -using UniSpy.Server.Core.Database.DatabaseModel; -using System.Net; -using UniSpy.Server.QueryReport.V2.Contract.Request; - -namespace UniSpy.Server.QueryReport.V2.Application -{ - public sealed class StorageOperation : IStorageOperation - { - private static QueryReport.V2.Aggregate.Redis.GameServer.RedisClient _gameServerRedisClient = new QueryReport.V2.Aggregate.Redis.GameServer.RedisClient(); - public static IStorageOperation Persistance = new StorageOperation(); - public static NatNegChannel NatNegChannel = new NatNegChannel(); - /// - /// we do not run subscribe() in QR because QR only need to push. - /// We run subscribe() in SB, because SB need to receive message. - /// - public static HeartbeatChannel HeartbeatChannel = new HeartbeatChannel(); - public List GetServerInfos(uint instantKey) => _gameServerRedisClient.Context.Where(x => x.InstantKey == instantKey).ToList(); - - public void RemoveGameServer(GameServerInfo info) => _gameServerRedisClient.DeleteKeyValue(info); - public void UpdateGameServer(GameServerInfo info) => _ = _gameServerRedisClient.SetValueAsync(info); - public List GetGameServerInfos(string gameName) - { - return _gameServerRedisClient.Context.Where(x => x.GameName == gameName).ToList(); - } - - public Dictionary> GetAllGroupList() - { - using (var db = new UniSpyContext()) - { - var result = from g in db.Games - join gl in db.Grouplists on g.Gameid equals gl.Gameid - select new Grouplist - { - Game = g, - Gameid = g.Gameid, - Groupid = gl.Groupid, - Roomname = gl.Roomname - }; - var result2 = from g in result - group g by g.Game.Gamename into dd - select new KeyValuePair>(dd.Key, dd.ToList()); - - var data = result2.ToDictionary(x => x.Key, x => x.Value); - return data; - } - } - public GameServerInfo GetGameServerInfo(IPEndPoint end) - { - return _gameServerRedisClient.Context.FirstOrDefault(x => - x.HostIPAddress == end.Address & - x.QueryReportPort == (ushort)end.Port); - } - - // publish client message here - public void PublishClientMessage(ClientMessageRequest message) - { - NatNegChannel.PublishMessage(message); - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V2/Contract/Request/AvaliableRequest.cs b/src/Servers/QueryReport/src/V2/Contract/Request/AvaliableRequest.cs deleted file mode 100755 index 07b73aed4..000000000 --- a/src/Servers/QueryReport/src/V2/Contract/Request/AvaliableRequest.cs +++ /dev/null @@ -1,34 +0,0 @@ -using UniSpy.Server.QueryReport.V2.Abstraction.BaseClass; - - -namespace UniSpy.Server.QueryReport.V2.Contract.Request -{ - - public sealed class AvaliableRequest : RequestBase - { - public static readonly byte[] Prefix = { 0x09, 0x00, 0x00, 0x00, 0x00 }; - public static readonly byte Postfix = 0x00; - public AvaliableRequest(byte[] rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - //prefix check - for (int i = 0; i < AvaliableRequest.Prefix.Length; i++) - { - if (RawRequest[i] != AvaliableRequest.Prefix[i]) - { - throw new QueryReport.Exception("Avaliable request prefix is invalid."); - } - } - - //postfix check - if (RawRequest[RawRequest.Length - 1] != AvaliableRequest.Postfix) - { - throw new QueryReport.Exception("Avaliable request postfix is invalid."); - } - } - } -} diff --git a/src/Servers/QueryReport/src/V2/Contract/Request/ChallengeRequest.cs b/src/Servers/QueryReport/src/V2/Contract/Request/ChallengeRequest.cs deleted file mode 100755 index 24dc3a9a4..000000000 --- a/src/Servers/QueryReport/src/V2/Contract/Request/ChallengeRequest.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.QueryReport.V2.Abstraction.BaseClass; - -namespace UniSpy.Server.QueryReport.V2.Contract.Request -{ - - public sealed class ChallengeRequest : RequestBase - { - public ChallengeRequest(byte[] rawRequest) : base(rawRequest) - { - } - } -} diff --git a/src/Servers/QueryReport/src/V2/Contract/Request/ClientMessageAckRequest.cs b/src/Servers/QueryReport/src/V2/Contract/Request/ClientMessageAckRequest.cs deleted file mode 100644 index 65d9d2b2f..000000000 --- a/src/Servers/QueryReport/src/V2/Contract/Request/ClientMessageAckRequest.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.QueryReport.V2.Abstraction.BaseClass; - -namespace UniSpy.Server.QueryReport.V2.Contract.Request -{ - - public sealed class ClientMessageAckRequest : RequestBase - { - public ClientMessageAckRequest(byte[] rawRequest) : base(rawRequest) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V2/Contract/Request/ClientMessageRequest.cs b/src/Servers/QueryReport/src/V2/Contract/Request/ClientMessageRequest.cs deleted file mode 100755 index 9f2700c1f..000000000 --- a/src/Servers/QueryReport/src/V2/Contract/Request/ClientMessageRequest.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Net; -using Newtonsoft.Json; -using UniSpy.Server.QueryReport.V2.Abstraction.BaseClass; -using UniSpy.Server.Core.Misc; -using System.Linq; - -namespace UniSpy.Server.QueryReport.V2.Contract.Request -{ - public sealed class ClientMessageRequest : RequestBase - { - public Guid ServerBrowserSenderId { get; init; } - public new uint? InstantKey { get => base.InstantKey; set => base.InstantKey = value; } - public byte[] NatNegMessage { get; init; } - [JsonConverter(typeof(IPEndPointConverter))] - public IPEndPoint TargetIPEndPoint { get; init; } - /// - /// query report server will check on MessageKey, so this must different than previous ones - /// - /// - public int? MessageKey => new Random().Next(int.MinValue, int.MaxValue); - public uint Cookie => BitConverter.ToUInt32(NatNegMessage.Skip(6).Take(4).ToArray()); - public ClientMessageRequest() : base(null) - { - } - } -} diff --git a/src/Servers/QueryReport/src/V2/Contract/Request/EchoRequest.cs b/src/Servers/QueryReport/src/V2/Contract/Request/EchoRequest.cs deleted file mode 100644 index 5dc1d2cfb..000000000 --- a/src/Servers/QueryReport/src/V2/Contract/Request/EchoRequest.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.QueryReport.V2.Abstraction.BaseClass; - -namespace UniSpy.Server.QueryReport.V2.Contract.Request -{ - - public class EchoRequest : RequestBase - { - public EchoRequest(byte[] rawRequest) : base(rawRequest) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V2/Contract/Request/HeartBeatRequest.cs b/src/Servers/QueryReport/src/V2/Contract/Request/HeartBeatRequest.cs deleted file mode 100755 index 863b7a590..000000000 --- a/src/Servers/QueryReport/src/V2/Contract/Request/HeartBeatRequest.cs +++ /dev/null @@ -1,204 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using UniSpy.Server.QueryReport.V2.Abstraction.BaseClass; -using UniSpy.Server.QueryReport.V2.Enumerate; -using UniSpy.Server.Core.Encryption; -using UniSpy.Server.Core.Logging; - -namespace UniSpy.Server.QueryReport.V2.Contract.Request -{ - - public sealed class HeartBeatRequest : RequestBase - { - public Dictionary ServerData { get; private set; } - public List> PlayerData { get; private set; } - public List> TeamData { get; private set; } - public GameServerStatus ServerStatus { get; private set; } - public uint? GroupId { get; private set; } - public string GameName - { - get - { - List tempKeyVal = DataPartition.Split('\0').ToList(); - int indexOfGameName = tempKeyVal.IndexOf("gamename"); - return tempKeyVal[indexOfGameName + 1]; - } - } - public string DataPartition { get; private set; } - // public HeartBeatReportType ReportType { get; set; } - - public HeartBeatRequest(byte[] rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - int playerPos, teamPos; - int playerLenth, teamLength; - DataPartition = UniSpyEncoding.GetString(RawRequest.Skip(5).ToArray()); - - playerPos = DataPartition.IndexOf("player_\0", StringComparison.Ordinal); - teamPos = DataPartition.IndexOf("team_t\0", StringComparison.Ordinal); - // todo if there is no server data, we whether need to throw exception? - if (playerPos != -1 && teamPos != -1) - { - // ReportType = HeartBeatReportType.ServerTeamPlayerData; - playerLenth = teamPos - playerPos; - teamLength = DataPartition.Length - teamPos; - - var serverDataStr = DataPartition.Substring(0, playerPos - 4); - ParseServerData(serverDataStr); - var playerDataStr = DataPartition.Substring(playerPos - 1, playerLenth - 2); - ParsePlayerData(playerDataStr); - var teamDataStr = DataPartition.Substring(teamPos - 1, teamLength); - ParseTeamData(teamDataStr); - } - else if (playerPos != -1) - { - //normal heart beat - // ReportType = HeartBeatReportType.ServerPlayerData; - playerLenth = DataPartition.Length - playerPos; - var serverDataStr = DataPartition.Substring(0, playerPos - 4); - ParseServerData(serverDataStr); - var playerDataStr = DataPartition.Substring(playerPos - 1, playerLenth); - ParsePlayerData(playerDataStr); - } - else if (playerPos == -1 && teamPos == -1) - { - // ReportType = HeartBeatReportType.ServerData; - var serverDataStr = DataPartition; - ParseServerData(serverDataStr); - } - else - { - throw new QueryReport.Exception("HeartBeat request is invalid."); - } - - if (ServerData.ContainsKey("groupid")) - { - if (!uint.TryParse(ServerData["groupid"], out var groupId)) - { - throw new QueryReport.Exception("GroupId is invalid."); - - } - GroupId = groupId; - } - } - private void ParseServerData(string serverDataStr) - { - ServerData = new Dictionary(); - string[] keyValueArray = serverDataStr.Split("\0"); - - for (int i = 0; i < keyValueArray.Length; i += 2) - { - if (i + 2 > keyValueArray.Length) - { - break; - } - - string tempKey = keyValueArray[i]; - string tempValue = keyValueArray[i + 1]; - - if (tempKey == "") - { - LogWriter.LogVerbose("Skiping empty key value"); - continue; - } - // no matter happens we just update the key value - if (ServerData.ContainsKey(tempKey)) - { - ServerData[tempKey] = tempValue; - } - else - { - ServerData.Add(tempKey, tempValue); - } - } - if (!ServerData.ContainsKey("statechanged")) - { - ServerStatus = GameServerStatus.Normal; - } - else - { - ServerStatus = (GameServerStatus)Enum.Parse(typeof(GameServerStatus), ServerData?["statechanged"]); - } - } - private void ParsePlayerData(string playerDataStr) - { - PlayerData = new List>(); - // _client.LogInfo(StringExtensions.ReplaceUnreadableCharToHex(playerDataStr)); - //TODO check if each update contains all player information - int playerCount = Convert.ToInt32(playerDataStr[0]); - playerDataStr = playerDataStr.Substring(1); - - //we first read the key index - int IndexOfKey = playerDataStr.IndexOf("\0\0", StringComparison.Ordinal); - //then get all the keys - string keyStr = playerDataStr.Substring(0, IndexOfKey); - List keys = keyStr.Split('\0', StringSplitOptions.RemoveEmptyEntries).ToList(); - - string valuesStr = playerDataStr.Substring(IndexOfKey + 2); - List values = valuesStr.Split('\0').ToList(); - - //according to player total number and key total number to add the data into list - for (int playerIndex = 0; playerIndex < playerCount; playerIndex++) - { - Dictionary keyValue = new Dictionary(); - - for (int keyIndex = 0; keyIndex < keys.Count; keyIndex++) - { - string tempKey = keys[keyIndex] + playerIndex.ToString(); - string tempValue = values[playerIndex * keys.Count + keyIndex]; - if (keyValue.ContainsKey(tempKey)) - { - keyValue[tempKey] = tempValue; - } - else - { - keyValue.Add(tempKey, tempValue); - } - } - PlayerData.Add(keyValue); - } - } - private void ParseTeamData(string teamDataStr) - { - TeamData = new List>(); - // _client.LogInfo(// StringExtensions.ReplaceUnreadableCharToHex(teamDataStr)); - //TODO check if each update contains all team information - - int teamCount = System.Convert.ToInt32(teamDataStr[0]); - teamDataStr = teamDataStr.Substring(1); - - int endKeyIndex = teamDataStr.IndexOf("\0\0", System.StringComparison.Ordinal); - string keyStr = teamDataStr.Substring(0, endKeyIndex); - List keys = keyStr.Split('\0', System.StringSplitOptions.RemoveEmptyEntries).ToList(); - - string valueStr = teamDataStr.Substring(endKeyIndex + 2); - List values = valueStr.Split('\0').ToList(); - - for (int teamIndex = 0; teamIndex < teamCount; teamIndex++) - { - Dictionary keyValue = new Dictionary(); - // iterate the index get the keys and values - for (int keyIndex = 0; keyIndex < keys.Count(); keyIndex++) - { - string tempKey = keys[keyIndex] + teamIndex.ToString(); - string tempValue = values[teamIndex * keys.Count + keyIndex]; - if (keyValue.ContainsKey(tempKey)) - { - keyValue[tempKey] = tempValue; - } - else - { - keyValue.Add(tempKey, tempValue); - } - //LogWriter.ToLog(LogEventLevel.Verbose, $"Updated new team key value {tempKey}:{tempValue}"); - } - TeamData.Add(keyValue); - } - } - } -} diff --git a/src/Servers/QueryReport/src/V2/Contract/Request/KeepAliveRequest.cs b/src/Servers/QueryReport/src/V2/Contract/Request/KeepAliveRequest.cs deleted file mode 100644 index 83bc2d107..000000000 --- a/src/Servers/QueryReport/src/V2/Contract/Request/KeepAliveRequest.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.QueryReport.V2.Abstraction.BaseClass; - -namespace UniSpy.Server.QueryReport.V2.Contract.Request -{ - - public class KeepAliveRequest : RequestBase - { - public KeepAliveRequest(byte[] rawRequest) : base(rawRequest) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V2/Contract/Response/AvaliableResponse.cs b/src/Servers/QueryReport/src/V2/Contract/Response/AvaliableResponse.cs deleted file mode 100755 index a483becec..000000000 --- a/src/Servers/QueryReport/src/V2/Contract/Response/AvaliableResponse.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.QueryReport.V2.Abstraction.BaseClass; -using UniSpy.Server.QueryReport.V2.Enumerate; -using UniSpy.Server.QueryReport.V2.Contract.Request; - -namespace UniSpy.Server.QueryReport.V2.Contract.Response -{ - public sealed class AvaliableResponse : ResponseBase - { - public static readonly byte[] ResponsePrefix = { 0xfe, 0xfd, 0x09, 0x00, 0x00, 0x00 }; - - public AvaliableResponse(AvaliableRequest request) : base(request, null) - { - } - - public override void Build() - { - List data = new List(); - - data.AddRange(ResponsePrefix); - data.Add((byte)ServerAvailability.Available); - // NOTE: Change this if you want to make the server not avaliable. - SendingBuffer = data.ToArray(); - } - } -} diff --git a/src/Servers/QueryReport/src/V2/Contract/Response/ChallengeResponse.cs b/src/Servers/QueryReport/src/V2/Contract/Response/ChallengeResponse.cs deleted file mode 100755 index 7e3c0ee4e..000000000 --- a/src/Servers/QueryReport/src/V2/Contract/Response/ChallengeResponse.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.QueryReport.V2.Abstraction.BaseClass; -using UniSpy.Server.QueryReport.V2.Contract.Request; -using UniSpy.Server.QueryReport.V2.Contract.Result; -using UniSpy.Server.Core.Encryption; - -namespace UniSpy.Server.QueryReport.V2.Contract.Response -{ - public sealed class ChallengeResponse : ResponseBase - { - private static string Message = "RetroSpy echo!"; - - public ChallengeResponse(ChallengeRequest request, ChallengeResult result) : base(request, result) - { - } - - public override void Build() - { - base.Build(); - List data = new List(); - - data.AddRange(SendingBuffer); - data.AddRange(UniSpyEncoding.GetBytes(Message)); - - SendingBuffer = data.ToArray(); - } - } -} diff --git a/src/Servers/QueryReport/src/V2/Contract/Response/ClientMessageResponse.cs b/src/Servers/QueryReport/src/V2/Contract/Response/ClientMessageResponse.cs deleted file mode 100755 index 3624e69d0..000000000 --- a/src/Servers/QueryReport/src/V2/Contract/Response/ClientMessageResponse.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using UniSpy.Server.QueryReport.V2.Abstraction.BaseClass; -using UniSpy.Server.QueryReport.V2.Contract.Request; - -namespace UniSpy.Server.QueryReport.V2.Contract.Response -{ - public sealed class ClientMessageResponse : ResponseBase - { - private new ClientMessageRequest _request => (ClientMessageRequest)base._request; - public ClientMessageResponse(ClientMessageRequest request) : base(request, null) - { - } - - public override void Build() - { - base.Build(); - List data = new List(); - data.AddRange(SendingBuffer); - data.AddRange(BitConverter.GetBytes((int)_request.MessageKey)); - data.AddRange(_request.NatNegMessage); - SendingBuffer = data.ToArray(); - } - } -} diff --git a/src/Servers/QueryReport/src/V2/Contract/Response/HeartBeatResponse.cs b/src/Servers/QueryReport/src/V2/Contract/Response/HeartBeatResponse.cs deleted file mode 100755 index 84c4dd5d4..000000000 --- a/src/Servers/QueryReport/src/V2/Contract/Response/HeartBeatResponse.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Collections.Generic; -using UniSpy.Server.QueryReport.V2.Abstraction.BaseClass; -using UniSpy.Server.QueryReport.V2.Contract.Request; -using UniSpy.Server.QueryReport.V2.Contract.Result; - -namespace UniSpy.Server.QueryReport.V2.Contract.Response -{ - public sealed class HeartBeatResponse : ResponseBase - { - private new HeartBeatRequest _request => (HeartBeatRequest)base._request; - private new HeartBeatResult _result => (HeartBeatResult)base._result; - private static readonly byte[] Challenge = { 0x54, 0x54, 0x54, 0x00, 0x00 }; - private static readonly byte[] Spliter = { 0x00, 0x00, 0x00, 0x00 }; - public HeartBeatResponse(HeartBeatRequest request, HeartBeatResult result) : base(request, result) - { - } - - public override void Build() - { - base.Build(); - List data = new List(); - data.AddRange(SendingBuffer); - data.AddRange(Challenge); - data.AddRange(_result.RemoteIPEndPoint.Address.GetAddressBytes()); - data.AddRange(Spliter); - data.AddRange(BitConverter.GetBytes((int)_result.RemoteIPEndPoint.Port)); - SendingBuffer = data.ToArray(); - } - } -} diff --git a/src/Servers/QueryReport/src/V2/Contract/Response/KeepAliveResponse.cs b/src/Servers/QueryReport/src/V2/Contract/Response/KeepAliveResponse.cs deleted file mode 100755 index 65b6fd317..000000000 --- a/src/Servers/QueryReport/src/V2/Contract/Response/KeepAliveResponse.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.QueryReport.V2.Abstraction.BaseClass; -using UniSpy.Server.QueryReport.V2.Contract.Request; - -namespace UniSpy.Server.QueryReport.V2.Contract.Response -{ - public sealed class KeepAliveResponse : ResponseBase - { - public KeepAliveResponse(KeepAliveRequest request) : base(request, null) - { - } - } -} diff --git a/src/Servers/QueryReport/src/V2/Contract/Result/ChallengeResult.cs b/src/Servers/QueryReport/src/V2/Contract/Result/ChallengeResult.cs deleted file mode 100755 index 70ab40c54..000000000 --- a/src/Servers/QueryReport/src/V2/Contract/Result/ChallengeResult.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.QueryReport.V2.Abstraction.BaseClass; - -namespace UniSpy.Server.QueryReport.V2.Contract.Result -{ - public sealed class ChallengeResult : ResultBase - { - public ChallengeResult() - { - PacketType = Enumerate.PacketType.Challenge; - } - } -} diff --git a/src/Servers/QueryReport/src/V2/Contract/Result/ClientMessageResult.cs b/src/Servers/QueryReport/src/V2/Contract/Result/ClientMessageResult.cs deleted file mode 100755 index 2bfb65470..000000000 --- a/src/Servers/QueryReport/src/V2/Contract/Result/ClientMessageResult.cs +++ /dev/null @@ -1,15 +0,0 @@ -using UniSpy.Server.QueryReport.V2.Abstraction.BaseClass; - -namespace UniSpy.Server.QueryReport.V2.Contract.Result -{ - public sealed class ClientMessageResult : ResultBase - { - public byte[] NatNegMessage { get; set; } - public int? MessageKey { get; set; } - public ClientMessageResult() - { - //we need to change packet type to client message then send - PacketType = Enumerate.PacketType.ClientMessage; - } - } -} diff --git a/src/Servers/QueryReport/src/V2/Contract/Result/EchoResult.cs b/src/Servers/QueryReport/src/V2/Contract/Result/EchoResult.cs deleted file mode 100755 index ecabf9139..000000000 --- a/src/Servers/QueryReport/src/V2/Contract/Result/EchoResult.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.QueryReport.V2.Abstraction.BaseClass; -using UniSpy.Server.QueryReport.V2.Aggregate.Redis.GameServer; - -namespace UniSpy.Server.QueryReport.V2.Contract.Result -{ - public sealed class EchoResult : ResultBase - { - public GameServerInfo Info { get; set; } - public EchoResult() - { - } - } -} diff --git a/src/Servers/QueryReport/src/V2/Contract/Result/HeartBeatResult.cs b/src/Servers/QueryReport/src/V2/Contract/Result/HeartBeatResult.cs deleted file mode 100755 index 9ca70f10b..000000000 --- a/src/Servers/QueryReport/src/V2/Contract/Result/HeartBeatResult.cs +++ /dev/null @@ -1,14 +0,0 @@ -using UniSpy.Server.QueryReport.V2.Abstraction.BaseClass; -using System.Net; - -namespace UniSpy.Server.QueryReport.V2.Contract.Result -{ - public sealed class HeartBeatResult : ResultBase - { - public IPEndPoint RemoteIPEndPoint { get; set; } - public HeartBeatResult() - { - PacketType = Enumerate.PacketType.HeartBeat; - } - } -} diff --git a/src/Servers/QueryReport/src/V2/Enumerate/GeneralEnum.cs b/src/Servers/QueryReport/src/V2/Enumerate/GeneralEnum.cs deleted file mode 100755 index 51e524875..000000000 --- a/src/Servers/QueryReport/src/V2/Enumerate/GeneralEnum.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace UniSpy.Server.QueryReport.V2.Enumerate -{ - public enum RequestType : byte - { - //Client request - Challenge = 0x01, - HeartBeat = 0x03, - ClientMessage = 0x06, - ClientMessageAck = 0x07, - AddError = 0x04, - Echo = 0x02, - KeepAlive = 0x08, - AvaliableCheck = 0x09 - } - public enum ResponseType : byte - { - //Server response - Query = 0x00, - Echo = 0x02, - ADDError = 0x04, - ClientMessage = 0x06, - RequireIPVerify = 0x09, - ClientRegistered = 0x0A, - } - public enum PacketType : byte - { - //Server response - Query = 0x00, - Challenge = 0x01, - Echo = 0x02, - ADDError = 0x04, - ClientMessage = 0x06, - RequireIPVerify = 0x09, - ClientRegistered = 0x0A, - - //Client request - HeartBeat = 0x03, - EchoResponse = 0x05, - ClientMessageACK = 0x07, - KeepAlive = 0x08, - AvaliableCheck = 0x09 - } - - public enum QRStateChange : byte - { - NormalHeartBeat = 0, - GameModeChange = 1, - ServerShutDown = 2, - CanNotRecieveChallenge = 3 - } -} diff --git a/src/Servers/QueryReport/src/V2/Enumerate/HeartBeatEnum.cs b/src/Servers/QueryReport/src/V2/Enumerate/HeartBeatEnum.cs deleted file mode 100755 index f81594c91..000000000 --- a/src/Servers/QueryReport/src/V2/Enumerate/HeartBeatEnum.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace UniSpy.Server.QueryReport.V2.Enumerate -{ - public enum HeartBeatReportType - { - ServerTeamPlayerData, - ServerPlayerData, - ServerData, - } - - public enum GameServerStatus - { - Normal = 0, - Update = 1, - Shutdown = 2, - // todo check this flag - Playing = 3, - } -} diff --git a/src/Servers/QueryReport/src/V2/Enumerate/ServerAvailability.cs b/src/Servers/QueryReport/src/V2/Enumerate/ServerAvailability.cs deleted file mode 100755 index 6e6fa7481..000000000 --- a/src/Servers/QueryReport/src/V2/Enumerate/ServerAvailability.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace UniSpy.Server.QueryReport.V2.Enumerate -{ - public enum ServerAvailability : uint - { - Available = 0, - Waiting = 1, - PermanentUnavailable = 2, - TemporarilyUnavailable = 3, - }; -} diff --git a/src/Servers/QueryReport/src/V2/Handler/CmdHandler/AvailableHandler.cs b/src/Servers/QueryReport/src/V2/Handler/CmdHandler/AvailableHandler.cs deleted file mode 100755 index 3c3610496..000000000 --- a/src/Servers/QueryReport/src/V2/Handler/CmdHandler/AvailableHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using UniSpy.Server.QueryReport.V2.Abstraction.BaseClass; -using UniSpy.Server.QueryReport.V2.Contract.Request; -using UniSpy.Server.QueryReport.V2.Contract.Response; -using UniSpy.Server.QueryReport.Application; - -namespace UniSpy.Server.QueryReport.V2.Handler.CmdHandler -{ - /// - /// AvailableCheckHandler - /// - - public sealed class AvailableHandler : CmdHandlerBase - { - private new AvaliableRequest _request => (AvaliableRequest)base._request; - public AvailableHandler(Client client, AvaliableRequest request) : base(client, request) - { - } - protected override void ResponseConstruct() - { - _response = new AvaliableResponse(_request); - } - } -} diff --git a/src/Servers/QueryReport/src/V2/Handler/CmdHandler/ChallengeHandler.cs b/src/Servers/QueryReport/src/V2/Handler/CmdHandler/ChallengeHandler.cs deleted file mode 100755 index a967fc13f..000000000 --- a/src/Servers/QueryReport/src/V2/Handler/CmdHandler/ChallengeHandler.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Linq; -using UniSpy.Server.QueryReport.Application; -using UniSpy.Server.QueryReport.V2.Abstraction.BaseClass; -using UniSpy.Server.QueryReport.V2.Contract.Request; -using UniSpy.Server.QueryReport.V2.Contract.Response; -using UniSpy.Server.QueryReport.V2.Contract.Result; - -namespace UniSpy.Server.QueryReport.V2.Handler.CmdHandler -{ - - public sealed class ChallengeHandler : CmdHandlerBase - { - private new ChallengeRequest _request => (ChallengeRequest)base._request; - //we do not need to implement this to check the correctness of the challenge response - private new ChallengeResult _result { get => (ChallengeResult)base._result; set => base._result = value; } - public ChallengeHandler(Client client, ChallengeRequest request) : base(client, request) - { - _result = new ChallengeResult(); - } - - protected override void DataOperation() - { - var servers = QueryReport.V2.Application.StorageOperation.Persistance.GetServerInfos((uint)_request.InstantKey); - if (servers.Count() == 0) - { - throw new QueryReport.Exception("No server found in redis, please make sure there is only one server."); - } - // _gameServerInfo = servers.First(); - } - - protected override void ResponseConstruct() - { - // We send the echo packet to check the ping - _response = new ChallengeResponse(_request, _result); - } - } -} diff --git a/src/Servers/QueryReport/src/V2/Handler/CmdHandler/ClientMessageAckHandler.cs b/src/Servers/QueryReport/src/V2/Handler/CmdHandler/ClientMessageAckHandler.cs deleted file mode 100644 index 04aa5e1d4..000000000 --- a/src/Servers/QueryReport/src/V2/Handler/CmdHandler/ClientMessageAckHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.QueryReport.V2.Abstraction.BaseClass; -using UniSpy.Server.Core.Logging; -using UniSpy.Server.QueryReport.Application; -using UniSpy.Server.QueryReport.V2.Contract.Request; - -namespace UniSpy.Server.QueryReport.V2.Handler.CmdHandler -{ - - public sealed class ClientMessageAckHandler : CmdHandlerBase - { - public ClientMessageAckHandler(Client client, ClientMessageAckRequest request) : base(client, request) - { - } - protected override void DataOperation() - { - base.DataOperation(); - _client.LogInfo("Get client message ack."); - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/src/V2/Handler/CmdHandler/ClientMessageHandler.cs b/src/Servers/QueryReport/src/V2/Handler/CmdHandler/ClientMessageHandler.cs deleted file mode 100755 index dc62492e8..000000000 --- a/src/Servers/QueryReport/src/V2/Handler/CmdHandler/ClientMessageHandler.cs +++ /dev/null @@ -1,26 +0,0 @@ -using UniSpy.Server.QueryReport.V2.Abstraction.BaseClass; -using UniSpy.Server.QueryReport.V2.Contract.Request; -using UniSpy.Server.QueryReport.V2.Contract.Response; -using UniSpy.Server.Core.Logging; -using UniSpy.Server.QueryReport.Application; - -namespace UniSpy.Server.QueryReport.V2.Handler.CmdHandler -{ - - public sealed class ClientMessageHandler : CmdHandlerBase - { - private new ClientMessageRequest _request => (ClientMessageRequest)base._request; - public ClientMessageHandler(Client client, ClientMessageRequest request) : base(client, request) - { - } - protected override void RequestCheck() - { - // we do not need to execute request.Parse() - _client.LogInfo($"Received client message with cookie: {_request.Cookie}"); - } - protected override void ResponseConstruct() - { - _response = new ClientMessageResponse(_request); - } - } -} diff --git a/src/Servers/QueryReport/src/V2/Handler/CmdHandler/EchoHandler.cs b/src/Servers/QueryReport/src/V2/Handler/CmdHandler/EchoHandler.cs deleted file mode 100755 index 907119d1f..000000000 --- a/src/Servers/QueryReport/src/V2/Handler/CmdHandler/EchoHandler.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Linq; -using UniSpy.Server.QueryReport.V2.Abstraction.BaseClass; -using UniSpy.Server.QueryReport.V2.Contract.Request; -using UniSpy.Server.QueryReport.V2.Contract.Result; -using UniSpy.Server.Core.Logging; -using UniSpy.Server.QueryReport.Application; - -namespace UniSpy.Server.QueryReport.V2.Handler.CmdHandler -{ - - public sealed class EchoHandler : CmdHandlerBase - { - private new EchoRequest _request => (EchoRequest)base._request; - private new EchoResult _result { get => (EchoResult)base._result; set => base._result = value; } - public EchoHandler(Client client, EchoRequest request) : base(client, request) - { - _result = new EchoResult(); - } - - protected override void DataOperation() - { - //TODO prevent one pc create multiple game servers - var servers = QueryReport.V2.Application.StorageOperation.Persistance.GetServerInfos((uint)_request.InstantKey); - if (servers.Count() != 1) - { - _client.LogInfo("Can not find game server"); - return; - } - //add recive echo packet on gameserverList - - //we get the first key in matchedKeys - _result.Info = servers.First(); - _result.Info.LastPacketReceivedTime = DateTime.Now; - // StorageOperation.Persistance.UpdateGameServer(_result.Info); - QueryReport.V2.Application.StorageOperation.Persistance.UpdateGameServer(_result.Info); - } - } -} diff --git a/src/Servers/QueryReport/src/V2/Handler/CmdHandler/HeartBeatHandler.cs b/src/Servers/QueryReport/src/V2/Handler/CmdHandler/HeartBeatHandler.cs deleted file mode 100755 index d21e3811d..000000000 --- a/src/Servers/QueryReport/src/V2/Handler/CmdHandler/HeartBeatHandler.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using UniSpy.Server.QueryReport.V2.Abstraction.BaseClass; -using UniSpy.Server.QueryReport.V2.Enumerate; -using UniSpy.Server.QueryReport.V2.Aggregate.Redis.GameServer; -using UniSpy.Server.QueryReport.V2.Contract.Request; -using UniSpy.Server.QueryReport.V2.Contract.Response; -using UniSpy.Server.QueryReport.V2.Contract.Result; -using UniSpy.Server.QueryReport.Application; - -namespace UniSpy.Server.QueryReport.V2.Handler.CmdHandler -{ - - public sealed class HeartBeatHandler : CmdHandlerBase - { - private new HeartBeatRequest _request => (HeartBeatRequest)base._request; - private new HeartBeatResult _result { get => (HeartBeatResult)base._result; set => base._result = value; } - private GameServerInfo _gameServerInfo; - public HeartBeatHandler(Client client, HeartBeatRequest request) : base(client, request) - { - _result = new HeartBeatResult(); - } - protected override void DataOperation() - { - //Parse the endpoint information into result class - _result.RemoteIPEndPoint = _client.Connection.RemoteIPEndPoint; - - CheckSpamGameServer(); - // todo check if server data is null - //normal heart beat - _gameServerInfo.ServerData = _request.ServerData; - _gameServerInfo.PlayerData = _request.PlayerData; - _gameServerInfo.TeamData = _request.TeamData; - _gameServerInfo.LastPacketReceivedTime = DateTime.Now; - UpdateGameServerByState(); - // we publish message to notice all sb server to send adhoc message to their clients. - QueryReport.V2.Application.StorageOperation.HeartbeatChannel.PublishMessage(_gameServerInfo); - } - - private void UpdateGameServerByState() - { - if (_gameServerInfo.ServerStatus == GameServerStatus.Shutdown) - { - QueryReport.V2.Application.StorageOperation.Persistance.RemoveGameServer(_gameServerInfo); - } - else - { - QueryReport.V2.Application.StorageOperation.Persistance.UpdateGameServer(_gameServerInfo); - } - } - - protected override void ResponseConstruct() - { - _response = new HeartBeatResponse(_request, _result); - } - - private void CheckSpamGameServer() - { - // Ensures that an IP address creates a server for each game, we check if redis has multiple game servers - _gameServerInfo = new GameServerInfo() - { - ServerID = _client.Server.Id, - HostIPAddress = _client.Connection.RemoteIPEndPoint.Address, - QueryReportPort = (ushort)_client.Connection.RemoteIPEndPoint.Port, - GameName = _request.GameName, - InstantKey = _request.InstantKey, - ServerStatus = _request.ServerStatus, - LastPacketReceivedTime = DateTime.Now - }; - } - } -} diff --git a/src/Servers/QueryReport/src/V2/Handler/CmdHandler/KeepAliveHandler.cs b/src/Servers/QueryReport/src/V2/Handler/CmdHandler/KeepAliveHandler.cs deleted file mode 100755 index 7024cd9e9..000000000 --- a/src/Servers/QueryReport/src/V2/Handler/CmdHandler/KeepAliveHandler.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Linq; -using UniSpy.Server.QueryReport.V2.Abstraction.BaseClass; -using UniSpy.Server.QueryReport.Application; -using UniSpy.Server.QueryReport.V2.Contract.Request; - -namespace UniSpy.Server.QueryReport.V2.Handler.CmdHandler -{ - - public sealed class KeepAliveHandler : CmdHandlerBase - { - public KeepAliveHandler(Client client, KeepAliveRequest request) : base(client, request) - { - } - protected override void DataOperation() - { - var result = QueryReport.V2.Application.StorageOperation.Persistance.GetServerInfos((uint)_request.InstantKey); - if (result.Count != 1) - { - throw new QueryReport.Exception("No server or multiple servers found in redis, please make sure there is only one server."); - } - - var gameServer = result.First(); - gameServer.LastPacketReceivedTime = DateTime.Now; - QueryReport.V2.Application.StorageOperation.Persistance.UpdateGameServer(gameServer); - } - } -} diff --git a/src/Servers/QueryReport/src/V2/Handler/CmdSwitcher.cs b/src/Servers/QueryReport/src/V2/Handler/CmdSwitcher.cs deleted file mode 100755 index 36c37345f..000000000 --- a/src/Servers/QueryReport/src/V2/Handler/CmdSwitcher.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.QueryReport.Application; -using UniSpy.Server.QueryReport.V2.Enumerate; -using UniSpy.Server.QueryReport.V2.Handler.CmdHandler; - -namespace UniSpy.Server.QueryReport.V2.Handler -{ - public sealed class CmdSwitcher : CmdSwitcherBase - { - private new byte[] _rawRequest => (byte[])base._rawRequest; - private new Client _client => (Client)base._client; - public CmdSwitcher(Client client, byte[] rawRequest) : base(client, rawRequest) - { - } - protected override void ProcessRawRequest() - { - // var rawRequest = base._rawRequest as byte[]; - if (_rawRequest.Length < 4) - { - throw new UniSpy.Exception("Invalid request"); - } - - // qr v2 protocol - var name = (RequestType)_rawRequest[0]; - var rawRequest = _rawRequest; - _requests.Add(new KeyValuePair(name, rawRequest)); - } - - protected override IHandler CreateCmdHandlers(object name, object rawRequest) - { - var req = (byte[])rawRequest; - // query report v2 - switch ((RequestType)name) - { - case RequestType.HeartBeat: - return new HeartBeatHandler(_client, new Contract.Request.HeartBeatRequest(req)); - case RequestType.Challenge: - return new ChallengeHandler(_client, new Contract.Request.ChallengeRequest(req)); - case RequestType.AvaliableCheck: - return new AvailableHandler(_client, new Contract.Request.AvaliableRequest(req)); - case RequestType.ClientMessageAck: - return new ClientMessageAckHandler(_client, new Contract.Request.ClientMessageAckRequest(req)); - case RequestType.Echo: - return new EchoHandler(_client, new Contract.Request.EchoRequest(req)); - case RequestType.KeepAlive: - return new KeepAliveHandler(_client, new Contract.Request.KeepAliveRequest(req)); - default: - return null; - } - } - } -} diff --git a/src/Servers/QueryReport/test/UniSpy.Server.QueryReport.Test.csproj b/src/Servers/QueryReport/test/UniSpy.Server.QueryReport.Test.csproj deleted file mode 100644 index 2d8b5e942..000000000 --- a/src/Servers/QueryReport/test/UniSpy.Server.QueryReport.Test.csproj +++ /dev/null @@ -1,31 +0,0 @@ - - - - net6.0 - false - ..\..\..\..\common\Icon\UniSpy_Logo.ico - - - AnyCPU - ..\..\..\..\build\$(Configuration) - - - ..\..\..\..\build\$(Configuration) - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - \ No newline at end of file diff --git a/src/Servers/QueryReport/test/V2/GameTest.cs b/src/Servers/QueryReport/test/V2/GameTest.cs deleted file mode 100644 index 727ad7cc2..000000000 --- a/src/Servers/QueryReport/test/V2/GameTest.cs +++ /dev/null @@ -1,115 +0,0 @@ -using UniSpy.Server.Core.Abstraction.Interface; -using Xunit; - -namespace UniSpy.Server.QueryReport.V2.Test -{ - public class GameTest - { - IClient _client; - public GameTest() - { - _client = MockObject.Client; - } - [Fact] - public void FaltOut2() - { - var raw = new byte[]{0x03,0xc2,0x94,0x1c,0xe7,0x6c,0x6f,0x63,0x61,0x6c,0x69,0x70,0x30,0x00,0x31,0x39 - ,0x32,0x2e,0x31,0x36,0x38,0x2e,0x30,0x2e,0x35,0x30,0x00,0x6c,0x6f,0x63,0x61,0x6c - ,0x69,0x70,0x31,0x00,0x31,0x37,0x32,0x2e,0x31,0x36,0x2e,0x37,0x34,0x2e,0x31,0x00 - ,0x6c,0x6f,0x63,0x61,0x6c,0x69,0x70,0x32,0x00,0x31,0x37,0x32,0x2e,0x31,0x37,0x2e - ,0x30,0x2e,0x31,0x00,0x6c,0x6f,0x63,0x61,0x6c,0x69,0x70,0x33,0x00,0x31,0x39,0x32 - ,0x2e,0x31,0x36,0x38,0x2e,0x31,0x32,0x32,0x2e,0x31,0x00,0x6c,0x6f,0x63,0x61,0x6c - ,0x69,0x70,0x34,0x00,0x31,0x37,0x32,0x2e,0x31,0x36,0x2e,0x36,0x35,0x2e,0x31,0x00 - ,0x6c,0x6f,0x63,0x61,0x6c,0x70,0x6f,0x72,0x74,0x00,0x32,0x33,0x37,0x35,0x36,0x00 - ,0x6e,0x61,0x74,0x6e,0x65,0x67,0x00,0x31,0x00,0x73,0x74,0x61,0x74,0x65,0x63,0x68 - ,0x61,0x6e,0x67,0x65,0x64,0x00,0x31,0x00,0x67,0x61,0x6d,0x65,0x6e,0x61,0x6d,0x65 - ,0x00,0x66,0x6c,0x61,0x74,0x6f,0x75,0x74,0x32,0x70,0x63,0x00,0x70,0x75,0x62,0x6c - ,0x69,0x63,0x69,0x70,0x00,0x30,0x00,0x70,0x75,0x62,0x6c,0x69,0x63,0x70,0x6f,0x72 - ,0x74,0x00,0x30,0x00,0x68,0x6f,0x73,0x74,0x6b,0x65,0x79,0x00,0x2d,0x38,0x32,0x30 - ,0x39,0x36,0x36,0x33,0x32,0x32,0x00,0x68,0x6f,0x73,0x74,0x6e,0x61,0x6d,0x65,0x00 - ,0x53,0x70,0x6f,0x72,0x65,0x00,0x67,0x61,0x6d,0x65,0x76,0x65,0x72,0x00,0x46,0x4f - ,0x31,0x34,0x00,0x67,0x61,0x6d,0x65,0x74,0x79,0x70,0x65,0x00,0x72,0x61,0x63,0x65 - ,0x00,0x67,0x61,0x6d,0x65,0x76,0x61,0x72,0x69,0x61,0x6e,0x74,0x00,0x6e,0x6f,0x72 - ,0x6d,0x61,0x6c,0x5f,0x72,0x61,0x63,0x65,0x00,0x67,0x61,0x6d,0x65,0x6d,0x6f,0x64 - ,0x65,0x00,0x6f,0x70,0x65,0x6e,0x77,0x61,0x69,0x74,0x69,0x6e,0x67,0x00,0x6e,0x75 - ,0x6d,0x70,0x6c,0x61,0x79,0x65,0x72,0x73,0x00,0x31,0x00,0x6d,0x61,0x78,0x70,0x6c - ,0x61,0x79,0x65,0x72,0x73,0x00,0x38,0x00,0x6d,0x61,0x70,0x6e,0x61,0x6d,0x65,0x00 - ,0x54,0x69,0x6d,0x62,0x65,0x72,0x6c,0x61,0x6e,0x64,0x73,0x5f,0x31,0x00,0x74,0x69 - ,0x6d,0x65,0x6c,0x69,0x6d,0x69,0x74,0x00,0x30,0x00,0x70,0x61,0x73,0x73,0x77,0x6f - ,0x72,0x64,0x00,0x30,0x00,0x63,0x61,0x72,0x5f,0x74,0x79,0x70,0x65,0x00,0x30,0x00 - ,0x63,0x61,0x72,0x5f,0x63,0x6c,0x61,0x73,0x73,0x00,0x30,0x00,0x72,0x61,0x63,0x65 - ,0x73,0x5f,0x70,0x00,0x31,0x30,0x30,0x00,0x64,0x65,0x72,0x62,0x69,0x65,0x73,0x5f - ,0x70,0x00,0x30,0x00,0x73,0x74,0x75,0x6e,0x74,0x73,0x5f,0x70,0x00,0x30,0x00,0x6e - ,0x6f,0x72,0x6d,0x61,0x6c,0x5f,0x72,0x61,0x63,0x65,0x5f,0x70,0x00,0x31,0x30,0x30 - ,0x00,0x70,0x6f,0x6e,0x67,0x5f,0x72,0x61,0x63,0x65,0x5f,0x70,0x00,0x30,0x00,0x77 - ,0x72,0x65,0x63,0x6b,0x5f,0x64,0x65,0x72,0x62,0x79,0x5f,0x70,0x00,0x30,0x00,0x73 - ,0x75,0x72,0x76,0x69,0x76,0x6f,0x72,0x5f,0x64,0x65,0x72,0x62,0x79,0x5f,0x70,0x00 - ,0x30,0x00,0x66,0x72,0x61,0x67,0x5f,0x64,0x65,0x72,0x62,0x79,0x5f,0x70,0x00,0x30 - ,0x00,0x74,0x61,0x67,0x5f,0x70,0x00,0x30,0x00,0x75,0x70,0x67,0x72,0x61,0x64,0x65 - ,0x73,0x00,0x32,0x00,0x6e,0x69,0x74,0x72,0x6f,0x5f,0x72,0x65,0x67,0x65,0x6e,0x65 - ,0x72,0x61,0x74,0x69,0x6f,0x6e,0x00,0x32,0x00,0x64,0x61,0x6d,0x61,0x67,0x65,0x5f - ,0x6c,0x65,0x76,0x65,0x6c,0x00,0x32,0x00,0x64,0x65,0x72,0x62,0x79,0x5f,0x64,0x61 - ,0x6d,0x61,0x67,0x65,0x5f,0x6c,0x65,0x76,0x65,0x6c,0x00,0x31,0x00,0x6e,0x65,0x78 - ,0x74,0x5f,0x72,0x61,0x63,0x65,0x5f,0x74,0x79,0x70,0x65,0x00,0x6e,0x6f,0x72,0x6d - ,0x61,0x6c,0x5f,0x72,0x61,0x63,0x65,0x00,0x6c,0x61,0x70,0x73,0x5f,0x6f,0x72,0x5f - ,0x74,0x69,0x6d,0x65,0x6c,0x69,0x6d,0x69,0x74,0x00,0x34,0x00,0x6e,0x75,0x6d,0x5f - ,0x72,0x61,0x63,0x65,0x73,0x00,0x31,0x00,0x6e,0x75,0x6d,0x5f,0x64,0x65,0x72,0x62 - ,0x69,0x65,0x73,0x00,0x30,0x00,0x6e,0x75,0x6d,0x5f,0x73,0x74,0x75,0x6e,0x74,0x73 - ,0x00,0x30,0x00,0x64,0x61,0x74,0x61,0x63,0x68,0x65,0x63,0x6b,0x73,0x75,0x6d,0x00 - ,0x33,0x35,0x34,0x36,0x64,0x35,0x38,0x30,0x39,0x33,0x32,0x33,0x37,0x65,0x62,0x33 - ,0x33,0x62,0x32,0x61,0x39,0x36,0x62,0x62,0x38,0x31,0x33,0x33,0x37,0x30,0x64,0x38 - ,0x34,0x36,0x66,0x66,0x63,0x65,0x63,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - ((ITestClient)_client).TestReceived(raw); - } - [Fact] - public void Worms3d() - { - var raw = new byte[] { - 0x03,0x51,0x5d,0xa0 - ,0xe8,0x6c,0x6f,0x63,0x61,0x6c,0x69,0x70,0x30,0x00,0x31,0x39,0x32,0x2e,0x31,0x36 - ,0x38,0x2e,0x30,0x2e,0x36,0x30,0x00,0x6c,0x6f,0x63,0x61,0x6c,0x70,0x6f,0x72,0x74 - ,0x00,0x36,0x35,0x30,0x30,0x00,0x6e,0x61,0x74,0x6e,0x65,0x67,0x00,0x31,0x00,0x73 - ,0x74,0x61,0x74,0x65,0x63,0x68,0x61,0x6e,0x67,0x65,0x64,0x00,0x33,0x00,0x67,0x61 - ,0x6d,0x65,0x6e,0x61,0x6d,0x65,0x00,0x77,0x6f,0x72,0x6d,0x73,0x33,0x00,0x68,0x6f - ,0x73,0x74,0x6e,0x61,0x6d,0x65,0x00,0x74,0x65,0x73,0x74,0x00,0x67,0x61,0x6d,0x65 - ,0x6d,0x6f,0x64,0x65,0x00,0x6f,0x70,0x65,0x6e,0x73,0x74,0x61,0x67,0x69,0x6e,0x67 - ,0x00,0x67,0x72,0x6f,0x75,0x70,0x69,0x64,0x00,0x36,0x32,0x32,0x00,0x6e,0x75,0x6d - ,0x70,0x6c,0x61,0x79,0x65,0x72,0x73,0x00,0x31,0x00,0x6d,0x61,0x78,0x70,0x6c,0x61 - ,0x79,0x65,0x72,0x73,0x00,0x32,0x00,0x68,0x6f,0x73,0x74,0x6e,0x61,0x6d,0x65,0x00 - ,0x74,0x65,0x73,0x74,0x00,0x68,0x6f,0x73,0x74,0x70,0x6f,0x72,0x74,0x00,0x00,0x6d - ,0x61,0x78,0x70,0x6c,0x61,0x79,0x65,0x72,0x73,0x00,0x32,0x00,0x6e,0x75,0x6d,0x70 - ,0x6c,0x61,0x79,0x65,0x72,0x73,0x00,0x31,0x00,0x53,0x63,0x68,0x65,0x6d,0x65,0x43 - ,0x68,0x61,0x6e,0x67,0x69,0x6e,0x67,0x00,0x30,0x00,0x67,0x61,0x6d,0x65,0x76,0x65 - ,0x72,0x00,0x31,0x30,0x37,0x33,0x00,0x67,0x61,0x6d,0x65,0x74,0x79,0x70,0x65,0x00 - ,0x00,0x6d,0x61,0x70,0x6e,0x61,0x6d,0x65,0x00,0x00,0x66,0x69,0x72,0x65,0x77,0x61 - ,0x6c,0x6c,0x00,0x30,0x00,0x70,0x75,0x62,0x6c,0x69,0x63,0x69,0x70,0x00,0x32,0x35 - ,0x35,0x2e,0x32,0x35,0x35,0x2e,0x32,0x35,0x35,0x2e,0x32,0x35,0x35,0x00,0x70,0x72 - ,0x69,0x76,0x61,0x74,0x65,0x69,0x70,0x00,0x31,0x39,0x32,0x2e,0x31,0x36,0x38,0x2e - ,0x30,0x2e,0x36,0x30,0x00,0x67,0x61,0x6d,0x65,0x6d,0x6f,0x64,0x65,0x00,0x6f,0x70 - ,0x65,0x6e,0x73,0x74,0x61,0x67,0x69,0x6e,0x67,0x00,0x76,0x61,0x6c,0x00,0x30,0x00 - ,0x70,0x61,0x73,0x73,0x77,0x6f,0x72,0x64,0x00,0x30,0x00,0x00,0x00,0x01,0x70,0x6c - ,0x61,0x79,0x65,0x72,0x5f,0x00,0x70,0x69,0x6e,0x67,0x5f,0x00,0x68,0x6f,0x73,0x74 - ,0x6e,0x61,0x6d,0x65,0x00,0x68,0x6f,0x73,0x74,0x70,0x6f,0x72,0x74,0x00,0x6d,0x61 - ,0x78,0x70,0x6c,0x61,0x79,0x65,0x72,0x73,0x00,0x6e,0x75,0x6d,0x70,0x6c,0x61,0x79 - ,0x65,0x72,0x73,0x00,0x53,0x63,0x68,0x65,0x6d,0x65,0x43,0x68,0x61,0x6e,0x67,0x69 - ,0x6e,0x67,0x00,0x67,0x61,0x6d,0x65,0x76,0x65,0x72,0x00,0x67,0x61,0x6d,0x65,0x74 - ,0x79,0x70,0x65,0x00,0x6d,0x61,0x70,0x6e,0x61,0x6d,0x65,0x00,0x66,0x69,0x72,0x65 - ,0x77,0x61,0x6c,0x6c,0x00,0x70,0x75,0x62,0x6c,0x69,0x63,0x69,0x70,0x00,0x70,0x72 - ,0x69,0x76,0x61,0x74,0x65,0x69,0x70,0x00,0x67,0x61,0x6d,0x65,0x6d,0x6f,0x64,0x65 - ,0x00,0x76,0x61,0x6c,0x00,0x70,0x61,0x73,0x73,0x77,0x6f,0x72,0x64,0x00,0x00,0x77 - ,0x6f,0x72,0x6d,0x73,0x31,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x30 - ,0x37,0x33,0x00,0x00,0x00,0x31,0x00,0x32,0x35,0x35,0x2e,0x32,0x35,0x35,0x2e,0x32 - ,0x35,0x35,0x2e,0x32,0x35,0x35,0x00,0x31,0x39,0x32,0x2e,0x31,0x36,0x38,0x2e,0x30 - ,0x2e,0x36,0x30,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x68,0x6f,0x73,0x74,0x6e,0x61 - ,0x6d,0x65,0x00,0x68,0x6f,0x73,0x74,0x70,0x6f,0x72,0x74,0x00,0x6d,0x61,0x78,0x70 - ,0x6c,0x61,0x79,0x65,0x72,0x73,0x00,0x6e,0x75,0x6d,0x70,0x6c,0x61,0x79,0x65,0x72 - ,0x73,0x00,0x53,0x63,0x68,0x65,0x6d,0x65,0x43,0x68,0x61,0x6e,0x67,0x69,0x6e,0x67 - ,0x00,0x67,0x61,0x6d,0x65,0x76,0x65,0x72,0x00,0x67,0x61,0x6d,0x65,0x74,0x79,0x70 - ,0x65,0x00,0x6d,0x61,0x70,0x6e,0x61,0x6d,0x65,0x00,0x66,0x69,0x72,0x65,0x77,0x61 - ,0x6c,0x6c,0x00,0x70,0x75,0x62,0x6c,0x69,0x63,0x69,0x70,0x00,0x70,0x72,0x69,0x76 - ,0x61,0x74,0x65,0x69,0x70,0x00,0x67,0x61,0x6d,0x65,0x6d,0x6f,0x64,0x65,0x00,0x76 - ,0x61,0x6c,0x00,0x70,0x61,0x73,0x73,0x77,0x6f,0x72,0x64,0x00,0x00 }; - ((ITestClient)_client).TestReceived(raw); - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/test/V2/MockObject.cs b/src/Servers/QueryReport/test/V2/MockObject.cs deleted file mode 100644 index 942c3608f..000000000 --- a/src/Servers/QueryReport/test/V2/MockObject.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Net; -using Moq; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.QueryReport.Application; - -namespace UniSpy.Server.QueryReport.V2.Test -{ - public class MockObject - { - public static IClient Client = CreateClient(); - - public static Client CreateClient(string ipAddress = "192.168.1.1", int port = 9999) - { - var managerMock = new Mock(); - var connectionMock = new Mock(); - connectionMock.Setup(s => s.RemoteIPEndPoint).Returns(new IPEndPoint(IPAddress.Parse(ipAddress), port)); - connectionMock.Setup(s => s.Manager).Returns(managerMock.Object); - connectionMock.Setup(s => s.ConnectionType).Returns(NetworkConnectionType.Udp); - var serverMock = new QueryReport.Application.Server(managerMock.Object); - - return new Client(connectionMock.Object, serverMock); - } - } -} \ No newline at end of file diff --git a/src/Servers/QueryReport/test/V2/RequestTest.cs b/src/Servers/QueryReport/test/V2/RequestTest.cs deleted file mode 100644 index e0a31d556..000000000 --- a/src/Servers/QueryReport/test/V2/RequestTest.cs +++ /dev/null @@ -1,77 +0,0 @@ -using UniSpy.Server.QueryReport.V2.Enumerate; -using UniSpy.Server.QueryReport.V2.Contract.Request; -using Xunit; -namespace UniSpy.Server.QueryReport.V2.Test -{ - public class RequestTest - { - [Fact] - public void AvaliableTest() - { - var rawRequest = new byte[]{ - 0x09,//packet type - 0x00,0x00,0x00,0x00,//instant key - 0x09, 0x00, 0x00, 0x00, 0x00,//prefix - 0x67, 0x61, 0x6D, 0x65 ,0x73, 0x70, 0x79,//gamename - 0x00 - }; - var request = new AvaliableRequest(rawRequest); - request.Parse(); - Assert.Equal(RequestType.AvaliableCheck, request.CommandName); - Assert.Equal((uint)0, request.InstantKey); - } - [Fact] - public void ChallengeTest() - { - var rawRequest = new byte[]{ - 0x01,//packet type - 0x00,0x00,0x00,0x00,//instant key - 0x67, 0x61, 0x6D, 0x65 ,0x73, 0x70, 0x79,//gamename - 0x00 - }; - var request = new ChallengeRequest(rawRequest); - request.Parse(); - Assert.Equal(RequestType.Challenge, request.CommandName); - Assert.Equal((uint)0, request.InstantKey); - } - [Fact] - public void EchoRequest() - { - var rawRequest = new byte[]{ - 0x02,//packet type - 0x00,0x00,0x00,0x00,//instant key - 0x67, 0x61, 0x6D, 0x65 ,0x73, 0x70, 0x79,//gamename - 0x00 - }; - var request = new EchoRequest(rawRequest); - request.Parse(); - Assert.Equal(RequestType.Echo, request.CommandName); - Assert.Equal((uint)0, request.InstantKey); - } - [Fact] - public void HeartBeatTest() - { - var rawRequest = new byte[] { 0x03, 0xae, 0x1f, 0x77, 0x64, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x70, 0x30, 0x00, 0x31, 0x39, 0x32, 0x2e, 0x31, 0x36, 0x38, 0x2e, 0x30, 0x2e, 0x31, 0x30, 0x39, 0x00, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x70, 0x6f, 0x72, 0x74, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x00, 0x6e, 0x61, 0x74, 0x6e, 0x65, 0x67, 0x00, 0x31, 0x00, 0x73, 0x74, 0x61, 0x74, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x00, 0x33, 0x00, 0x67, 0x61, 0x6d, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x67, 0x6d, 0x74, 0x65, 0x73, 0x74, 0x00, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x47, 0x61, 0x6d, 0x65, 0x53, 0x70, 0x79, 0x20, 0x51, 0x52, 0x32, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x00, 0x67, 0x61, 0x6d, 0x65, 0x76, 0x65, 0x72, 0x00, 0x32, 0x2e, 0x30, 0x30, 0x00, 0x68, 0x6f, 0x73, 0x74, 0x70, 0x6f, 0x72, 0x74, 0x00, 0x32, 0x35, 0x30, 0x30, 0x30, 0x00, 0x6d, 0x61, 0x70, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x67, 0x6d, 0x74, 0x6d, 0x61, 0x70, 0x31, 0x00, 0x67, 0x61, 0x6d, 0x65, 0x74, 0x79, 0x70, 0x65, 0x00, 0x61, 0x72, 0x65, 0x6e, 0x61, 0x00, 0x6e, 0x75, 0x6d, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x00, 0x36, 0x00, 0x6e, 0x75, 0x6d, 0x74, 0x65, 0x61, 0x6d, 0x73, 0x00, 0x32, 0x00, 0x6d, 0x61, 0x78, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x00, 0x33, 0x32, 0x00, 0x67, 0x61, 0x6d, 0x65, 0x6d, 0x6f, 0x64, 0x65, 0x00, 0x6f, 0x70, 0x65, 0x6e, 0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x00, 0x74, 0x65, 0x61, 0x6d, 0x70, 0x6c, 0x61, 0x79, 0x00, 0x31, 0x00, 0x66, 0x72, 0x61, 0x67, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x00, 0x30, 0x00, 0x74, 0x69, 0x6d, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x00, 0x34, 0x30, 0x00, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x79, 0x00, 0x38, 0x30, 0x30, 0x00, 0x72, 0x61, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x6f, 0x6e, 0x00, 0x31, 0x00, 0x00, 0x00, 0x06, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x00, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x00, 0x64, 0x65, 0x61, 0x74, 0x68, 0x73, 0x5f, 0x00, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x00, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x00, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x00, 0x00, 0x4a, 0x6f, 0x65, 0x20, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x00, 0x32, 0x37, 0x00, 0x36, 0x00, 0x31, 0x32, 0x33, 0x00, 0x31, 0x00, 0x34, 0x30, 0x39, 0x00, 0x4c, 0x33, 0x33, 0x74, 0x20, 0x30, 0x6e, 0x33, 0x00, 0x36, 0x00, 0x32, 0x33, 0x00, 0x32, 0x37, 0x37, 0x00, 0x30, 0x00, 0x36, 0x37, 0x33, 0x00, 0x52, 0x61, 0x70, 0x74, 0x6f, 0x72, 0x00, 0x33, 0x30, 0x00, 0x31, 0x00, 0x31, 0x34, 0x36, 0x00, 0x31, 0x00, 0x37, 0x30, 0x31, 0x00, 0x47, 0x72, 0x38, 0x31, 0x00, 0x32, 0x31, 0x00, 0x31, 0x36, 0x00, 0x31, 0x32, 0x35, 0x00, 0x31, 0x00, 0x35, 0x38, 0x32, 0x00, 0x46, 0x6c, 0x75, 0x62, 0x62, 0x65, 0x72, 0x00, 0x33, 0x00, 0x32, 0x31, 0x00, 0x31, 0x31, 0x30, 0x00, 0x30, 0x00, 0x32, 0x39, 0x38, 0x00, 0x53, 0x61, 0x72, 0x67, 0x65, 0x00, 0x33, 0x00, 0x32, 0x38, 0x00, 0x31, 0x32, 0x35, 0x00, 0x31, 0x00, 0x35, 0x39, 0x30, 0x00, 0x00, 0x02, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x74, 0x00, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x74, 0x00, 0x61, 0x76, 0x67, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x00, 0x00, 0x52, 0x65, 0x64, 0x00, 0x32, 0x39, 0x34, 0x00, 0x33, 0x37, 0x39, 0x00, 0x42, 0x6c, 0x75, 0x65, 0x00, 0x38, 0x39, 0x00, 0x33, 0x38, 0x33, 0x00 }; - var request = new HeartBeatRequest(rawRequest); - request.Parse(); - Assert.Equal("gmtest", request.GameName); - Assert.Equal((uint)1685528494, request.InstantKey); - Assert.Equal(6, request.PlayerData.Count); - Assert.Equal(19, request.ServerData.Count); - Assert.Equal(2, request.TeamData.Count); - // Assert.Equal(HeartBeatReportType.ServerTeamPlayerData, request.ReportType); - } - [Fact] - public void KeepAliveTest() - { - var rawRequest = new byte[]{ - 0x08,//packet type - 0x00,0x00,0x00,0x00,//instant key - }; - var request = new EchoRequest(rawRequest); - request.Parse(); - Assert.Equal(RequestType.KeepAlive, request.CommandName); - Assert.Equal((uint)0, request.InstantKey); - } - } -} diff --git a/src/Servers/ServerBrowser/src/Aggregate/GameServerFilter.cs b/src/Servers/ServerBrowser/src/Aggregate/GameServerFilter.cs deleted file mode 100644 index 433eab087..000000000 --- a/src/Servers/ServerBrowser/src/Aggregate/GameServerFilter.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace UniSpy.Server.ServerBrowser.Aggregate -{ - public class GameServerFilter - { - // public static Process(List<>) - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/Application/Program.cs b/src/Servers/ServerBrowser/src/Application/Program.cs deleted file mode 100755 index 88ddc0a8b..000000000 --- a/src/Servers/ServerBrowser/src/Application/Program.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using UniSpy.Server.Core.Logging; - -namespace UniSpy.Server.ServerBrowser.Application -{ - public sealed class Program - { - static void Main(string[] args) - { - try - { - new ServerLauncher().Start(); - Console.WriteLine("Press < Q > to exit. "); - while (Console.ReadKey().Key != ConsoleKey.Q) { } - } - catch (System.Exception e) - { - LogWriter.LogError(e); - } - - } - } -} diff --git a/src/Servers/ServerBrowser/src/Application/ServerLauncher.cs b/src/Servers/ServerBrowser/src/Application/ServerLauncher.cs deleted file mode 100644 index 48913b483..000000000 --- a/src/Servers/ServerBrowser/src/Application/ServerLauncher.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Core.Abstraction.BaseClass.Factory; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.ServerBrowser.Application -{ - public sealed class ServerLauncher : ServerLauncherBase - { - public static IServer ServerV1 => ServerInstances[0]; - public static IServer ServerV2 => ServerInstances[1]; - protected override List LaunchNetworkService() => - new List - { - new ServerBrowser.V1.Application.Server(), - new ServerBrowser.V2.Application.Server() - }; - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/Dockerfile b/src/Servers/ServerBrowser/src/Dockerfile deleted file mode 100755 index 5bd89b150..000000000 --- a/src/Servers/ServerBrowser/src/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base -WORKDIR /app -EXPOSE 28910 -EXPOSE 28900 - -FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build -WORKDIR /src -COPY ["src/Servers/ServerBrowser/src/UniSpy.Server.ServerBrowser.csproj", "src/Servers/ServerBrowser/src/"] -COPY ["src/Servers/NatNegotiation/src/UniSpy.Server.NatNegotiation.csproj", "src/Servers/NatNegotiation/src/"] -COPY ["src/Libraries/Core/src/UniSpy.Server.Core.csproj", "src/Libraries/Core/src/"] -COPY ["src/Servers/QueryReport/src/UniSpy.Server.QueryReport.csproj", "src/Servers/QueryReport/src/"] -RUN dotnet restore "src/Servers/ServerBrowser/src/UniSpy.Server.ServerBrowser.csproj" -COPY . . -WORKDIR "/src/src/Servers/ServerBrowser/src" -RUN dotnet build "UniSpy.Server.ServerBrowser.csproj" -c Release -o /app/build - -FROM build AS publish -RUN dotnet publish "UniSpy.Server.ServerBrowser.csproj" -c Release -o /app/publish - -FROM base AS final -WORKDIR /app -COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "UniSpy.Server.ServerBrowser.dll"] \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/Exception/Exception.cs b/src/Servers/ServerBrowser/src/Exception/Exception.cs deleted file mode 100755 index 464e5ec8a..000000000 --- a/src/Servers/ServerBrowser/src/Exception/Exception.cs +++ /dev/null @@ -1,26 +0,0 @@ -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.ServerBrowser -{ - public class Exception : UniSpy.Exception, IResponse - { - public Exception() - { - } - - public Exception(string message) : base(message) - { - } - - public Exception(string message, System.Exception innerException) : base(message, innerException) - { - } - - public object SendingBuffer { get; private set; } - - public void Build() - { - SendingBuffer = @$"\error\{Message}\final\"; - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/UniSpy.Server.ServerBrowser.csproj b/src/Servers/ServerBrowser/src/UniSpy.Server.ServerBrowser.csproj deleted file mode 100755 index e6dfd4a58..000000000 --- a/src/Servers/ServerBrowser/src/UniSpy.Server.ServerBrowser.csproj +++ /dev/null @@ -1,24 +0,0 @@ - - - - Exe - net6.0 - ..\..\..\..\common\Icon\UniSpy_Logo.ico - Linux - ..\..\..\.. - - - ..\..\..\..\build\$(Configuration) - - - ..\..\..\..\build\$(Configuration) - - - - - - - - - - \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V1/Abstraction/BaseClass/CmdHandlerBase.cs b/src/Servers/ServerBrowser/src/V1/Abstraction/BaseClass/CmdHandlerBase.cs deleted file mode 100644 index fc5a8bffc..000000000 --- a/src/Servers/ServerBrowser/src/V1/Abstraction/BaseClass/CmdHandlerBase.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.ServerBrowser.V1.Application; - -namespace UniSpy.Server.ServerBrowser.V1.Abstraction.BaseClass -{ - public abstract class CmdHandlerBase : UniSpy.Server.Core.Abstraction.BaseClass.CmdHandlerBase - { - protected new Client _client => (Client)base._client; - public CmdHandlerBase(Client client, RequestBase request) : base(client, request) - { - } - protected override void HandleException(System.Exception ex) - { - base.HandleException(ex); - if (ex is ServerBrowser.Exception) - { - _client.Send((ServerBrowser.Exception)ex); - } - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V1/Abstraction/BaseClass/EnctypeBase.cs b/src/Servers/ServerBrowser/src/V1/Abstraction/BaseClass/EnctypeBase.cs deleted file mode 100644 index 6b22bb7e0..000000000 --- a/src/Servers/ServerBrowser/src/V1/Abstraction/BaseClass/EnctypeBase.cs +++ /dev/null @@ -1,102 +0,0 @@ -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.ServerBrowser.V1.Abstraction.BaseClass -{ - public abstract class EnctypeBase : ICryptography - { - public byte[] Decrypt(byte[] data) => throw new UniSpy.Exception("Enctype only encrypt message on server side."); - public abstract byte[] Encrypt(byte[] data); - protected void EncShare3(byte[] data, byte n1 = 0, byte n2 = 0) - { - byte t1, t2, t3, t4; - int i; - t2 = n1; - t1 = 0; - t4 = 1; - data[304] = 0; - - for (i = 32768; i != 0; i >>= 1) - { - t2 += t4; - t1 += t2; - t2 += t1; - - if ((n2 & i) != 0) - { - t2 = (byte)~t2; - t4 = (byte)((t4 << 1) + 1); - t3 = (byte)((t2 << 24) | (t2 >> 8)); - t3 ^= data[t3 & 0xff]; - t1 ^= data[t1 & 0xff]; - t2 = (byte)((t3 << 24) | (t3 >> 8)); - t3 = (byte)((t1 >> 24) | (t1 << 8)); - t2 ^= data[t2 & 0xff]; - t3 ^= data[t3 & 0xff]; - t1 = (byte)((t3 >> 24) | (t3 << 8)); - } - else - { - data[data[304] + 256] = t2; - data[data[304] + 272] = t1; - data[data[304] + 288] = t4; - data[304]++; - t3 = (byte)((t1 << 24) | (t1 >> 8)); - t2 ^= data[t2 & 0xff]; - t3 ^= data[t3 & 0xff]; - t1 = (byte)((t3 << 24) | (t3 >> 8)); - t3 = (byte)((t2 >> 24) | (t2 << 8)); - t3 ^= data[t3 & 0xff]; - t1 ^= data[t1 & 0xff]; - t2 = (byte)((t3 >> 24) | (t3 << 8)); - t4 <<= 1; - } - } - data[305] = t2; - data[306] = t1; - data[307] = t4; - data[308] = n1; - } - protected byte[] EncShare4(byte[] data) - { - byte[] encodeData = new byte[326]; - byte tmp; - byte i; - byte pos, x, y; - // encrypted data size - int size = data[0]; - - for (y = 0; y < 4; y++) - { - for (i = 0; i <= 255; i++) - { - encodeData[i] = (byte)((encodeData[i] << 8) + i); - // fill 256 bytes of encodeData with 0,1,2,3...255 - // Array.Copy(Enumerable.Range(0,255).ToArray(),encodeData,256); - } - - for (pos = y, x = 0; x < 2; x++) - { - for (i = 0; i <= 255; i++) - { - tmp = encodeData[i]; - pos += (byte)(tmp + data[i % size]); - encodeData[i] = encodeData[pos]; - encodeData[pos] = tmp; - } - } - } - - for (i = 0; i <= 255; i++) - { - encodeData[i] ^= i; - } - - EncShare3(encodeData); - return encodeData; - } - protected void EncShare2(byte[] buffer, byte[] bufferp) - { - - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V1/Abstraction/BaseClass/RequestBase.cs b/src/Servers/ServerBrowser/src/V1/Abstraction/BaseClass/RequestBase.cs deleted file mode 100644 index d0fcd84c5..000000000 --- a/src/Servers/ServerBrowser/src/V1/Abstraction/BaseClass/RequestBase.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using UniSpy.Server.Core.Misc; - -namespace UniSpy.Server.ServerBrowser.V1.Abstraction.BaseClass -{ - public abstract class RequestBase : UniSpy.Server.Core.Abstraction.BaseClass.RequestBase - { - public new string RawRequest { get => (string)base.RawRequest; protected set => base.RawRequest = value; } - public new string CommandName { get => (string)base.CommandName; protected set => base.CommandName = value; } - public Dictionary KeyValues { get; private set; } - public string GameName { get; private set; } - public RequestBase(string rawRequest) : base(rawRequest) - { - } - public override void Parse() - { - KeyValues = GameSpyUtils.ConvertToKeyValue(RawRequest); - CommandName = KeyValues.Keys.First(); - if (!KeyValues.ContainsKey("gamename")) - { - throw new ServerBrowser.Exception("No game name present in request."); - } - GameName = KeyValues["gamename"]; - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V1/Abstraction/BaseClass/ResponseBase.cs b/src/Servers/ServerBrowser/src/V1/Abstraction/BaseClass/ResponseBase.cs deleted file mode 100644 index 5a5cf3b37..000000000 --- a/src/Servers/ServerBrowser/src/V1/Abstraction/BaseClass/ResponseBase.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace UniSpy.Server.ServerBrowser.V1.Abstraction.BaseClass -{ - public abstract class ResponseBase : UniSpy.Server.Core.Abstraction.BaseClass.ResponseBase - { - public new string SendingBuffer { get => (string)base.SendingBuffer; protected set => base.SendingBuffer = value; } - public ResponseBase(RequestBase request, ResultBase result) : base(request, result) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V1/Abstraction/BaseClass/ResultBase.cs b/src/Servers/ServerBrowser/src/V1/Abstraction/BaseClass/ResultBase.cs deleted file mode 100644 index 1b551651c..000000000 --- a/src/Servers/ServerBrowser/src/V1/Abstraction/BaseClass/ResultBase.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace UniSpy.Server.ServerBrowser.V1.Abstraction.BaseClass -{ - public abstract class ResultBase : UniSpy.Server.Core.Abstraction.BaseClass.ResultBase - { - public ResultBase() - { - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V1/Abstraction/Interface/IStorageOperation.cs b/src/Servers/ServerBrowser/src/V1/Abstraction/Interface/IStorageOperation.cs deleted file mode 100644 index c1e2b2b03..000000000 --- a/src/Servers/ServerBrowser/src/V1/Abstraction/Interface/IStorageOperation.cs +++ /dev/null @@ -1,13 +0,0 @@ -// using System.Net; -// using UniSpy.Server.ServerBrowser.V1.Aggregation.Redis; - -// namespace UniSpy.Server.ServerBrowser.V1.Abstraction.Interface -// { -// public interface IStorageOperation -// { -// string GetGameSecretKey(string gameName); -// GameServerInfo GetServerInfo(IPEndPoint endPoint); -// void UpdateServerInfo(GameServerInfo info); -// void RemoveServerInfo(IPEndPoint endPoint); -// } -// } \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V1/Aggregate/Enctype1.cs b/src/Servers/ServerBrowser/src/V1/Aggregate/Enctype1.cs deleted file mode 100644 index 503bc919a..000000000 --- a/src/Servers/ServerBrowser/src/V1/Aggregate/Enctype1.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using UniSpy.Server.ServerBrowser.V1.Abstraction.BaseClass; - -namespace UniSpy.Server.ServerBrowser.V1.Aggregate -{ - public class Enctype1 : EnctypeBase - { - /// - /// The server key - /// 256 bytes - /// - public static readonly byte[] ServerKey = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - /// - /// Client key - /// 16 bytes - /// - public static readonly byte[] ClientKey = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - public byte[] Key { get; private set; } - public Enctype1(byte[] key) - { - Key = key; - } - - - public override byte[] Encrypt(byte[] data) - { - byte[] lengthBytes = BitConverter.GetBytes(data.Length); - - throw new System.NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V1/Aggregate/Enctype2.cs b/src/Servers/ServerBrowser/src/V1/Aggregate/Enctype2.cs deleted file mode 100644 index 1680dc5c5..000000000 --- a/src/Servers/ServerBrowser/src/V1/Aggregate/Enctype2.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Core.Encryption; -using UniSpy.Server.ServerBrowser.V1.Abstraction.BaseClass; - -namespace UniSpy.Server.ServerBrowser.V1.Aggregate -{ - - public class Enctype2 : EnctypeBase - { - public const int HeaderSize = 8; - public byte[] GameSecreteKey { get; private set; } - public Enctype2(string gameSecretKey) - { - GameSecreteKey = UniSpyEncoding.GetBytes(gameSecretKey); - } - - public override byte[] Encrypt(byte[] data) - { - var encData = new byte[326]; - var buffer = new List(); - // add 8 bytes header - buffer.AddRange(new byte[8] { 0, 0, 0, 0, 0, 0, 0, 0 }); - // add 1 byte empty data - buffer.Add(0); - // add data after - buffer.AddRange(data); - - KeyXor(encData); - // at last - data[0] ^= 0xec; - throw new System.NotImplementedException(); - } - - private void KeyXor(byte[] data) - { - for (int i = 0; i < GameSecreteKey.Length; i++) - { - data[i] ^= GameSecreteKey[i]; - } - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V1/Application/Client.cs b/src/Servers/ServerBrowser/src/V1/Application/Client.cs deleted file mode 100644 index c2b3ba072..000000000 --- a/src/Servers/ServerBrowser/src/V1/Application/Client.cs +++ /dev/null @@ -1,25 +0,0 @@ -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Encryption; -using UniSpy.Server.Core.Logging; -using UniSpy.Server.ServerBrowser.V1.Handler; - -namespace UniSpy.Server.ServerBrowser.V1.Application -{ - public sealed class Client : ClientBase - { - public new ClientInfo Info { get => (ClientInfo)base.Info; private set => base.Info = value; } - public Client(IConnection connection, IServer server) : base(connection, server) - { - Info = new ClientInfo(); - } - protected override void OnConnected() - { - this.LogNetworkSending(ClientInfo.ChallengeResponse); - Connection.Send(ClientInfo.ChallengeResponse); - base.OnConnected(); - } - - protected override ISwitcher CreateSwitcher(object buffer) => new CmdSwitcher(this, UniSpyEncoding.GetString((byte[])buffer)); - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V1/Application/ClientInfo.cs b/src/Servers/ServerBrowser/src/V1/Application/ClientInfo.cs deleted file mode 100644 index 417c42927..000000000 --- a/src/Servers/ServerBrowser/src/V1/Application/ClientInfo.cs +++ /dev/null @@ -1,14 +0,0 @@ -using UniSpy.Server.Core.Abstraction.BaseClass; - -namespace UniSpy.Server.ServerBrowser.V1.Application -{ - public sealed class ClientInfo : ClientInfoBase - { - public static string EncKey = @"000000"; - public static string ChallengeResponse = $@"\basic\\secure\{EncKey}\final\"; - public string GameSecretKey { get; set; } - public ClientInfo() - { - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V1/Application/Server.cs b/src/Servers/ServerBrowser/src/V1/Application/Server.cs deleted file mode 100644 index 26886b9a8..000000000 --- a/src/Servers/ServerBrowser/src/V1/Application/Server.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Net; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Network.Tcp.Server; - -namespace UniSpy.Server.ServerBrowser.V1.Application -{ - public sealed class Server : ServerBase - { - static Server() - { - _name = "ServerBrowserV1"; - } - public Server() { } - - public Server(IConnectionManager manager) : base(manager) { } - protected override IClient CreateClient(IConnection connection) => new Client(connection, this); - - - protected override IConnectionManager CreateConnectionManager(IPEndPoint endPoint) => new TcpConnectionManager(endPoint); - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V1/Contract/Request/GameNameRequest.cs b/src/Servers/ServerBrowser/src/V1/Contract/Request/GameNameRequest.cs deleted file mode 100644 index 2e0cd8d8f..000000000 --- a/src/Servers/ServerBrowser/src/V1/Contract/Request/GameNameRequest.cs +++ /dev/null @@ -1,53 +0,0 @@ -using UniSpy.Server.ServerBrowser.V1.Abstraction.BaseClass; - -namespace UniSpy.Server.ServerBrowser.V1.Contract.Request -{ - public enum EncryptionType - { - // do not encrypt - Plaintext, - // use encryption method 1 - Type1, - // use encryption method 2 - Type2 - } - /// - /// verify client - /// The request maybe \gamename\\gamever\\location\0\validate\\secure\\final\\queryid\1.1\" - /// - public sealed class GameNameRequest : RequestBase - { - public EncryptionType EncType { get; private set; } - public string Version { get; private set; } - public string EncKey { get; private set; } - public GameNameRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - if (KeyValues.ContainsKey("enctype")) - { - if (!System.Enum.TryParse(KeyValues["enctype"], out var type)) - { - throw new ServerBrowser.Exception("Encryption type format is not correct."); - } - EncType = type; - } - - if (!KeyValues.ContainsKey("gamever")) - { - throw new ServerBrowser.Exception("Game engine version is not presented in request."); - } - - Version = KeyValues["gamever"]; - //process secure - // star trek armada 2 do not use encryption - if (KeyValues.ContainsKey("secure")) - { - EncKey = KeyValues["secure"]; - } - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V1/Contract/Request/ListRequest.cs b/src/Servers/ServerBrowser/src/V1/Contract/Request/ListRequest.cs deleted file mode 100644 index a8c634e19..000000000 --- a/src/Servers/ServerBrowser/src/V1/Contract/Request/ListRequest.cs +++ /dev/null @@ -1,48 +0,0 @@ -using UniSpy.Server.ServerBrowser.V1.Abstraction.BaseClass; - -namespace UniSpy.Server.ServerBrowser.V1.Contract.Request -{ - public enum ListRequestType - { - Basic, - Info, - Group - } - /// - /// Query for game server list of specific game name with filter - /// - public sealed class ListRequest : RequestBase - { - public string Filter { get; private set; } - public bool IsSendingCompressFormat { get; private set; } - public bool IsSendAllInfo { get; private set; } - public ListRequestType? Type { get; private set; } - public ListRequest(string rawRequest) : base(rawRequest) - { - } - public override void Parse() - { - base.Parse(); - if (KeyValues.ContainsKey("where")) - { - Filter = KeyValues["where"]; - } - switch (KeyValues[CommandName]) - { - case "cmp": - IsSendingCompressFormat = true; - Type = ListRequestType.Basic; - break; - case "info2": - IsSendAllInfo = true; - Type = ListRequestType.Info; - break; - case "groups": - Type = ListRequestType.Group; - IsSendingCompressFormat = true; - IsSendAllInfo = true; - break; - } - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V1/Contract/Response/GameNameResponse.cs b/src/Servers/ServerBrowser/src/V1/Contract/Response/GameNameResponse.cs deleted file mode 100644 index c623696c8..000000000 --- a/src/Servers/ServerBrowser/src/V1/Contract/Response/GameNameResponse.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.ServerBrowser.V1.Abstraction.BaseClass; - -namespace UniSpy.Server.ServerBrowser.V1.Contract.Response -{ - public sealed class GameNameResponse : ResponseBase - { - /// - /// Crypt key is 14 char long string - /// - public static string CryptKey = "00000000000000"; - public GameNameResponse(RequestBase request, ResultBase result) : base(request, result) - { - } - - public override void Build() - { - throw new System.NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V1/Contract/Response/ListResponse.cs b/src/Servers/ServerBrowser/src/V1/Contract/Response/ListResponse.cs deleted file mode 100644 index 409e99e59..000000000 --- a/src/Servers/ServerBrowser/src/V1/Contract/Response/ListResponse.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using UniSpy.Server.ServerBrowser.V1.Abstraction.BaseClass; -using UniSpy.Server.ServerBrowser.V1.Contract.Request; -using UniSpy.Server.ServerBrowser.V1.Contract.Result; - -namespace UniSpy.Server.ServerBrowser.V1.Contract.Response -{ - public sealed class ListResponse : ResponseBase - { - private new ListRequest _request => (ListRequest)base._request; - private new ListResult _result => (ListResult)base._result; - public ListResponse(ListRequest request, ListResult result) : base(request, result) - { - } - - public override void Build() - { - SendingBuffer = $@"\fieldcount\{_result.ServersInfo.Count}"; - switch (_request.Type) - { - case ListRequestType.Basic: - BuildServerGeneralInfo(); - break; - case ListRequestType.Info: - BuildServerAllInfo(); - break; - case ListRequestType.Group: - BuildGroupInfo(); - break; - } - - SendingBuffer += @"\final\"; - } - - public void BuildGroupInfo() - { - - } - public void BuildServerAllInfo() - { - - } - public void BuildServerGeneralInfo() - { - foreach (var info in _result.ServersInfo) - { - if (_request.IsSendingCompressFormat) - { - var buffer = BitConverter.ToString(info.HostIPAddress.GetAddressBytes()) + BitConverter.ToString(BitConverter.GetBytes((short)info.HostPort)); - SendingBuffer += @$"\ip\{buffer}"; - } - SendingBuffer += @$"\ip\{info.HostIPEndPoint}"; - } - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V1/Contract/Result/ListResult.cs b/src/Servers/ServerBrowser/src/V1/Contract/Result/ListResult.cs deleted file mode 100644 index 3069c835f..000000000 --- a/src/Servers/ServerBrowser/src/V1/Contract/Result/ListResult.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.QueryReport.Aggregate.Redis.PeerGroup; -using UniSpy.Server.QueryReport.V1.Aggregation.Redis; -using UniSpy.Server.ServerBrowser.V1.Abstraction.BaseClass; - -namespace UniSpy.Server.ServerBrowser.V1.Contract.Result -{ - public sealed class ListResult : ResultBase - { - public List ServersInfo { get; set; } - public List PeerRoomsInfo { get; set; } - public ListResult() - { - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V1/Handler/CmdHandler/GameNameHandler.cs b/src/Servers/ServerBrowser/src/V1/Handler/CmdHandler/GameNameHandler.cs deleted file mode 100644 index 2d6a16318..000000000 --- a/src/Servers/ServerBrowser/src/V1/Handler/CmdHandler/GameNameHandler.cs +++ /dev/null @@ -1,43 +0,0 @@ -using UniSpy.Server.Core.Extension; -using UniSpy.Server.ServerBrowser.V1.Abstraction.BaseClass; -using UniSpy.Server.ServerBrowser.V1.Application; -using UniSpy.Server.ServerBrowser.V1.Contract.Request; - -namespace UniSpy.Server.ServerBrowser.V1.Handler.CmdHandler -{ - public sealed class GameNameHandler : CmdHandlerBase - { - private new GameNameRequest _request => (GameNameRequest)base._request; - public GameNameHandler(Client client, RequestBase request) : base(client, request) - { - } - - protected override void RequestCheck() - { - // todo create ICryptographic implementation here based on the enctype - base.RequestCheck(); - _client.Info.GameSecretKey = DataOperationExtensions.GetSecretKey(_request.GameName); - // we currently do not care about this, assume client is received our challenge - // todo we need to decode the EncKey here, which is sended when client connect to us - // if (_request.EncKey != ClientInfo.EncKey) - // { - // throw new ServerBrowser.Exception("Game encryption key is not valid"); - // } - } - protected override void DataOperation() - { - - switch (_request.EncType) - { - case EncryptionType.Plaintext: - break; - case EncryptionType.Type1: - // _client.Crypto = xxx; - break; - case EncryptionType.Type2: - // _client.Crypto = xxx; - break; - } - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V1/Handler/CmdHandler/ListHandler.cs b/src/Servers/ServerBrowser/src/V1/Handler/CmdHandler/ListHandler.cs deleted file mode 100644 index 09175c167..000000000 --- a/src/Servers/ServerBrowser/src/V1/Handler/CmdHandler/ListHandler.cs +++ /dev/null @@ -1,39 +0,0 @@ -using UniSpy.Server.ServerBrowser.V1.Abstraction.BaseClass; -using UniSpy.Server.ServerBrowser.V1.Application; -using UniSpy.Server.ServerBrowser.V1.Contract.Request; -using UniSpy.Server.ServerBrowser.V1.Contract.Response; -using UniSpy.Server.ServerBrowser.V1.Contract.Result; - -namespace UniSpy.Server.ServerBrowser.V1.Handler.CmdHandler -{ - public class ListHandler : CmdHandlerBase - { - private new ListResult _result { get => (ListResult)base._result; set => base._result = value; } - private new ListResponse _response { get => (ListResponse)base._response; set => base._response = value; } - private new ListRequest _request => (ListRequest)base._request; - public ListHandler(Client client, RequestBase request) : base(client, request) - { - _result = new ListResult(); - } - protected override void RequestCheck() - { - switch (_request.Type) - { - - case ListRequestType.Info: - case ListRequestType.Basic: - _result.ServersInfo = QueryReport.V1.Application.StorageOperation.Persistance.GetServersInfo(_request.GameName); - break; - case ListRequestType.Group: - // _result.PeerRoomsInfo = - // QueryReport.V2.Application.StorageOperation.Persistance.GetPeerRoomsInfo(_request.GameName); - // todo - break; - } - } - protected override void ResponseConstruct() - { - _response = new ListResponse(_request, _result); - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V1/Handler/CmdSwitcher.cs b/src/Servers/ServerBrowser/src/V1/Handler/CmdSwitcher.cs deleted file mode 100644 index bd6f5904a..000000000 --- a/src/Servers/ServerBrowser/src/V1/Handler/CmdSwitcher.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Misc; -using UniSpy.Server.ServerBrowser.V1.Application; -using UniSpy.Server.ServerBrowser.V1.Contract.Request; -using UniSpy.Server.ServerBrowser.V1.Handler.CmdHandler; - -namespace UniSpy.Server.ServerBrowser.V1.Handler -{ - public sealed class CmdSwitcher : CmdSwitcherBase - { - private new string _rawRequest => (string)base._rawRequest; - private new Client _client => (Client)base._client; - public CmdSwitcher(Client client, string rawRequest) : base(client, rawRequest) - { - } - - protected override IHandler CreateCmdHandlers(object name, object rawRequest) - { - //todo add v1 support - var request = (string)rawRequest; - switch ((string)name) - { - case "gamename": - return new GameNameHandler(_client, new GameNameRequest(request)); - case "list": - return new ListHandler(_client, new ListRequest(request)); - default: - return null; - } - } - - protected override void ProcessRawRequest() - { - // sb v1 protocol - var name = GameSpyUtils.GetRequestName(_rawRequest); - _requests.Add(new KeyValuePair(name, _rawRequest)); - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/AdHocRequestBase.cs b/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/AdHocRequestBase.cs deleted file mode 100755 index 819294634..000000000 --- a/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/AdHocRequestBase.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Linq; -using System.Net; -using UniSpy.Server.ServerBrowser.V2.Abstraction.BaseClass; - -namespace UniSpy.Server.ServerBrowser.V2.Abstraction -{ - public abstract class AdHocRequestBase : RequestBase - { - /// - /// The game server client search for - /// - public IPEndPoint GameServerPublicIPEndPoint { get; private set; } - public AdHocRequestBase(byte[] rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - byte[] ip = RawRequest.Skip(3).Take(4).ToArray(); - // raw request is in big endian we need to convert it to little endian - byte[] port = RawRequest.Skip(7).Take(2).Reverse().ToArray(); - //TODO fix for gbrome!!!!!!!!!!!!!!!!!!! - GameServerPublicIPEndPoint = new IPEndPoint(new IPAddress(ip), BitConverter.ToUInt16(port)); - } - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/AdHocResponseBase.cs b/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/AdHocResponseBase.cs deleted file mode 100644 index 942570e8f..000000000 --- a/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/AdHocResponseBase.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.ServerBrowser.V2.Contract.Result; - -namespace UniSpy.Server.ServerBrowser.V2.Abstraction.BaseClass -{ - public abstract class AdHocResponseBase : ResponseBase - { - public new AdHocResult _result => (AdHocResult)base._result; - protected List _buffer = new List(); - - protected AdHocResponseBase(ResultBase result) : base(null, result) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/CmdHandlerBase.cs b/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/CmdHandlerBase.cs deleted file mode 100755 index b39b9e775..000000000 --- a/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/CmdHandlerBase.cs +++ /dev/null @@ -1,15 +0,0 @@ -using UniSpy.Server.ServerBrowser.V2.Application; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.ServerBrowser.V2.Abstraction.BaseClass -{ - public abstract class CmdHandlerBase : UniSpy.Server.Core.Abstraction.BaseClass.CmdHandlerBase - { - protected new Client _client => (Client)base._client; - protected new RequestBase _request => (RequestBase)base._request; - protected new ResultBase _result { get => (ResultBase)base._result; set => base._result = value; } - public CmdHandlerBase(IClient client, IRequest request) : base(client, request) - { - } - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/RequestBase.cs b/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/RequestBase.cs deleted file mode 100755 index f0f5f3bc4..000000000 --- a/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/RequestBase.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Linq; -using UniSpy.Server.ServerBrowser.V2.Enumerate; - -namespace UniSpy.Server.ServerBrowser.V2.Abstraction.BaseClass -{ - public abstract class RequestBase : UniSpy.Server.Core.Abstraction.BaseClass.RequestBase - { - public int RequestLength { get; private set; } - public new byte[] RawRequest => (byte[])base.RawRequest; - public new RequestType CommandName { get => (RequestType)base.CommandName; protected set => base.CommandName = value; } - public RequestBase() { } - protected RequestBase(byte[] rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - RequestLength = BitConverter.ToInt16(RawRequest.Take(2).Reverse().ToArray()); - CommandName = (RequestType)RawRequest[2]; - } - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/ResponseBase.cs b/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/ResponseBase.cs deleted file mode 100755 index 9e535b727..000000000 --- a/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/ResponseBase.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace UniSpy.Server.ServerBrowser.V2.Abstraction.BaseClass -{ - - /// - /// SB always need to response to client even there are no server or error occured - /// - public abstract class ResponseBase : UniSpy.Server.Core.Abstraction.BaseClass.ResponseBase - { - protected new RequestBase _request => (RequestBase)base._request; - protected new ResultBase _result => (ResultBase)base._result; - public new byte[] SendingBuffer { get => (byte[])base.SendingBuffer; set => base.SendingBuffer = value; } - public ResponseBase(RequestBase request, ResultBase result) : base(request, result) - { - } - - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/ResultBase.cs b/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/ResultBase.cs deleted file mode 100755 index 870f40a85..000000000 --- a/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/ResultBase.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace UniSpy.Server.ServerBrowser.V2.Abstraction.BaseClass -{ - public class ResultBase : UniSpy.Server.Core.Abstraction.BaseClass.ResultBase - { - public ResultBase() - { - } - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/ServerListUpdateOption/ServerListUpdateOptionHandlerBase.cs b/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/ServerListUpdateOption/ServerListUpdateOptionHandlerBase.cs deleted file mode 100755 index fe51c9786..000000000 --- a/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/ServerListUpdateOption/ServerListUpdateOptionHandlerBase.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.Linq; -using UniSpy.Server.ServerBrowser.V2.Aggregate.Misc; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Extension; -using UniSpy.Server.Core.Logging; - -namespace UniSpy.Server.ServerBrowser.V2.Abstraction.BaseClass -{ - public abstract class ServerListUpdateOptionHandlerBase : CmdHandlerBase - { - protected new ServerListUpdateOptionRequestBase _request => (ServerListUpdateOptionRequestBase)base._request; - protected new ServerListUpdateOptionResultBase _result { get => (ServerListUpdateOptionResultBase)base._result; set => base._result = value; } - protected new ServerListUpdateOptionResponseBase _response { get => (ServerListUpdateOptionResponseBase)base._response; set => base._response = value; } - public ServerListUpdateOptionHandlerBase(IClient client, IRequest request) : base(client, request) - { - } - protected override void RequestCheck() - { - base.RequestCheck(); - if (_client.Info.GameSecretKey is null) - { - string secretKey = DataOperationExtensions - .GetSecretKey(_request.GameName); - //we first check and get secrete key from database - if (secretKey is null) - { - throw new System.ArgumentNullException("Can not find secretkey in database."); - } - //this is client public ip and default query port - _client.Info.GameSecretKey = secretKey; - } - if (_client.Info.ClientChallenge is null) - { - _client.Info.ClientChallenge = _request.ClientChallenge; - } - // initialize sb encryption - if (_client.Crypto is null) - { - _client.Crypto = new EnctypeX( - _client.Info.GameSecretKey, - _client.Info.ClientChallenge); - } - _client.Info.GameName = _request.GameName; - } - - protected override void Response() - { - _response.Build(); - var bodyBuffer = _response.SendingBuffer.Skip(14).ToArray(); - var headBuffer = _response.SendingBuffer.Take(14).ToArray(); - var bufferEncrypted = _client.Crypto.Encrypt(bodyBuffer); - var buffer = headBuffer.Concat(bufferEncrypted).ToArray(); - _client.LogNetworkSending(_response.SendingBuffer); - _client.Connection.Send(buffer); - } - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/ServerListUpdateOption/ServerListUpdateOptionRequestBase.cs b/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/ServerListUpdateOption/ServerListUpdateOptionRequestBase.cs deleted file mode 100755 index 96318511a..000000000 --- a/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/ServerListUpdateOption/ServerListUpdateOptionRequestBase.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Net; -using UniSpy.Server.ServerBrowser.V2.Enumerate; -namespace UniSpy.Server.ServerBrowser.V2.Abstraction.BaseClass -{ - public abstract class ServerListUpdateOptionRequestBase : RequestBase - { - public byte? RequestVersion { get; protected set; } - public byte? ProtocolVersion { get; protected set; } - public byte? EncodingVersion { get; protected set; } - public int? GameVersion { get; protected set; } - public int? QueryOptions { get; protected set; } - public string DevGameName { get; protected set; } - public string GameName { get; protected set; } - public string ClientChallenge { get; protected set; } - public ServerListUpdateOption? UpdateOption { get; protected set; } - public string[] Keys { get; protected set; } - public string Filter { get; protected set; } - public IPAddress SourceIP { get; protected set; } - public int? MaxServers { get; protected set; } - protected ServerListUpdateOptionRequestBase() { } - protected ServerListUpdateOptionRequestBase(byte[] rawRequest) : base(rawRequest) - { - } - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/ServerListUpdateOption/ServerListUpdateOptionResponseBase.cs b/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/ServerListUpdateOption/ServerListUpdateOptionResponseBase.cs deleted file mode 100755 index de9bc2e5f..000000000 --- a/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/ServerListUpdateOption/ServerListUpdateOptionResponseBase.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.ServerBrowser.V2.Application; -using UniSpy.Server.ServerBrowser.V2.Enumerate; -using UniSpy.Server.ServerBrowser.V2.Aggregate.Misc; -using UniSpy.Server.Core.Encryption; - -namespace UniSpy.Server.ServerBrowser.V2.Abstraction.BaseClass -{ - public abstract class ServerListUpdateOptionResponseBase : ResponseBase - { - protected new ServerListUpdateOptionRequestBase _request => (ServerListUpdateOptionRequestBase)base._request; - protected new ServerListUpdateOptionResultBase _result => (ServerListUpdateOptionResultBase)base._result; - protected List _serversInfoBuffer; - public ServerListUpdateOptionResponseBase(RequestBase request, ResultBase result) : base(request, result) - { - _serversInfoBuffer = new List(); - } - - public override void Build() - { - //todo check protocol version to build response data - //Add crypt header - var cryptHeader = BuildCryptHeader(); - _serversInfoBuffer.AddRange(cryptHeader); - _serversInfoBuffer.AddRange(_result.ClientRemoteIP); - _serversInfoBuffer.AddRange(ClientInfo.HtonQueryReportDefaultPort); - } - public byte[] BuildCryptHeader() - { - // cryptHeader have 14 bytes, when we encrypt data we need skip the first 14 bytes - var cryptHeader = new List(); - cryptHeader.Add(2 ^ 0xEC); - #region message length? - cryptHeader.AddRange(new byte[] { 0, 0 }); - #endregion - cryptHeader.Add((byte)(ClientInfo.ServerChallenge.Length ^ 0xEA)); - cryptHeader.AddRange(UniSpyEncoding.GetBytes(ClientInfo.ServerChallenge)); - return cryptHeader.ToArray(); - } - protected abstract void BuildServersFullInfo(); - - protected void BuildUniqueValue() - { - //because we are using NTS string so we do not have any value here - _serversInfoBuffer.Add(0); - } - protected void BuildServerKeys() - { - //we add the total number of the requested keys - _serversInfoBuffer.Add((byte)_request.Keys.Length); - //then we add the keys - foreach (var key in _request.Keys) - { - _serversInfoBuffer.Add((byte)DataKeyType.String); - _serversInfoBuffer.AddRange(UniSpyEncoding.GetBytes(key)); - _serversInfoBuffer.Add(StringFlag.StringSpliter); - } - } - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/ServerListUpdateOption/ServerListUpdateOptionResultBase.cs b/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/ServerListUpdateOption/ServerListUpdateOptionResultBase.cs deleted file mode 100755 index d95ea40b7..000000000 --- a/src/Servers/ServerBrowser/src/V2/Abstraction/BaseClass/ServerListUpdateOption/ServerListUpdateOptionResultBase.cs +++ /dev/null @@ -1,14 +0,0 @@ -using UniSpy.Server.ServerBrowser.V2.Enumerate; - -namespace UniSpy.Server.ServerBrowser.V2.Abstraction.BaseClass -{ - public abstract class ServerListUpdateOptionResultBase : ResultBase - { - public byte[] ClientRemoteIP { get; set; } - public GameServerFlags Flag { get; set; } - public string GameSecretKey { get; set; } - protected ServerListUpdateOptionResultBase() - { - } - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Aggregate/HeartbeatChannel.cs b/src/Servers/ServerBrowser/src/V2/Aggregate/HeartbeatChannel.cs deleted file mode 100644 index c238af607..000000000 --- a/src/Servers/ServerBrowser/src/V2/Aggregate/HeartbeatChannel.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.Core.Logging; -using UniSpy.Server.QueryReport.V2.Aggregate.Redis.GameServer; -using UniSpy.Server.ServerBrowser.V2.Handler.CmdHandler.AdHoc; - -namespace UniSpy.Server.ServerBrowser.V2.Aggregate -{ - public sealed class HeartbeatChannel : QueryReport.V2.Aggregate.Redis.HeartbeatChannel - { - /// - /// we do not run subscribe() in QR because QR only need to push - /// We run subscribe() in SB, because SB need to receive message - /// - public override void ReceivedMessage(GameServerInfo message) - { - LogWriter.LogInfo($"Received game server message from QR:{message.ServerID}"); - var handler = new AdHocHandler(message); - handler.Handle(); - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V2/Aggregate/Misc/BufferCache.cs b/src/Servers/ServerBrowser/src/V2/Aggregate/Misc/BufferCache.cs deleted file mode 100644 index 85241ef62..000000000 --- a/src/Servers/ServerBrowser/src/V2/Aggregate/Misc/BufferCache.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.Linq; -using UniSpy.Server.ServerBrowser.V2.Enumerate; - -namespace UniSpy.Server.ServerBrowser.V2.Aggregate.Misc -{ - public class BufferCache : Core.Misc.BufferCacheBase - { - public override bool ProcessBuffer(byte[] buffer, out byte[] completeBuffer) - { - if (((RequestType)buffer[2]) == RequestType.SendMessageRequest) - { - if (buffer.Length > 9) - { - // complete sendmessage request received - completeBuffer = buffer; - return true; - } - else - { - InCompleteBuffer = buffer; - completeBuffer = null; - return false; - } - } - else if (buffer.Take(6).SequenceEqual(NatNegotiation.Abstraction.BaseClass.RequestBase.MagicData)) - { - if (InCompleteBuffer is not null) - { - completeBuffer = InCompleteBuffer.Concat(buffer).ToArray(); - InCompleteBuffer = null; - return true; - } - else - { - // we ignore natneg message when _incompleteBuffer is null - completeBuffer = null; - return false; - } - } - else - { - completeBuffer = buffer; - return true; - } - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V2/Aggregate/Misc/Encryption.cs b/src/Servers/ServerBrowser/src/V2/Aggregate/Misc/Encryption.cs deleted file mode 100755 index c704211cf..000000000 --- a/src/Servers/ServerBrowser/src/V2/Aggregate/Misc/Encryption.cs +++ /dev/null @@ -1,192 +0,0 @@ -using UniSpy.Server.ServerBrowser.V2.Application; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Encryption; -namespace UniSpy.Server.ServerBrowser.V2.Aggregate.Misc -{ - public class EncryptionParameters - { - public byte[] Register = new byte[256]; - public byte Index0; - public byte Index1; - public byte Index2; - public byte Index3; - public byte Index4; - } - public class EnctypeX : ICryptography - { - private EncryptionParameters _encParams; - private byte[] _clientChallenge = new byte[8]; - private byte[] _serverChallenge; - private byte[] _secretKey; - public EnctypeX(string secretKey, string clientChallenge) - { - _encParams = new EncryptionParameters(); - _clientChallenge = UniSpyEncoding.GetBytes(clientChallenge); - _serverChallenge = UniSpyEncoding.GetBytes(ClientInfo.ServerChallenge); - _secretKey = UniSpyEncoding.GetBytes(secretKey); - InitEncryptionAlgorithm(); - } - - /// - /// Initialize the challenge which generates the permutation table - /// - /// game secret key - /// the random number challenge that server or client generate - public void InitEncryptionAlgorithm() - { - if (_clientChallenge.Length != 8) - { - //we have error client challenge - throw new System.ArgumentException("Client challenge length not valid!"); - } - - for (int i = 0; i < _serverChallenge.Length; i++) - { - int tempIndex0 = i * _secretKey[i % _secretKey.Length] % 8; - int tempIndex1 = i % 8; - byte bitwiseResult = (byte)(_clientChallenge[tempIndex1] ^ _serverChallenge[i]); - _clientChallenge[tempIndex0] ^= (byte)(bitwiseResult & 0xFF); - } - InitEncryptionParameters(); - } - - private void InitEncryptionParameters() - { - int i; - byte toSwap, swapTemp, randomSum; - byte keyPosition; - - if (_clientChallenge.Length < 1) - { - NonChallengeMappingInit(); - return; - } - - //generate ascii table - for (i = 0; i < 256; i++) - { - _encParams.Register[i] = (byte)i; - } - - toSwap = 0; - keyPosition = 0; - randomSum = 0; - for (i = 255; i > 0; i--) - { - toSwap = IndexPositionGeneration(i, ref randomSum, ref keyPosition); - swapTemp = _encParams.Register[i]; - _encParams.Register[i] = _encParams.Register[toSwap]; - _encParams.Register[toSwap] = swapTemp; - } - - // Initialize the indices and data dependencies. - // Indices are set to different values instead of all 0 - // to reduce what is known about the state of the state.cards - // when the first byte is emitted. - - _encParams.Index0 = _encParams.Register[1]; - _encParams.Index1 = _encParams.Register[3]; - _encParams.Index2 = _encParams.Register[5]; - _encParams.Index3 = _encParams.Register[7]; - _encParams.Index4 = _encParams.Register[randomSum]; - } - private void NonChallengeMappingInit() - { - // Initialize the indices and data dependencies. - byte i, j; - _encParams.Index0 = 1; - _encParams.Index1 = 3; - _encParams.Index2 = 5; - _encParams.Index3 = 7; - _encParams.Index4 = 11; - - // Start with state.cards all in inverse order. - for (i = 0, j = 255; i <= 255; i++, j--) - { - _encParams.Register[i] = j; - } - } - - private byte ByteShift(byte b) - { - byte swapTempStorage; - _encParams.Index1 = (byte)(_encParams.Index1 + _encParams.Register[_encParams.Index0++]); - swapTempStorage = _encParams.Register[_encParams.Index4]; - _encParams.Register[_encParams.Index4] = _encParams.Register[_encParams.Index1]; - _encParams.Register[_encParams.Index1] = _encParams.Register[_encParams.Index3]; - _encParams.Register[_encParams.Index3] = _encParams.Register[_encParams.Index0]; - _encParams.Register[_encParams.Index0] = swapTempStorage; - _encParams.Index2 = (byte)(_encParams.Index2 + _encParams.Register[swapTempStorage]); - - - _encParams.Index4 = (byte)(b ^ _encParams.Register[(_encParams.Register[_encParams.Index2] + - _encParams.Register[_encParams.Index0]) & 0xFF] ^ - _encParams.Register[_encParams.Register[(_encParams.Register[_encParams.Index3] + - _encParams.Register[_encParams.Index4] + - _encParams.Register[_encParams.Index1]) & 0xFF]]); - _encParams.Index3 = b; - - return _encParams.Index4; - } - - - /// - /// Generate permutation index position - /// - /// - /// - /// - /// - /// - private byte IndexPositionGeneration(int limit, ref byte randomSum, ref byte keyPosition) - { - byte swapIndex, retryLimiter, bitMask; - - if (limit == 0) - { - return 0; - } - - retryLimiter = 0; - bitMask = 1; - - while (bitMask < limit) - { - bitMask = (byte)((bitMask << 1) + 1); - } - - do - { - randomSum = (byte)(_encParams.Register[randomSum] + _clientChallenge[keyPosition++]); - - if (keyPosition >= _clientChallenge.Length) - { - keyPosition = 0; - randomSum = (byte)(randomSum + _clientChallenge.Length); - } - swapIndex = (byte)(bitMask & randomSum); - if (++retryLimiter > 11) - { - swapIndex %= (byte)limit; - } - } - while (swapIndex > limit); - - return swapIndex; - } - - public byte[] Encrypt(byte[] plainText) - { - int i; - byte[] cipherText = new byte[plainText.Length]; - for (i = 0; i < plainText.Length; i++) - { - cipherText[i] = ByteShift(plainText[i]); - } - return cipherText; - } - public byte[] Decrypt(byte[] buffer) => buffer; - - } - -} diff --git a/src/Servers/ServerBrowser/src/V2/Aggregate/Misc/GameFilter.cs b/src/Servers/ServerBrowser/src/V2/Aggregate/Misc/GameFilter.cs deleted file mode 100644 index d592d20bd..000000000 --- a/src/Servers/ServerBrowser/src/V2/Aggregate/Misc/GameFilter.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace UniSpy.Server.ServerBrowser.V2.Entity -{ - class GameFilter - { - public GameFilter() - { - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V2/Aggregate/Misc/KeyType.cs b/src/Servers/ServerBrowser/src/V2/Aggregate/Misc/KeyType.cs deleted file mode 100755 index cc0a86db7..000000000 --- a/src/Servers/ServerBrowser/src/V2/Aggregate/Misc/KeyType.cs +++ /dev/null @@ -1,49 +0,0 @@ -namespace UniSpy.Server.ServerBrowser.V2.Handler.SystemHandler.KeyType -{ - /// - /// all unique value string has 255 limits, - /// we do not think there will be a lot of server for each game - /// so we parse every value in string format for simplicity - /// - public class KeyTypeHandler - { - public Enumerate.DataKeyType GetKeyType(string key, string value) - { - if (IsByte(key, value)) - { - return Enumerate.DataKeyType.Byte; - } - else if (IsShort(key, value)) - { - return Enumerate.DataKeyType.Short; - } - else - { - return Enumerate.DataKeyType.String; - } - } - - public bool IsByte(string key, string value) - { - if (value.Length == 1) - { - if (key.Contains("numplayers") || key.Contains("maxplayers") || key.Contains("password")) - { - return true; - } - } - - return false; - } - - public bool IsShort(string key, string value) - { - if (value.Length == 2) - { - return true; - } - - return false; - } - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Aggregate/Misc/SBStringFlag.cs b/src/Servers/ServerBrowser/src/V2/Aggregate/Misc/SBStringFlag.cs deleted file mode 100755 index 7efe5827d..000000000 --- a/src/Servers/ServerBrowser/src/V2/Aggregate/Misc/SBStringFlag.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace UniSpy.Server.ServerBrowser.V2.Aggregate.Misc -{ - public class StringFlag - { - public static readonly byte[] AllServerEndFlag = { 0, 255, 255, 255, 255 }; - public static readonly byte StringSpliter = 0; - public static readonly byte NTSStringFlag = 0xFF; - - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Aggregate/ServerInfoBuilder.cs b/src/Servers/ServerBrowser/src/V2/Aggregate/ServerInfoBuilder.cs deleted file mode 100644 index aef6f43b2..000000000 --- a/src/Servers/ServerBrowser/src/V2/Aggregate/ServerInfoBuilder.cs +++ /dev/null @@ -1,127 +0,0 @@ -using System.Collections.Generic; -using System.Net; -using UniSpy.Server.QueryReport.V2.Aggregate.Redis.GameServer; -using UniSpy.Server.ServerBrowser.V2.Application; -using UniSpy.Server.ServerBrowser.V2.Enumerate; - -namespace UniSpy.Server.ServerBrowser.V2.Aggregate -{ - public static class ServerInfoBuilder - { - - /// - /// Add more server info here - /// the sequence of server info is important - /// 1.PRIVATE_IP_FLAG length=4 - /// 2.ICMP_IP_FLAG length=4 - /// 3.NONSTANDARD_PORT_FLAG length=2 - /// 4.NONSTANDARD_PRIVATE_PORT_FLAG length=2 - /// - /// - /// - public static List BuildServerInfoHeader(GameServerFlags flag, GameServerInfo serverInfo) - { - List header = new List(); - // add key flag - header.Add((byte)flag); - // we add server public ip here - header.AddRange(serverInfo.HostIPAddress.GetAddressBytes()); - // we check host port is standard port or not - CheckNonStandardPort(header, serverInfo); - // check if game can directly query information from server - CheckUnsolicitedUdp(header, serverInfo); - // we check the natneg flag - CheckNatNegFlag(header, serverInfo); - // now we check if there are private ip - CheckPrivateIP(header, serverInfo); - // we check private port here - CheckNonStandardPrivatePort(header, serverInfo); - // we check icmp support here - CheckICMPSupport(header, serverInfo); - - // _serverListData.AddRange(header); - return header; - } - public static void CheckNatNegFlag(List header, GameServerInfo serverInfo) - { - if (serverInfo.ServerData.ContainsKey("natneg")) - { - var natNegFlag = int.Parse(serverInfo.ServerData["natneg"]); - var unsolicitedUdp = header[0] & (byte)GameServerFlags.UnsolicitedUdpFlag; - if (natNegFlag == 1 && unsolicitedUdp == 0) - { - header[0] ^= (byte)GameServerFlags.ConnectNegotiateFlag; - } - } - } - public static void CheckUnsolicitedUdp(List header, GameServerInfo serverInfo) - { - if (serverInfo.ServerData.ContainsKey("allow_unsolicited_udp")) - { - var unsolicitedUdp = int.Parse(serverInfo.ServerData["unsolicitedudp"]); - if (unsolicitedUdp == 1) - { - header[0] ^= (byte)GameServerFlags.UnsolicitedUdpFlag; - } - } - } - /// - /// !when game create a channel chat, it will use both the public ip and private ip to build the name. - /// !Known game: Worm3d - /// - public static void CheckPrivateIP(List header, GameServerInfo serverInfo) - { - if (QueryReport.Application.StorageOperation.PeerGroupList.ContainsKey(serverInfo.GameName)) - { - // We already have the localip. Bytes are worng. - if (serverInfo.ServerData.ContainsKey("localip0")) - { - header[0] ^= (byte)GameServerFlags.PrivateIPFlag; - // there are multiple localip in dictionary we do not know which one is needed here, - // so we just send the first one. - byte[] bytesAddress = IPAddress.Parse(serverInfo.ServerData["localip0"]).GetAddressBytes(); - header.AddRange(bytesAddress); - } - } - } - public static void CheckNonStandardPort(List header, GameServerInfo serverInfo) - { - // !! only dedicated server have different query report port and host port - // !! but peer server have same query report port and host port - // todo we have to check when we need send host port or query report port - if (serverInfo.QueryReportPort != ClientInfo.QueryReportDefaultPort) - { - header[0] ^= (byte)GameServerFlags.NonStandardPort; - byte[] htonPort = serverInfo.QueryReportPortBytes; - header.AddRange(htonPort); - } - } - /// - /// !disabled because crysiswars localport is 64100 which is larger than short integer, need to find whether this function is needed. - /// - public static void CheckNonStandardPrivatePort(List header, GameServerInfo serverInfo) - { - // we check private port here - // if (serverInfo.ServerData.ContainsKey("localport")) - // { - // if (serverInfo.ServerData["localport"] != "" - // && serverInfo.ServerData["localport"] != ClientInfo.QueryReportDefaultPort.ToString()) - // { - // header[0] ^= (byte)GameServerFlags.NonStandardPrivatePortFlag; - // byte[] port = BitConverter.GetBytes(short.Parse(serverInfo.ServerData["localport"])); - // header.AddRange(port); - // } - // } - } - public static void CheckICMPSupport(List header, GameServerInfo serverInfo) - { - if (serverInfo.ServerData.ContainsKey("icmp_address")) - { - header[0] ^= (byte)GameServerFlags.IcmpIpFlag; - byte[] bytesAddress = IPAddress.Parse(serverInfo.ServerData["icmp_address"]).GetAddressBytes(); - header.AddRange(bytesAddress); - } - } - - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V2/Application/Client.cs b/src/Servers/ServerBrowser/src/V2/Application/Client.cs deleted file mode 100644 index d08582f55..000000000 --- a/src/Servers/ServerBrowser/src/V2/Application/Client.cs +++ /dev/null @@ -1,29 +0,0 @@ -using UniSpy.Server.ServerBrowser.V2.Handler; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.ServerBrowser.V2.Aggregate.Misc; - -namespace UniSpy.Server.ServerBrowser.V2.Application -{ - public sealed class Client : ClientBase - { - public new ClientInfo Info { get => (ClientInfo)base.Info; set => base.Info = value; } - private BufferCache _bufferCache = new BufferCache(); - public Client(IConnection connection, IServer server) : base(connection, server) - { - // Crypto is init in ServerListHandler - Info = new ClientInfo(); - IsLogRaw = true; - } - - protected override ISwitcher CreateSwitcher(object buffer) => new CmdSwitcher(this, (byte[])buffer); - - protected override void OnReceived(object buffer) - { - if (_bufferCache.ProcessBuffer((byte[])buffer, out var completeBuffer)) - { - base.OnReceived(completeBuffer); - } - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V2/Application/ClientInfo.cs b/src/Servers/ServerBrowser/src/V2/Application/ClientInfo.cs deleted file mode 100644 index 000f20bbd..000000000 --- a/src/Servers/ServerBrowser/src/V2/Application/ClientInfo.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Linq; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.ServerBrowser.V2.Enumerate; - -namespace UniSpy.Server.ServerBrowser.V2.Application -{ - public sealed class ClientInfo : ClientInfoBase - { - public const string LocalIP0 = "localip0"; - public const string LocalIP1 = "localip1"; - public const string PrivatePort = "privateport"; - public const string HostPort = "hostport"; - public const string HostPortNumber = "6500"; - /// - /// we are not gamespy, - /// for simplicity we use hard coded challenge - /// to reduce computation cost of our program - /// - public const string ServerChallenge = "0000000000"; - public const ushort QueryReportDefaultPort = 6500; - public static byte[] HtonQueryReportDefaultPort => BitConverter.GetBytes(QueryReportDefaultPort).Reverse().ToArray(); - public string GameSecretKey { get; set; } - public string ClientChallenge { get; set; } - public ServerListUpdateOption? SearchType { get; set; } - /// - /// The game name that this client is searching for - /// - public string GameName { get; set; } - public ClientInfo() - { - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V2/Application/ClientManager.cs b/src/Servers/ServerBrowser/src/V2/Application/ClientManager.cs deleted file mode 100644 index 3ea99c7ca..000000000 --- a/src/Servers/ServerBrowser/src/V2/Application/ClientManager.cs +++ /dev/null @@ -1,14 +0,0 @@ -using UniSpy.Server.Core.Abstraction.BaseClass; -using System.Linq; -using System.Collections.Generic; - -namespace UniSpy.Server.ServerBrowser.V2.Application -{ - public class ClientManager : ClientManagerBase - { - public static List GetClient(string gameName) - { - return ClientPool.Values.Where(c=>(((Client)c).Info).GameName == gameName).Select(c=>((Client)c)).ToList(); - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V2/Application/Server.cs b/src/Servers/ServerBrowser/src/V2/Application/Server.cs deleted file mode 100644 index 24038e8e9..000000000 --- a/src/Servers/ServerBrowser/src/V2/Application/Server.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Net; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Logging; -using UniSpy.Server.Core.Network.Tcp.Server; - -namespace UniSpy.Server.ServerBrowser.V2.Application -{ - public sealed class Server : ServerBase - { - static Server() - { - _name = "ServerBrowserV2"; - } - public Server() { } - - public Server(IConnectionManager manager) : base(manager) { } - public override void Start() - { - QueryReport.V2.Application.StorageOperation.HeartbeatChannel.Subscribe(); - QueryReport.V2.Application.StorageOperation.HeartbeatChannel.OnReceived += ReceivedMessage; - base.Start(); - } - public void ReceivedMessage(QueryReport.V2.Aggregate.Redis.GameServer.GameServerInfo message) - { - LogWriter.LogInfo($"Received game server message from QR:{message.ServerID}"); - var handler = new Handler.CmdHandler.AdHoc.AdHocHandler(message); - handler.Handle(); - } - protected override IClient CreateClient(IConnection connection) => new Client(connection, this); - - protected override IConnectionManager CreateConnectionManager(IPEndPoint endPoint) => new TcpConnectionManager(endPoint); - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V2/Contract/Request/AdHoc/PlayerSearchRequest.cs b/src/Servers/ServerBrowser/src/V2/Contract/Request/AdHoc/PlayerSearchRequest.cs deleted file mode 100755 index c5733e0fc..000000000 --- a/src/Servers/ServerBrowser/src/V2/Contract/Request/AdHoc/PlayerSearchRequest.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Linq; -using UniSpy.Server.ServerBrowser.V2.Abstraction.BaseClass; -using UniSpy.Server.Core.Encryption; - -namespace UniSpy.Server.ServerBrowser.V2.Contract.Request -{ - - public sealed class PlayerSearchRequest : RequestBase - { - public int SearchOption { get; private set; } - public new int CommandName => SearchOption; - public int MaxResults { get; private set; } - public string SearchName { get; private set; } - public string Message { get; private set; } - - - public PlayerSearchRequest(byte[] rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - SearchOption = Convert.ToInt16(RawRequest.Skip(3).Take(4).ToArray()); - MaxResults = Convert.ToInt16(RawRequest.Skip(7).Take(4).ToArray()); - - int nameLength = BitConverter.ToInt32(RawRequest.Skip(11).Take(4).ToArray()); - SearchName = UniSpyEncoding.GetString(RawRequest.Skip(15).Take(nameLength).ToArray()); - - int messageLength = BitConverter.ToInt32(RawRequest.Skip(15).Take(4).ToArray()); - Message = UniSpyEncoding.GetString(RawRequest.Skip(15 + nameLength + 4).Take(messageLength).ToArray()); - } - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Contract/Request/AdHoc/SendMsgRequest.cs b/src/Servers/ServerBrowser/src/V2/Contract/Request/AdHoc/SendMsgRequest.cs deleted file mode 100644 index 0459495b2..000000000 --- a/src/Servers/ServerBrowser/src/V2/Contract/Request/AdHoc/SendMsgRequest.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Linq; -using UniSpy.Server.ServerBrowser.V2.Abstraction; - -namespace UniSpy.Server.ServerBrowser.V2.Contract.Request -{ - - - public class SendMsgRequest : AdHocRequestBase - { - public byte[] PrefixMessage { get; private set; } - public byte[] ClientMessage { get; private set; } - public SendMsgRequest(byte[] rawRequest) : base(rawRequest) - { - } - public override void Parse() - { - base.Parse(); - ClientMessage = RawRequest.Skip(9).ToArray(); - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V2/Contract/Request/AdHoc/ServerInfoRequest.cs b/src/Servers/ServerBrowser/src/V2/Contract/Request/AdHoc/ServerInfoRequest.cs deleted file mode 100644 index 3bc0c7b20..000000000 --- a/src/Servers/ServerBrowser/src/V2/Contract/Request/AdHoc/ServerInfoRequest.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.ServerBrowser.V2.Abstraction; - -namespace UniSpy.Server.ServerBrowser.V2.Contract.Request -{ - - public class ServerInfoRequest : AdHocRequestBase - { - public ServerInfoRequest(byte[] rawRequest) : base(rawRequest) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V2/Contract/Request/ServerList/ServerListRequest.cs b/src/Servers/ServerBrowser/src/V2/Contract/Request/ServerList/ServerListRequest.cs deleted file mode 100755 index a64b861e9..000000000 --- a/src/Servers/ServerBrowser/src/V2/Contract/Request/ServerList/ServerListRequest.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.Linq; -using UniSpy.Server.ServerBrowser.V2.Abstraction.BaseClass; -using UniSpy.Server.ServerBrowser.V2.Enumerate; - -using UniSpy.Server.Core.Encryption; - -namespace UniSpy.Server.ServerBrowser.V2.Contract.Request -{ - /// - /// ServerList also called ServerRule in GameSpy SDK - /// - - public sealed class ServerListRequest : ServerListUpdateOptionRequestBase - { - public ServerListRequest(byte[] rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - CommandName = RequestType.ServerListRequest; - // if (RequestLength != RawRequest.Length) - // { - // throw new ServerBrowser.Exception("Server list request length is not correct."); - // } - - RequestVersion = RawRequest[2]; - ProtocolVersion = RawRequest[3]; - EncodingVersion = RawRequest[4]; - GameVersion = BitConverter.ToInt32(RawRequest.Skip(5).Take(4).ToArray()); - - //because there are empty string we can not use StringSplitOptions.RemoveEmptyEntries - var remainData = RawRequest.Skip(9).ToList(); - var devGameNameIndex = remainData.FindIndex(x => x == 0); - DevGameName = UniSpyEncoding.GetString(remainData.Take(devGameNameIndex).ToArray()); - remainData = remainData.Skip(devGameNameIndex + 1).ToList(); - var gameNameIndex = remainData.FindIndex(x => x == 0); - GameName = UniSpyEncoding.GetString(remainData.Take(gameNameIndex).ToArray()); - remainData = remainData.Skip(gameNameIndex + 1).ToList(); - // client challenge length is 8 - ClientChallenge = UniSpyEncoding.GetString(remainData.Take(8).ToArray()); - remainData = remainData.Skip(8).ToList(); - - var filterIndex = remainData.FindIndex(x => x == 0); - if (filterIndex > 0) - { - Filter = UniSpyEncoding.GetString(remainData.Take(filterIndex).ToArray()); - } - remainData = remainData.Skip(filterIndex + 1).ToList(); - - var keysIndex = remainData.FindIndex(x => x == 0); - Keys = UniSpyEncoding.GetString(remainData.Take(keysIndex).ToArray()).Split("\\", StringSplitOptions.RemoveEmptyEntries); - remainData = remainData.Skip(keysIndex + 1).ToList(); - //gamespy send this in big endian, we need to convert to little endian - byte[] byteUpdateOptions = remainData.Take(4).Reverse().ToArray(); - UpdateOption = (ServerListUpdateOption)BitConverter.ToInt32(byteUpdateOptions); - remainData = remainData.Skip(4).ToList(); - if ((UpdateOption & ServerListUpdateOption.AlternateSourceIP) != 0) - { - SourceIP = new System.Net.IPAddress(remainData.Take(4).ToArray()); - remainData = remainData.Skip(7).ToList(); - } - - if ((UpdateOption & ServerListUpdateOption.LimitResultCount) != 0) - { - if (remainData.Count != 4) - { - throw new ServerBrowser.Exception("The max number of server is incorrect."); - } - MaxServers = BitConverter.ToInt32(remainData.Take(4).Reverse().ToArray()); - } - } - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Contract/Response/AdHoc/DeleteServerInfoResponse.cs b/src/Servers/ServerBrowser/src/V2/Contract/Response/AdHoc/DeleteServerInfoResponse.cs deleted file mode 100644 index ec80ff446..000000000 --- a/src/Servers/ServerBrowser/src/V2/Contract/Response/AdHoc/DeleteServerInfoResponse.cs +++ /dev/null @@ -1,21 +0,0 @@ -using UniSpy.Server.ServerBrowser.V2.Abstraction.BaseClass; -using UniSpy.Server.ServerBrowser.V2.Contract.Result; -using UniSpy.Server.ServerBrowser.V2.Enumerate; - -namespace UniSpy.Server.ServerBrowser.V2.Contract.Response.AdHoc -{ - public sealed class DeleteServerInfoResponse : AdHocResponseBase - { - public DeleteServerInfoResponse(AdHocResult result) : base(result) - { - } - - public override void Build() - { - _buffer.Add((byte)ResponseType.DeleteServerMessage); - _buffer.AddRange(_result.GameServerInfo.HostIPAddress.GetAddressBytes()); - _buffer.AddRange(_result.GameServerInfo.QueryReportPortBytes); - SendingBuffer = _buffer.ToArray(); - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V2/Contract/Response/AdHoc/UpdateServerInfoResponse.cs b/src/Servers/ServerBrowser/src/V2/Contract/Response/AdHoc/UpdateServerInfoResponse.cs deleted file mode 100755 index 0c0d511ef..000000000 --- a/src/Servers/ServerBrowser/src/V2/Contract/Response/AdHoc/UpdateServerInfoResponse.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System; -using System.Linq; -using UniSpy.Server.ServerBrowser.V2.Abstraction.BaseClass; -using UniSpy.Server.ServerBrowser.V2.Enumerate; -using UniSpy.Server.ServerBrowser.V2.Aggregate.Misc; -using UniSpy.Server.ServerBrowser.V2.Contract.Result; -using UniSpy.Server.Core.Encryption; -using UniSpy.Server.ServerBrowser.V2.Aggregate; - -namespace UniSpy.Server.ServerBrowser.V2.Contract.Response -{ - /// - /// Get a server's information - /// - public sealed class UpdateServerInfoResponse : AdHocResponseBase - { - public UpdateServerInfoResponse(AdHocResult result) : base(result) - { - } - - public override void Build() - { - lock (_buffer) - { - _buffer.Add((byte)ResponseType.PushServerMessage); - BuildSingleServerFullInfo(); - // add message length here - var msgLength = BitConverter.GetBytes((ushort)(_buffer.Count + 2)).Reverse().ToArray(); - // we add the message length at the start - _buffer.InsertRange(0, msgLength); - } - SendingBuffer = _buffer.ToArray(); - } - - private void BuildSingleServerFullInfo() - { - var header = ServerInfoBuilder.BuildServerInfoHeader( - GameServerFlags.HasFullRulesFlag, - _result.GameServerInfo); - _buffer.AddRange(header); - if (_result.GameServerInfo.ServerData is not null) - { - foreach (var kv in _result.GameServerInfo.ServerData) - { - _buffer.AddRange(UniSpyEncoding.GetBytes(kv.Key)); - _buffer.Add(StringFlag.StringSpliter); - _buffer.AddRange(UniSpyEncoding.GetBytes(kv.Value)); - _buffer.Add(StringFlag.StringSpliter); - } - } - if (_result.GameServerInfo.PlayerData is not null) - { - foreach (var player in _result.GameServerInfo.PlayerData) - { - foreach (var kv in player) - { - _buffer.AddRange(UniSpyEncoding.GetBytes(kv.Key)); - _buffer.Add(StringFlag.StringSpliter); - _buffer.AddRange(UniSpyEncoding.GetBytes(kv.Value)); - _buffer.Add(StringFlag.StringSpliter); - } - } - } - if (_result.GameServerInfo.TeamData is not null) - { - foreach (var team in _result.GameServerInfo.TeamData) - { - foreach (var kv in team) - { - _buffer.AddRange(UniSpyEncoding.GetBytes(kv.Key)); - _buffer.Add(StringFlag.StringSpliter); - _buffer.AddRange(UniSpyEncoding.GetBytes(kv.Value)); - _buffer.Add(StringFlag.StringSpliter); - } - } - } - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V2/Contract/Response/ServerList/P2PGroupRoomListResponse.cs b/src/Servers/ServerBrowser/src/V2/Contract/Response/ServerList/P2PGroupRoomListResponse.cs deleted file mode 100755 index 626acccbe..000000000 --- a/src/Servers/ServerBrowser/src/V2/Contract/Response/ServerList/P2PGroupRoomListResponse.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Linq; -using UniSpy.Server.ServerBrowser.V2.Abstraction.BaseClass; -using UniSpy.Server.ServerBrowser.V2.Enumerate; -using UniSpy.Server.ServerBrowser.V2.Aggregate.Misc; -using UniSpy.Server.ServerBrowser.V2.Contract.Request; -using UniSpy.Server.ServerBrowser.V2.Contract.Result; -using UniSpy.Server.Core.Encryption; - -namespace UniSpy.Server.ServerBrowser.V2.Contract.Response.ServerList -{ - public sealed class P2PGroupRoomListResponse : ServerListUpdateOptionResponseBase - { - private new ServerListRequest _request => (ServerListRequest)base._request; - private new P2PGroupRoomListResult _result => (P2PGroupRoomListResult)base._result; - public P2PGroupRoomListResponse(ServerListUpdateOptionRequestBase request, ServerListUpdateOptionResultBase result) : base(request, result) - { - } - public override void Build() - { - base.Build(); - // we add the server keys - BuildServerKeys(); - //we use NTS string so total unique value list is 0 - BuildUniqueValue(); - //add server infomation such as public ip etc. - BuildServersFullInfo(); - SendingBuffer = _serversInfoBuffer.ToArray(); - } - - protected override void BuildServersFullInfo() - { - foreach (var room in _result.PeerRoomsInfo) - { - //add has key flag - _serversInfoBuffer.Add((byte)GameServerFlags.HasKeysFlag); - //in group list server ip is group id - - var groupIdBytes = BitConverter.GetBytes((int)room.GroupId).Reverse().ToArray(); - _serversInfoBuffer.AddRange(groupIdBytes); - - foreach (var key in _request.Keys) - { - _serversInfoBuffer.Add(StringFlag.NTSStringFlag); - var value = room.KeyValues.ContainsKey(key) ? room.KeyValues[key] : ""; - // if key is uint or int, we need first convert to ASCII string then get bytes - _serversInfoBuffer.AddRange(UniSpyEncoding.GetBytes(value.ToString())); - _serversInfoBuffer.Add(StringFlag.StringSpliter); - } - } - // group id = 0 means the end flag of group list - var endFlag = BitConverter.GetBytes((int)0); - _serversInfoBuffer.AddRange(endFlag); - } - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Contract/Response/ServerList/ServerMainListResponse.cs b/src/Servers/ServerBrowser/src/V2/Contract/Response/ServerList/ServerMainListResponse.cs deleted file mode 100755 index 164da16d7..000000000 --- a/src/Servers/ServerBrowser/src/V2/Contract/Response/ServerList/ServerMainListResponse.cs +++ /dev/null @@ -1,53 +0,0 @@ -using UniSpy.Server.ServerBrowser.V2.Abstraction.BaseClass; -using UniSpy.Server.ServerBrowser.V2.Aggregate.Misc; -using UniSpy.Server.ServerBrowser.V2.Contract.Request; -using UniSpy.Server.ServerBrowser.V2.Contract.Result; -using UniSpy.Server.Core.Encryption; - -namespace UniSpy.Server.ServerBrowser.V2.Aggregate.Packet.Response -{ - public sealed class ServerMainListResponse : ServerListUpdateOptionResponseBase - { - private new ServerListRequest _request => (ServerListRequest)base._request; - private new ServerMainListResult _result => (ServerMainListResult)base._result; - public ServerMainListResponse(ServerListUpdateOptionRequestBase request, ServerListUpdateOptionResultBase result) : base(request, result) - { - } - - public override void Build() - { - // we add the other header - base.Build(); - // we add the server keys - BuildServerKeys(); - //we use NTS string so total unique value list is 0 - BuildUniqueValue(); - //add server infomation such as public ip etc. - BuildServersFullInfo(); - - SendingBuffer = _serversInfoBuffer.ToArray(); - } - - protected override void BuildServersFullInfo() - { - foreach (var serverInfo in _result.GameServerInfos) - { - var header = ServerInfoBuilder.BuildServerInfoHeader(_result.Flag, serverInfo); - _serversInfoBuffer.AddRange(header); - foreach (var key in _request.Keys) - { - _serversInfoBuffer.Add(StringFlag.NTSStringFlag); - // if the key is in our database, we just add it - // otherwise we leave it empty, game will set default value - if (serverInfo.ServerData.ContainsKey(key)) - { - _serversInfoBuffer.AddRange(UniSpyEncoding.GetBytes(serverInfo.ServerData[key])); - } - _serversInfoBuffer.Add(StringFlag.StringSpliter); - } - } - //after all server information is added we add the end flag - _serversInfoBuffer.AddRange(StringFlag.AllServerEndFlag); - } - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Contract/Response/ServerList/ServerNetworkInfoListResponse.cs b/src/Servers/ServerBrowser/src/V2/Contract/Response/ServerList/ServerNetworkInfoListResponse.cs deleted file mode 100755 index d9a3b8d69..000000000 --- a/src/Servers/ServerBrowser/src/V2/Contract/Response/ServerList/ServerNetworkInfoListResponse.cs +++ /dev/null @@ -1,63 +0,0 @@ -using UniSpy.Server.ServerBrowser.V2.Abstraction.BaseClass; -using UniSpy.Server.ServerBrowser.V2.Enumerate; -using UniSpy.Server.ServerBrowser.V2.Aggregate.Misc; -using UniSpy.Server.ServerBrowser.V2.Contract.Result.ServerList; -using UniSpy.Server.Core.Encryption; -using UniSpy.Server.ServerBrowser.V2.Aggregate; - -namespace UniSpy.Server.ServerBrowser.V2.Contract.Response.ServerList -{ - /// - /// Get all server's full information - /// - public sealed class ServerNetworkInfoListResponse : ServerListUpdateOptionResponseBase - { - private new ServerNetworkInfoListResult _result => (ServerNetworkInfoListResult)base._result; - public ServerNetworkInfoListResponse(ServerListUpdateOptionRequestBase request, ServerListUpdateOptionResultBase result) : base(request, result) - { - } - public override void Build() - { - base.Build(); - SendingBuffer = _serversInfoBuffer.ToArray(); - } - protected override void BuildServersFullInfo() - { - foreach (var server in _result.ServersInfo) - { - var header = ServerInfoBuilder.BuildServerInfoHeader( - GameServerFlags.HasFullRulesFlag, - server); - _serversInfoBuffer.AddRange(header); - - foreach (var kv in server.ServerData) - { - _serversInfoBuffer.AddRange(UniSpyEncoding.GetBytes(kv.Key)); - _serversInfoBuffer.Add(StringFlag.StringSpliter); - _serversInfoBuffer.AddRange(UniSpyEncoding.GetBytes(kv.Value)); - _serversInfoBuffer.Add(StringFlag.StringSpliter); - } - foreach (var player in server.PlayerData) - { - foreach (var kv in player) - { - _serversInfoBuffer.AddRange(UniSpyEncoding.GetBytes(kv.Key)); - _serversInfoBuffer.Add(StringFlag.StringSpliter); - _serversInfoBuffer.AddRange(UniSpyEncoding.GetBytes(kv.Value)); - _serversInfoBuffer.Add(StringFlag.StringSpliter); - } - } - foreach (var team in server.TeamData) - { - foreach (var kv in team) - { - _serversInfoBuffer.AddRange(UniSpyEncoding.GetBytes(kv.Key)); - _serversInfoBuffer.Add(StringFlag.StringSpliter); - _serversInfoBuffer.AddRange(UniSpyEncoding.GetBytes(kv.Value)); - _serversInfoBuffer.Add(StringFlag.StringSpliter); - } - } - } - } - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Contract/Result/AdHoc/AdHocResult.cs b/src/Servers/ServerBrowser/src/V2/Contract/Result/AdHoc/AdHocResult.cs deleted file mode 100755 index dcfc2730f..000000000 --- a/src/Servers/ServerBrowser/src/V2/Contract/Result/AdHoc/AdHocResult.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.QueryReport.V2.Aggregate.Redis.GameServer; -using UniSpy.Server.ServerBrowser.V2.Abstraction.BaseClass; - -namespace UniSpy.Server.ServerBrowser.V2.Contract.Result -{ - public sealed class AdHocResult : ResultBase - { - public GameServerInfo GameServerInfo { get; set; } - public AdHocResult() - { - } - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Contract/Result/ServerList/P2PGroupRoomListResult.cs b/src/Servers/ServerBrowser/src/V2/Contract/Result/ServerList/P2PGroupRoomListResult.cs deleted file mode 100755 index 8389e9e19..000000000 --- a/src/Servers/ServerBrowser/src/V2/Contract/Result/ServerList/P2PGroupRoomListResult.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.QueryReport.Aggregate.Redis.PeerGroup; -using UniSpy.Server.ServerBrowser.V2.Abstraction.BaseClass; - -namespace UniSpy.Server.ServerBrowser.V2.Contract.Result -{ - public sealed class P2PGroupRoomListResult : ServerListUpdateOptionResultBase - { - public List PeerRoomsInfo { get; set; } - public P2PGroupRoomListResult() - { - } - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Contract/Result/ServerList/ServerMainListResult.cs b/src/Servers/ServerBrowser/src/V2/Contract/Result/ServerList/ServerMainListResult.cs deleted file mode 100755 index d5e3790dd..000000000 --- a/src/Servers/ServerBrowser/src/V2/Contract/Result/ServerList/ServerMainListResult.cs +++ /dev/null @@ -1,15 +0,0 @@ -using UniSpy.Server.ServerBrowser.V2.Abstraction.BaseClass; -using System.Collections.Generic; -using UniSpy.Server.QueryReport.V2.Aggregate.Redis.GameServer; - -namespace UniSpy.Server.ServerBrowser.V2.Contract.Result -{ - public class ServerMainListResult : ServerListUpdateOptionResultBase - { - public List GameServerInfos { get; set; } - public ServerMainListResult() - { - GameServerInfos = new List(); - } - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Contract/Result/ServerList/ServerNetworkInfoListResult.cs b/src/Servers/ServerBrowser/src/V2/Contract/Result/ServerList/ServerNetworkInfoListResult.cs deleted file mode 100755 index 9c63feac3..000000000 --- a/src/Servers/ServerBrowser/src/V2/Contract/Result/ServerList/ServerNetworkInfoListResult.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.QueryReport.V2.Aggregate.Redis.GameServer; - -namespace UniSpy.Server.ServerBrowser.V2.Contract.Result.ServerList -{ - - public sealed class ServerNetworkInfoListResult : ServerMainListResult - { - public List ServersInfo { get; private set; } - public ServerNetworkInfoListResult() - { - ServersInfo = new List(); - } - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Enumerate/GeneralEnum.cs b/src/Servers/ServerBrowser/src/V2/Enumerate/GeneralEnum.cs deleted file mode 100755 index 31d0d87e8..000000000 --- a/src/Servers/ServerBrowser/src/V2/Enumerate/GeneralEnum.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace UniSpy.Server.ServerBrowser.V2.Enumerate -{ - public enum PlayerSearchOptions - { - SearchAllGames = 1, - SearchLeftSubstring = 2, - SearchRightSubString = 4, - SearchAnySubString = 8, - } - - public enum QueryType - { - Basic, - Full, - ICMP - } - - public enum DataKeyType - { - String, - Byte, - Short - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Enumerate/ServerListEnum.cs b/src/Servers/ServerBrowser/src/V2/Enumerate/ServerListEnum.cs deleted file mode 100755 index 4a0930d06..000000000 --- a/src/Servers/ServerBrowser/src/V2/Enumerate/ServerListEnum.cs +++ /dev/null @@ -1,85 +0,0 @@ -namespace UniSpy.Server.ServerBrowser.V2.Enumerate -{ - public enum RequestType : byte - { - ServerListRequest, - ServerInfoRequest, - SendMessageRequest, - KeepAliveReply, - MapLoopRequest, - PlayerSearchRequest - } - - public enum ResponseType - { - PushKeysMessage = 1, - PushServerMessage = 2, - KeepAliveMessage = 3, - DeleteServerMessage = 4, - MapLoopMessage = 5, - PlayerSearchMessage = 6 - } - - public enum ProtocolVersion - { - ListProtocolVersion1 = 0, - ListEncodingVersion = 3 - } - - public enum ServerListUpdateOption - { - /// - /// This is used to tell server browser client want main server list (keys and values) - /// - ServerMainList = 0, - SendFieldForAll = 1, - /// - /// get the full information of all servers - /// - ServerFullInfoList = 2, - /// - /// Push new local game status to QueryReport server - /// - P2PServerMainList = 4, - AlternateSourceIP = 8, - P2PGroupRoomList = 32, - NoListCache = 64, - LimitResultCount = 128 - } - - public enum GameServerFlags - { - /// - /// game can directly send request to dedicate server - /// - UnsolicitedUdpFlag = 1, - /// - /// private ip exist - /// - PrivateIPFlag = 2, - /// - /// connect with nat neg - /// - ConnectNegotiateFlag = 4, - /// - /// server has icmp - /// - IcmpIpFlag = 8, - /// - /// non standard query port - /// - NonStandardPort = 16, - /// - /// nonstandard private port - /// - NonStandardPrivatePortFlag = 32, - /// - /// has standard keys - /// - HasKeysFlag = 64, - /// - /// has full rules keys - /// - HasFullRulesFlag = 128 - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Handler/CmdHandler/AdHoc/AdHocHandler.cs b/src/Servers/ServerBrowser/src/V2/Handler/CmdHandler/AdHoc/AdHocHandler.cs deleted file mode 100644 index 291c9986e..000000000 --- a/src/Servers/ServerBrowser/src/V2/Handler/CmdHandler/AdHoc/AdHocHandler.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System.Threading.Tasks; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Logging; -using UniSpy.Server.QueryReport.V2.Aggregate.Redis.GameServer; -using UniSpy.Server.ServerBrowser.V2.Application; -using UniSpy.Server.ServerBrowser.V2.Contract.Response; -using UniSpy.Server.ServerBrowser.V2.Contract.Response.AdHoc; -using UniSpy.Server.ServerBrowser.V2.Contract.Result; -using UniSpy.Server.ServerBrowser.V2.Enumerate; - -namespace UniSpy.Server.ServerBrowser.V2.Handler.CmdHandler.AdHoc -{ - public class AdHocHandler : IHandler - { - public GameServerInfo _message; - public AdHocHandler(GameServerInfo message) - { - LogWriter.LogCurrentClass(this); - _message = message; - } - - public void Handle() - { - IResponse response = null; - var result = new AdHocResult() { GameServerInfo = _message }; - switch (_message.ServerStatus) - { - case QueryReport.V2.Enumerate.GameServerStatus.Normal: - case QueryReport.V2.Enumerate.GameServerStatus.Update: - case QueryReport.V2.Enumerate.GameServerStatus.Playing: - response = new UpdateServerInfoResponse(result); - break; - case QueryReport.V2.Enumerate.GameServerStatus.Shutdown: - response = new DeleteServerInfoResponse(result); - break; - } - - var clients = ClientManager.GetClient(_message.GameName); - Parallel.ForEach(clients, client => - { - if (client.Info.GameName == _message.GameName - && client.Crypto is not null - && (client.Info.SearchType == ServerListUpdateOption.ServerMainList - || client.Info.SearchType == ServerListUpdateOption.P2PServerMainList)) - { - client.LogInfo($"Sending AdHoc message {_message.ServerStatus} to client"); - client.Send(response); - } - }); - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V2/Handler/CmdHandler/AdHoc/SendMsgHandler.cs b/src/Servers/ServerBrowser/src/V2/Handler/CmdHandler/AdHoc/SendMsgHandler.cs deleted file mode 100755 index b67a31c78..000000000 --- a/src/Servers/ServerBrowser/src/V2/Handler/CmdHandler/AdHoc/SendMsgHandler.cs +++ /dev/null @@ -1,42 +0,0 @@ -using UniSpy.Server.ServerBrowser.V2.Abstraction.BaseClass; -using UniSpy.Server.ServerBrowser.V2.Contract.Request; -using UniSpy.Server.QueryReport.V2.Contract.Request; -using UniSpy.Server.Core.Extension; -using UniSpy.Server.Core.Logging; -using UniSpy.Server.ServerBrowser.V2.Application; - -namespace UniSpy.Server.ServerBrowser.V2.Handler.CmdHandler -{ - /// - /// Natneg message maybe incompelete - /// when debugging sdk the natneg message will split to 2 request - /// we have to save first message then wait for next message - /// - public sealed class SendMsgHandler : CmdHandlerBase - { - private new SendMsgRequest _request => (SendMsgRequest)base._request; - public SendMsgHandler(Client client, SendMsgRequest request) : base(client, request) - { - } - protected override void DataOperation() - { - var gameServer = QueryReport.V2.Application.StorageOperation.Persistance.GetGameServerInfo(_request.GameServerPublicIPEndPoint); - - if (gameServer is null) - { - throw new ServerBrowser.Exception($"No match server found by address {_request.GameServerPublicIPEndPoint}, we ignore client request."); - } - - var message = new ClientMessageRequest() - { - ServerBrowserSenderId = _client.Server.Id, - NatNegMessage = _request.ClientMessage, - InstantKey = gameServer.InstantKey, - TargetIPEndPoint = gameServer.QueryReportIPEndPoint, - CommandName = QueryReport.V2.Enumerate.RequestType.ClientMessage - }; - QueryReport.V2.Application.StorageOperation.Persistance.PublishClientMessage(message); - _client.LogInfo($"Send client message to QueryReport Server: {gameServer.ServerID} [{StringExtensions.ConvertByteToHexString(message.NatNegMessage)}]"); - } - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Handler/CmdHandler/AdHoc/ServerInfoHandler.cs b/src/Servers/ServerBrowser/src/V2/Handler/CmdHandler/AdHoc/ServerInfoHandler.cs deleted file mode 100755 index 19fea349a..000000000 --- a/src/Servers/ServerBrowser/src/V2/Handler/CmdHandler/AdHoc/ServerInfoHandler.cs +++ /dev/null @@ -1,47 +0,0 @@ -using UniSpy.Server.ServerBrowser.V2.Application; -using UniSpy.Server.ServerBrowser.V2.Abstraction.BaseClass; -using UniSpy.Server.ServerBrowser.V2.Contract.Request; -using UniSpy.Server.ServerBrowser.V2.Contract.Response; -using UniSpy.Server.ServerBrowser.V2.Contract.Result; -using UniSpy.Server.Core.Logging; - -namespace UniSpy.Server.ServerBrowser.V2.Handler.CmdHandler -{ - /// - /// Get full rules for a server (for example, to get - /// player information from a server that only has basic information so far) - /// - - public sealed class ServerInfoHandler : CmdHandlerBase - { - private new ServerInfoRequest _request => (ServerInfoRequest)base._request; - private new AdHocResult _result { get => (AdHocResult)base._result; set => base._result = value; } - - public ServerInfoHandler(Client client, ServerInfoRequest request) : base(client, request) - { - _result = new AdHocResult(); - } - - protected override void DataOperation() - { - _result.GameServerInfo = QueryReport.V2.Application.StorageOperation.Persistance.GetGameServerInfo(_request.GameServerPublicIPEndPoint); - - //TODO if there are no server found, we still send response back to client - if (_result.GameServerInfo is null) - { - // throw new ServerBrowser.Exception("No server found in database."); - _client.LogInfo($"No server found on IP {_request.GameServerPublicIPEndPoint}."); - return; - } - } - - protected override void ResponseConstruct() - { - if (_result.GameServerInfo is null) - { - return; - } - _response = new UpdateServerInfoResponse(_result); - } - } -} diff --git a/src/Servers/ServerBrowser/src/V2/Handler/CmdHandler/ServerList/ServerListHandler.cs b/src/Servers/ServerBrowser/src/V2/Handler/CmdHandler/ServerList/ServerListHandler.cs deleted file mode 100644 index 5d07288ff..000000000 --- a/src/Servers/ServerBrowser/src/V2/Handler/CmdHandler/ServerList/ServerListHandler.cs +++ /dev/null @@ -1,145 +0,0 @@ -using System.Linq; -using UniSpy.Server.ServerBrowser.V2.Application; -using UniSpy.Server.ServerBrowser.V2.Abstraction.BaseClass; -using UniSpy.Server.ServerBrowser.V2.Enumerate; -using UniSpy.Server.ServerBrowser.V2.Aggregate.Packet.Response; -using UniSpy.Server.ServerBrowser.V2.Contract.Response.ServerList; -using UniSpy.Server.ServerBrowser.V2.Contract.Result; -using UniSpy.Server.ServerBrowser.V2.Contract.Request; -using UniSpy.Server.QueryReport.Aggregate.Redis.PeerGroup; -using System.Collections.Generic; - -namespace UniSpy.Server.ServerBrowser.V2.Handler.CmdHandler -{ - - public class ServerListHandler : ServerListUpdateOptionHandlerBase - { - public ServerListHandler(Client client, ServerListRequest request) : base(client, request) - { - } - protected override void RequestCheck() - { - base.RequestCheck(); - switch (_request.UpdateOption) - { - case ServerListUpdateOption.ServerMainList: - case ServerListUpdateOption.P2PServerMainList: - case ServerListUpdateOption.LimitResultCount: - case ServerListUpdateOption.ServerFullInfoList: - _result = new ServerMainListResult(); - break; - case ServerListUpdateOption.P2PGroupRoomList: - _result = new P2PGroupRoomListResult(); - break; - default: - throw new ServerBrowser.Exception("unknown serverlist update option type"); - } - } - protected override void DataOperation() - { - _result.GameSecretKey = _client.Info.GameSecretKey; - _result.ClientRemoteIP = _client.Connection.RemoteIPEndPoint.Address.GetAddressBytes(); - //todo check protocol version!!!! - switch (_request.UpdateOption) - { - case ServerListUpdateOption.ServerMainList: - ServerMainList(); - break; - case ServerListUpdateOption.P2PServerMainList: - case ServerListUpdateOption.LimitResultCount: - P2PServerMainList(); - break; - case ServerListUpdateOption.P2PGroupRoomList: - P2PGroupRoomList(); - break; - case ServerListUpdateOption.ServerFullInfoList: - // do nothing here - break; - default: - throw new ServerBrowser.Exception("unknown serverlist update option type"); - } - _client.Info.SearchType = _request.UpdateOption; - - } - private void P2PGroupRoomList() - { - - // first get the peer room in memory, if there is no such game we do not continue - if (!QueryReport.Application.StorageOperation.PeerGroupList.ContainsKey(_request.GameName)) - { - throw new ServerBrowser.Exception($"Invalid game name: {_request.GameName}."); - } - - // Game name is unique in redis database - var grouplist = QueryReport.Application.StorageOperation.PeerGroupList[_request.GameName]; - // we do not create peer room cache on redis, we just send peer room info to client - var tempInfos = new List(); - foreach (var group in grouplist) - { - // we create room info, set the room properties to default - var roomInfo = new PeerRoomInfo(group.Game.Gamename, group.Groupid, group.Roomname); - tempInfos.Add(roomInfo); - // get the channels info from redis where groupid equals above - var groupRooms = QueryReport.Application.StorageOperation.GetPeerGroupChannel(group.Groupid); - // get the channels info from redis where created under gamename and groupid above - var stagingRooms = QueryReport.Application.StorageOperation.GetPeerStagingChannel(group.Game.Gamename, group.Groupid); - if (groupRooms.Count != 0) - { - roomInfo.NumberOfWaitingPlayers = groupRooms.Sum(r => r.Users.Count); - } - if (stagingRooms.Count != 0) - { - roomInfo.NumberOfPlayingPlayers = stagingRooms.Sum(r => r.Users.Count); - roomInfo.NumberOfGames = stagingRooms.Count; - } - roomInfo.NumberOfPlayers = roomInfo.NumberOfWaitingPlayers + roomInfo.NumberOfPlayingPlayers; - // if there did not have any rooms in redis, the properties in roominfo stay default - } - ((P2PGroupRoomListResult)_result).PeerRoomsInfo = tempInfos; - } - private void P2PServerMainList() - { - var serverInfos = QueryReport.V2.Application.StorageOperation.Persistance.GetGameServerInfos(_request.GameName); - ((ServerMainListResult)_result).Flag = GameServerFlags.HasKeysFlag; - - //TODO do filter - if (_request.Filter.Contains("groupid=")) - { - var groupId = _request.Filter.Replace("groupid=", ""); - var filteredGameServerInfos = serverInfos.Where(s => s.ServerData.ContainsKey("groupid=")).Where(s => s.ServerData["groupid"] == groupId).ToList(); - ((ServerMainListResult)_result).GameServerInfos = filteredGameServerInfos; - } - else - { - ((ServerMainListResult)_result).GameServerInfos = serverInfos; - } - - } - private void ServerMainList() - { - var serverInfos = QueryReport.V2.Application.StorageOperation.Persistance.GetGameServerInfos(_request.GameName); - ((ServerMainListResult)_result).GameServerInfos = serverInfos; - ((ServerMainListResult)_result).Flag = GameServerFlags.HasKeysFlag; - } - - protected override void ResponseConstruct() - { - switch (_request.UpdateOption) - { - case ServerListUpdateOption.ServerMainList: - case ServerListUpdateOption.P2PServerMainList: - case ServerListUpdateOption.LimitResultCount: - _response = new ServerMainListResponse(_request, _result); - break; - case ServerListUpdateOption.P2PGroupRoomList: - _response = new P2PGroupRoomListResponse(_request, _result); - break; - case ServerListUpdateOption.ServerFullInfoList: - _response = new ServerNetworkInfoListResponse(_request, _result); - break; - default: - throw new ServerBrowser.Exception("unknown serverlist update option type"); - } - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/src/V2/Handler/CmdSwitcher.cs b/src/Servers/ServerBrowser/src/V2/Handler/CmdSwitcher.cs deleted file mode 100755 index 3a1480962..000000000 --- a/src/Servers/ServerBrowser/src/V2/Handler/CmdSwitcher.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.ServerBrowser.V2.Enumerate; -using UniSpy.Server.ServerBrowser.V2.Contract.Request; -using UniSpy.Server.ServerBrowser.V2.Handler.CmdHandler; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.ServerBrowser.V2.Application; - -namespace UniSpy.Server.ServerBrowser.V2.Handler -{ - public sealed class CmdSwitcher : CmdSwitcherBase - { - private new byte[] _rawRequest => (byte[])base._rawRequest; - private new Client _client => (Client)base._client; - public CmdSwitcher(Client client, byte[] rawRequest) : base(client, rawRequest) - { - } - protected override void ProcessRawRequest() - { - var name = (RequestType)_rawRequest[2]; - _requests.Add(new KeyValuePair(name, _rawRequest)); - } - - protected override IHandler CreateCmdHandlers(object name, object rawRequest) - { - var req = (byte[])rawRequest; - switch ((RequestType)name) - { - case RequestType.ServerListRequest: - return new ServerListHandler(_client, new ServerListRequest(req)); - case RequestType.ServerInfoRequest: - return new ServerInfoHandler(_client, new ServerInfoRequest(req)); - case RequestType.SendMessageRequest: - return new SendMsgHandler(_client, new SendMsgRequest(req)); - default: - return null; - } - } - } -} diff --git a/src/Servers/ServerBrowser/test/UniSpy.Server.ServerBrowser.Test.csproj b/src/Servers/ServerBrowser/test/UniSpy.Server.ServerBrowser.Test.csproj deleted file mode 100644 index dd6f9415f..000000000 --- a/src/Servers/ServerBrowser/test/UniSpy.Server.ServerBrowser.Test.csproj +++ /dev/null @@ -1,33 +0,0 @@ - - - - net6.0 - false - ..\..\..\..\common\Icon\UniSpy_Logo.ico - - - AnyCPU - ..\..\..\..\build\$(Configuration) - - - ..\..\..\..\build\$(Configuration) - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - - - \ No newline at end of file diff --git a/src/Servers/ServerBrowser/test/V1/RequestTest.cs b/src/Servers/ServerBrowser/test/V1/RequestTest.cs deleted file mode 100644 index 44c530557..000000000 --- a/src/Servers/ServerBrowser/test/V1/RequestTest.cs +++ /dev/null @@ -1,23 +0,0 @@ -using UniSpy.Server.ServerBrowser.V1.Contract.Request; -using Xunit; - -namespace UniSpy.Server.ServerBrowser.Test.V1 -{ - public class RequestTest - { - [Fact] - public void Armada220230413() - { - var raw1 = @"\gamename\armada2\gamever\1.6\location\0\validate\Qsu/4AdL\final\\queryid\1.1\"; - var request1 = new GameNameRequest(raw1); - request1.Parse(); - Assert.True(request1.GameName == "armada2"); - Assert.True(request1.Version == "1.6"); - var raw2 = @"\list\groups\gamename\armada2\final\"; - var request2 = new ListRequest(raw2); - request2.Parse(); - Assert.True(request2.Type == ListRequestType.Group); - Assert.True(request2.GameName == "armada2"); - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/test/V2/FilterTest.cs b/src/Servers/ServerBrowser/test/V2/FilterTest.cs deleted file mode 100644 index 0ac2c8c01..000000000 --- a/src/Servers/ServerBrowser/test/V2/FilterTest.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Linq; -using Xunit; - -namespace UniSpy.Server.ServerBrowser.V2.Test -{ - public class Person - { - public string Name { get; set; } - public int Age { get; set; } - public int Weight { get; set; } - public DateTime FavouriteDay { get; set; } - } - public class FilterTest - { - [Fact(Skip = "not implemented")] - public void SimpleQueryFilter() - { - // Given - var temp = "(country = 'US' and numplayers > 5) or hostname like '%GameSpy%'"; - var delimiterChars = new char[] { '(', ')' }; - var frags = temp.Split(delimiterChars).ToList(); - frags.RemoveAll(s => s == ""); - // When - Assert.Equal("country = 'US' and numplayers > 5", frags[0]); - Assert.Equal("or hostname like '%GameSpy%'", frags[1]); - // Then - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/test/V2/GameTest.cs b/src/Servers/ServerBrowser/test/V2/GameTest.cs deleted file mode 100644 index f3f697651..000000000 --- a/src/Servers/ServerBrowser/test/V2/GameTest.cs +++ /dev/null @@ -1,139 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Core.Abstraction.Interface; -using Xunit; - -namespace UniSpy.Server.ServerBrowser.V2.Test -{ - public class GameTest - { - [Fact] - public void Gmtest20200309() - { - var qrReq = new byte[] { 0x03, 0xEA, 0x2B, 0xAF, 0x50, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x69, 0x70, 0x30, 0x00, 0x31, 0x39, 0x32, 0x2E, 0x31, 0x36, 0x38, 0x2E, 0x31, 0x32, 0x32, 0x2E, 0x32, 0x32, 0x36, 0x00, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x70, 0x6F, 0x72, 0x74, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x00, 0x6E, 0x61, 0x74, 0x6E, 0x65, 0x67, 0x00, 0x31, 0x00, 0x73, 0x74, 0x61, 0x74, 0x65, 0x63, 0x68, 0x61, 0x6E, 0x67, 0x65, 0x64, 0x00, 0x33, 0x00, 0x67, 0x61, 0x6D, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x00, 0x67, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x6E, 0x61, 0x6D, 0x65, 0x00, 0x47, 0x61, 0x6D, 0x65, 0x53, 0x70, 0x79, 0x20, 0x51, 0x52, 0x32, 0x20, 0x53, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x00, 0x67, 0x61, 0x6D, 0x65, 0x76, 0x65, 0x72, 0x00, 0x32, 0x2E, 0x30, 0x30, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x70, 0x6F, 0x72, 0x74, 0x00, 0x32, 0x35, 0x30, 0x30, 0x30, 0x00, 0x6D, 0x61, 0x70, 0x6E, 0x61, 0x6D, 0x65, 0x00, 0x67, 0x6D, 0x74, 0x6D, 0x61, 0x70, 0x31, 0x00, 0x67, 0x61, 0x6D, 0x65, 0x74, 0x79, 0x70, 0x65, 0x00, 0x61, 0x72, 0x65, 0x6E, 0x61, 0x00, 0x6E, 0x75, 0x6D, 0x70, 0x6C, 0x61, 0x79, 0x65, 0x72, 0x73, 0x00, 0x31, 0x30, 0x00, 0x6E, 0x75, 0x6D, 0x74, 0x65, 0x61, 0x6D, 0x73, 0x00, 0x32, 0x00, 0x6D, 0x61, 0x78, 0x70, 0x6C, 0x61, 0x79, 0x65, 0x72, 0x73, 0x00, 0x33, 0x32, 0x00, 0x67, 0x61, 0x6D, 0x65, 0x6D, 0x6F, 0x64, 0x65, 0x00, 0x6F, 0x70, 0x65, 0x6E, 0x70, 0x6C, 0x61, 0x79, 0x69, 0x6E, 0x67, 0x00, 0x74, 0x65, 0x61, 0x6D, 0x70, 0x6C, 0x61, 0x79, 0x00, 0x31, 0x00, 0x66, 0x72, 0x61, 0x67, 0x6C, 0x69, 0x6D, 0x69, 0x74, 0x00, 0x30, 0x00, 0x74, 0x69, 0x6D, 0x65, 0x6C, 0x69, 0x6D, 0x69, 0x74, 0x00, 0x34, 0x30, 0x00, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x79, 0x00, 0x38, 0x30, 0x30, 0x00, 0x72, 0x61, 0x6E, 0x6B, 0x69, 0x6E, 0x67, 0x6F, 0x6E, 0x00, 0x31, 0x00, 0x00, 0x00, 0x0A, 0x70, 0x6C, 0x61, 0x79, 0x65, 0x72, 0x5F, 0x00, 0x73, 0x63, 0x6F, 0x72, 0x65, 0x5F, 0x00, 0x64, 0x65, 0x61, 0x74, 0x68, 0x73, 0x5F, 0x00, 0x70, 0x69, 0x6E, 0x67, 0x5F, 0x00, 0x74, 0x65, 0x61, 0x6D, 0x5F, 0x00, 0x74, 0x69, 0x6D, 0x65, 0x5F, 0x00, 0x00, 0x4A, 0x6F, 0x65, 0x20, 0x50, 0x6C, 0x61, 0x79, 0x65, 0x72, 0x00, 0x34, 0x00, 0x32, 0x00, 0x37, 0x37, 0x00, 0x30, 0x00, 0x31, 0x38, 0x35, 0x00, 0x4C, 0x33, 0x33, 0x74, 0x20, 0x30, 0x6E, 0x33, 0x00, 0x36, 0x00, 0x32, 0x34, 0x00, 0x36, 0x38, 0x00, 0x31, 0x00, 0x38, 0x32, 0x30, 0x00, 0x52, 0x61, 0x70, 0x74, 0x6F, 0x72, 0x00, 0x31, 0x30, 0x00, 0x32, 0x39, 0x00, 0x32, 0x31, 0x36, 0x00, 0x31, 0x00, 0x36, 0x36, 0x34, 0x00, 0x47, 0x72, 0x38, 0x31, 0x00, 0x38, 0x00, 0x36, 0x00, 0x33, 0x32, 0x37, 0x00, 0x31, 0x00, 0x36, 0x39, 0x37, 0x00, 0x46, 0x6C, 0x75, 0x62, 0x62, 0x65, 0x72, 0x00, 0x31, 0x35, 0x00, 0x32, 0x00, 0x31, 0x37, 0x39, 0x00, 0x30, 0x00, 0x34, 0x38, 0x00, 0x53, 0x61, 0x72, 0x67, 0x65, 0x00, 0x39, 0x00, 0x31, 0x32, 0x00, 0x33, 0x33, 0x37, 0x00, 0x30, 0x00, 0x32, 0x39, 0x36, 0x00, 0x56, 0x6F, 0x69, 0x64, 0x00, 0x32, 0x37, 0x00, 0x32, 0x39, 0x00, 0x34, 0x35, 0x00, 0x30, 0x00, 0x33, 0x35, 0x35, 0x00, 0x72, 0x75, 0x6E, 0x61, 0x77, 0x61, 0x79, 0x00, 0x32, 0x34, 0x00, 0x34, 0x00, 0x31, 0x39, 0x37, 0x00, 0x31, 0x00, 0x34, 0x32, 0x38, 0x00, 0x50, 0x68, 0x33, 0x61, 0x72, 0x00, 0x33, 0x30, 0x00, 0x33, 0x30, 0x00, 0x33, 0x33, 0x39, 0x00, 0x31, 0x00, 0x35, 0x32, 0x35, 0x00, 0x77, 0x68, 0x30, 0x30, 0x74, 0x00, 0x33, 0x31, 0x00, 0x32, 0x38, 0x00, 0x32, 0x36, 0x39, 0x00, 0x31, 0x00, 0x37, 0x37, 0x00, 0x00, 0x02, 0x74, 0x65, 0x61, 0x6D, 0x5F, 0x74, 0x00, 0x73, 0x63, 0x6F, 0x72, 0x65, 0x5F, 0x74, 0x00, 0x61, 0x76, 0x67, 0x70, 0x69, 0x6E, 0x67, 0x5F, 0x74, 0x00, 0x00, 0x52, 0x65, 0x64, 0x00, 0x34, 0x38, 0x37, 0x00, 0x33, 0x33, 0x36, 0x00, 0x42, 0x6C, 0x75, 0x65, 0x00, 0x38, 0x32, 0x00, 0x34, 0x35, 0x38, 0x00 }; - var sbReq = new byte[] { 0x00, 0x09, 0x01, 0xC0, 0xA8, 0x7A, 0xE2, 0x2B, 0x67 }; - var qrClient = QueryReport.V2.Test.MockObject.CreateClient("192.168.122.226", 11111); - var sbClient = ServerBrowser.V2.Test.MockObject.CreateClient(); - - (qrClient as ITestClient).TestReceived(qrReq); - (sbClient as ITestClient).TestReceived(sbReq); - - } - [Fact] - public void SplitSendMessageTest() - { - // Given - var splitedRequests = new List() - { - // send message request - new byte[]{0x00,0x13,0x02,0x4F,0xD1,0xE0,0x1D,0x54,0xC5}, - // natneg message request - new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x00,0x00,0x2C,0xFD} - }; - var compeleteRequest = new byte[] { 0x00, 0x13, 0x02, 0x4F, 0xD1, 0xE0, 0x1D, 0x54, 0xC5, 0xFD, 0xFC, 0x1E, 0x66, 0x6A, 0xB2, 0x00, 0x00, 0x2C, 0xFD }; - // When - foreach (var req in splitedRequests) - { - ((ITestClient)MockObject.SBClient).TestReceived(req); - } - ((ITestClient)MockObject.SBClient).TestReceived(compeleteRequest); - } - [Fact] - public void Gmtest20220613() - { - // Given - var qrRequests = new List() - { - new byte[]{0x09,0x00,0x00,0x00,0x00,0x67,0x6D,0x74,0x65,0x73,0x74,0x00}, - new byte[]{0x03,0xB4,0xA3,0xCC,0x80,0x6C,0x6F,0x63,0x61,0x6C,0x69,0x70,0x30,0x00,0x31,0x39,0x32,0x2E,0x31,0x36,0x38,0x2E,0x30,0x2E,0x31,0x30,0x39,0x00,0x6C,0x6F,0x63,0x61,0x6C,0x70,0x6F,0x72,0x74,0x00,0x36,0x35,0x30,0x30,0x00,0x6E,0x61,0x74,0x6E,0x65,0x67,0x00,0x30,0x00,0x73,0x74,0x61,0x74,0x65,0x63,0x68,0x61,0x6E,0x67,0x65,0x64,0x00,0x33,0x00,0x67,0x61,0x6D,0x65,0x6E,0x61,0x6D,0x65,0x00,0x67,0x6D,0x74,0x65,0x73,0x74,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x69,0x70,0x00,0x30,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x70,0x6F,0x72,0x74,0x00,0x30,0x00,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x00,0x4D,0x79,0x20,0x53,0x65,0x72,0x76,0x65,0x72,0x00,0x67,0x61,0x6D,0x65,0x6D,0x6F,0x64,0x65,0x00,0x6F,0x70,0x65,0x6E,0x73,0x74,0x61,0x67,0x69,0x6E,0x67,0x00,0x67,0x72,0x6F,0x75,0x70,0x69,0x64,0x00,0x33,0x00,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x31,0x00,0x6D,0x61,0x78,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x38,0x00,0x67,0x61,0x6D,0x65,0x76,0x65,0x72,0x00,0x31,0x2E,0x30,0x31,0x00,0x00,0x00,0x01,0x70,0x6C,0x61,0x79,0x65,0x72,0x5F,0x00,0x70,0x69,0x6E,0x67,0x5F,0x00,0x00,0x50,0x65,0x65,0x72,0x50,0x6C,0x61,0x79,0x65,0x72,0x31,0x00,0x30,0x00,0x00,0x00,0x00}, - // new byte[]{0x08,0xB4,0xA3,0xCC,0x80}, - // new byte[] {0x03,0xB4,0xA3,0xCC,0x80,0x6C,0x6F,0x63,0x61,0x6C,0x69,0x70,0x30,0x00,0x31,0x39,0x32,0x2E,0x31,0x36,0x38,0x2E,0x30,0x2E,0x31,0x30,0x39,0x00,0x6C,0x6F,0x63,0x61,0x6C,0x70,0x6F,0x72,0x74,0x00,0x36,0x35,0x30,0x30,0x00,0x6E,0x61,0x74,0x6E,0x65,0x67,0x00,0x30,0x00,0x73,0x74,0x61,0x74,0x65,0x63,0x68,0x61,0x6E,0x67,0x65,0x64,0x00,0x32,0x00,0x67,0x61,0x6D,0x65,0x6E,0x61,0x6D,0x65,0x00,0x67,0x6D,0x74,0x65,0x73,0x74,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x69,0x70,0x00,0x30,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x70,0x6F,0x72,0x74,0x00,0x30,0x00,0x00} - }; - var sb1Requests = new List() - { - new byte[]{0x00,0x5A,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x67,0x6D,0x74,0x65,0x73,0x74,0x00,0x67,0x6D,0x74,0x65,0x73,0x74,0x00,0x29,0x3E,0x7C,0x23,0x43,0x5D,0x68,0x49,0x00,0x5C,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x5C,0x6E,0x75,0x6D,0x77,0x61,0x69,0x74,0x69,0x6E,0x67,0x5C,0x6D,0x61,0x78,0x77,0x61,0x69,0x74,0x69,0x6E,0x67,0x5C,0x6E,0x75,0x6D,0x73,0x65,0x72,0x76,0x65,0x72,0x73,0x5C,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x00,0x00,0x00,0x20} - }; - var sb2Requests = new List() - { - new byte[]{0x00,0x5A,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x67,0x6D,0x74,0x65,0x73,0x74,0x00,0x67,0x6D,0x74,0x65,0x73,0x74,0x00,0x29,0x3E,0x7C,0x23,0x43,0x5D,0x68,0x49,0x00,0x5C,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x5C,0x6E,0x75,0x6D,0x77,0x61,0x69,0x74,0x69,0x6E,0x67,0x5C,0x6D,0x61,0x78,0x77,0x61,0x69,0x74,0x69,0x6E,0x67,0x5C,0x6E,0x75,0x6D,0x73,0x65,0x72,0x76,0x65,0x72,0x73,0x5C,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x00,0x00,0x00,0x20}, - new byte[]{0x00,0x5A,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x67,0x6D,0x74,0x65,0x73,0x74,0x00,0x67,0x6D,0x74,0x65,0x73,0x74,0x00,0x24,0x68,0x41,0x78,0x23,0x39,0x59,0x70,0x00,0x5C,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x5C,0x6E,0x75,0x6D,0x77,0x61,0x69,0x74,0x69,0x6E,0x67,0x5C,0x6D,0x61,0x78,0x77,0x61,0x69,0x74,0x69,0x6E,0x67,0x5C,0x6E,0x75,0x6D,0x73,0x65,0x72,0x76,0x65,0x72,0x73,0x5C,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x00,0x00,0x00,0x20}, - new byte[]{0x00,0x5E,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x67,0x6D,0x74,0x65,0x73,0x74,0x00,0x67,0x6D,0x74,0x65,0x73,0x74,0x00,0x28,0x76,0x7D,0x30,0x33,0x74,0x35,0x52,0x67,0x72,0x6F,0x75,0x70,0x69,0x64,0x3D,0x33,0x00,0x5C,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x5C,0x67,0x61,0x6D,0x65,0x6D,0x6F,0x64,0x65,0x5C,0x67,0x61,0x6D,0x65,0x76,0x65,0x72,0x5C,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x5C,0x6D,0x61,0x78,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x00,0x00,0x00,0x04}, - new byte[]{0x00,0x5E,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x67,0x6D,0x74,0x65,0x73,0x74,0x00,0x67,0x6D,0x74,0x65,0x73,0x74,0x00,0x2D,0x42,0x4C,0x67,0x32,0x73,0x28,0x26,0x67,0x72,0x6F,0x75,0x70,0x69,0x64,0x3D,0x33,0x00,0x5C,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x5C,0x67,0x61,0x6D,0x65,0x6D,0x6F,0x64,0x65,0x5C,0x67,0x61,0x6D,0x65,0x76,0x65,0x72,0x5C,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x5C,0x6D,0x61,0x78,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x00,0x00,0x00,0x04} - }; - foreach (var qrReq in qrRequests) - { - ((ITestClient)MockObject.QRClient).TestReceived(qrReq); - } - - foreach (var sbReq in sb2Requests) - { - ((ITestClient)MockObject.SBClient).TestReceived(sbReq); - } - } - /// - /// Fixed 20221108 - /// - [Fact] - public void Anno1701Date20220620() - { - // because when search on redis, redis require the server ip and port as key words, - // the ip and port in qr should match when sb execute ServerInfoRequest - // therefore, we create client based on IP 91.43.50.186:21701 to test qr and sb - var qrClient = QueryReport.V2.Test.MockObject.CreateClient("91.43.50.186", 21701); - var sbClient = MockObject.CreateClient(); - var qrRequests = new List() - { - // avaliable check - new byte[] {0x09,0x00,0x00,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}, - // heart beat - new byte[] {0x03,0x1D,0x55,0xCC,0xCA,0x6C,0x6F,0x63,0x61,0x6C,0x69,0x70,0x30,0x00,0x31,0x39,0x32,0x2E,0x31,0x36,0x38,0x2E,0x30,0x2E,0x38,0x30,0x00,0x6C,0x6F,0x63,0x61,0x6C,0x70,0x6F,0x72,0x74,0x00,0x32,0x31,0x37,0x30,0x31,0x00,0x6E,0x61,0x74,0x6E,0x65,0x67,0x00,0x31,0x00,0x73,0x74,0x61,0x74,0x65,0x63,0x68,0x61,0x6E,0x67,0x65,0x64,0x00,0x33,0x00,0x67,0x61,0x6D,0x65,0x6E,0x61,0x6D,0x65,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x69,0x70,0x00,0x30,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x70,0x6F,0x72,0x74,0x00,0x30,0x00,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x00,0x28,0x75,0x6E,0x6B,0x6E,0x6F,0x77,0x6E,0x20,0x67,0x61,0x6D,0x65,0x29,0x00,0x67,0x61,0x6D,0x65,0x6D,0x6F,0x64,0x65,0x00,0x6F,0x70,0x65,0x6E,0x73,0x74,0x61,0x67,0x69,0x6E,0x67,0x00,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x31,0x00,0x6D,0x61,0x78,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x34,0x00,0x67,0x61,0x6D,0x65,0x76,0x65,0x72,0x00,0x32,0x31,0x39,0x30,0x33,0x00,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x00,0x52,0x61,0x6E,0x64,0x6F,0x6D,0x20,0x6D,0x61,0x70,0x00,0x67,0x61,0x6D,0x65,0x74,0x79,0x70,0x65,0x00,0x45,0x61,0x73,0x79,0x00,0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64,0x00,0x30,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x6F,0x70,0x74,0x69,0x6F,0x6E,0x73,0x00,0x33,0x37,0x37,0x35,0x36,0x33,0x30,0x37,0x36,0x00,0x6E,0x75,0x6D,0x61,0x69,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x00,0x6F,0x70,0x65,0x6E,0x73,0x6C,0x6F,0x74,0x73,0x00,0x00,0x67,0x61,0x6D,0x65,0x76,0x61,0x72,0x69,0x61,0x6E,0x74,0x00,0x50,0x76,0x50,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x77,0x69,0x6E,0x63,0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x00,0x30,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x75,0x73,0x65,0x72,0x63,0x6F,0x6E,0x74,0x65,0x6E,0x74,0x5F,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x00,0x00,0x00,0x00,0x01,0x70,0x6C,0x61,0x79,0x65,0x72,0x5F,0x00,0x70,0x69,0x6E,0x67,0x5F,0x00,0x70,0x69,0x6E,0x67,0x5F,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x5F,0x32,0x32,0x30,0x00,0x30,0x00,0x30,0x00,0x00,0x01,0x00}, - new byte[] {0x03,0x1D,0x55,0xCC,0xCA,0x6C,0x6F,0x63,0x61,0x6C,0x69,0x70,0x30,0x00,0x31,0x39,0x32,0x2E,0x31,0x36,0x38,0x2E,0x30,0x2E,0x38,0x30,0x00,0x6C,0x6F,0x63,0x61,0x6C,0x70,0x6F,0x72,0x74,0x00,0x32,0x31,0x37,0x30,0x31,0x00,0x6E,0x61,0x74,0x6E,0x65,0x67,0x00,0x31,0x00,0x73,0x74,0x61,0x74,0x65,0x63,0x68,0x61,0x6E,0x67,0x65,0x64,0x00,0x33,0x00,0x67,0x61,0x6D,0x65,0x6E,0x61,0x6D,0x65,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x69,0x70,0x00,0x30,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x70,0x6F,0x72,0x74,0x00,0x30,0x00,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x00,0x28,0x75,0x6E,0x6B,0x6E,0x6F,0x77,0x6E,0x20,0x67,0x61,0x6D,0x65,0x29,0x00,0x67,0x61,0x6D,0x65,0x6D,0x6F,0x64,0x65,0x00,0x6F,0x70,0x65,0x6E,0x73,0x74,0x61,0x67,0x69,0x6E,0x67,0x00,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x31,0x00,0x6D,0x61,0x78,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x34,0x00,0x67,0x61,0x6D,0x65,0x76,0x65,0x72,0x00,0x32,0x31,0x39,0x30,0x33,0x00,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x00,0x52,0x61,0x6E,0x64,0x6F,0x6D,0x20,0x6D,0x61,0x70,0x00,0x67,0x61,0x6D,0x65,0x74,0x79,0x70,0x65,0x00,0x45,0x61,0x73,0x79,0x00,0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64,0x00,0x30,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x6F,0x70,0x74,0x69,0x6F,0x6E,0x73,0x00,0x33,0x37,0x37,0x35,0x36,0x33,0x30,0x37,0x36,0x00,0x6E,0x75,0x6D,0x61,0x69,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x00,0x6F,0x70,0x65,0x6E,0x73,0x6C,0x6F,0x74,0x73,0x00,0x00,0x67,0x61,0x6D,0x65,0x76,0x61,0x72,0x69,0x61,0x6E,0x74,0x00,0x50,0x76,0x50,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x77,0x69,0x6E,0x63,0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x00,0x30,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x75,0x73,0x65,0x72,0x63,0x6F,0x6E,0x74,0x65,0x6E,0x74,0x5F,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x00,0x00,0x00,0x00,0x01,0x70,0x6C,0x61,0x79,0x65,0x72,0x5F,0x00,0x70,0x69,0x6E,0x67,0x5F,0x00,0x70,0x69,0x6E,0x67,0x5F,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x5F,0x32,0x32,0x30,0x00,0x30,0x00,0x30,0x00,0x00,0x01,0x00}, - new byte[] {0x03,0x1D,0x55,0xCC,0xCA,0x6C,0x6F,0x63,0x61,0x6C,0x69,0x70,0x30,0x00,0x31,0x39,0x32,0x2E,0x31,0x36,0x38,0x2E,0x30,0x2E,0x38,0x30,0x00,0x6C,0x6F,0x63,0x61,0x6C,0x70,0x6F,0x72,0x74,0x00,0x32,0x31,0x37,0x30,0x31,0x00,0x6E,0x61,0x74,0x6E,0x65,0x67,0x00,0x31,0x00,0x73,0x74,0x61,0x74,0x65,0x63,0x68,0x61,0x6E,0x67,0x65,0x64,0x00,0x31,0x00,0x67,0x61,0x6D,0x65,0x6E,0x61,0x6D,0x65,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x69,0x70,0x00,0x30,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x70,0x6F,0x72,0x74,0x00,0x30,0x00,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x00,0x28,0x75,0x6E,0x6B,0x6E,0x6F,0x77,0x6E,0x20,0x67,0x61,0x6D,0x65,0x29,0x00,0x67,0x61,0x6D,0x65,0x6D,0x6F,0x64,0x65,0x00,0x6F,0x70,0x65,0x6E,0x73,0x74,0x61,0x67,0x69,0x6E,0x67,0x00,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x31,0x00,0x6D,0x61,0x78,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x34,0x00,0x67,0x61,0x6D,0x65,0x76,0x65,0x72,0x00,0x32,0x31,0x39,0x30,0x33,0x00,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x00,0x52,0x61,0x6E,0x64,0x6F,0x6D,0x20,0x6D,0x61,0x70,0x00,0x67,0x61,0x6D,0x65,0x74,0x79,0x70,0x65,0x00,0x45,0x61,0x73,0x79,0x00,0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64,0x00,0x30,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x6F,0x70,0x74,0x69,0x6F,0x6E,0x73,0x00,0x31,0x30,0x39,0x31,0x32,0x37,0x36,0x32,0x30,0x00,0x6E,0x75,0x6D,0x61,0x69,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x30,0x00,0x6F,0x70,0x65,0x6E,0x73,0x6C,0x6F,0x74,0x73,0x00,0x34,0x00,0x67,0x61,0x6D,0x65,0x76,0x61,0x72,0x69,0x61,0x6E,0x74,0x00,0x50,0x76,0x50,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x77,0x69,0x6E,0x63,0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x00,0x30,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x75,0x73,0x65,0x72,0x63,0x6F,0x6E,0x74,0x65,0x6E,0x74,0x5F,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x00,0x00,0x00,0x00,0x01,0x70,0x6C,0x61,0x79,0x65,0x72,0x5F,0x00,0x70,0x69,0x6E,0x67,0x5F,0x00,0x70,0x69,0x6E,0x67,0x5F,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x5F,0x32,0x32,0x30,0x00,0x30,0x00,0x30,0x00,0x00,0x01,0x00}, - new byte[] {0x03,0x1D,0x55,0xCC,0xCA,0x6C,0x6F,0x63,0x61,0x6C,0x69,0x70,0x30,0x00,0x31,0x39,0x32,0x2E,0x31,0x36,0x38,0x2E,0x30,0x2E,0x38,0x30,0x00,0x6C,0x6F,0x63,0x61,0x6C,0x70,0x6F,0x72,0x74,0x00,0x32,0x31,0x37,0x30,0x31,0x00,0x6E,0x61,0x74,0x6E,0x65,0x67,0x00,0x31,0x00,0x73,0x74,0x61,0x74,0x65,0x63,0x68,0x61,0x6E,0x67,0x65,0x64,0x00,0x31,0x00,0x67,0x61,0x6D,0x65,0x6E,0x61,0x6D,0x65,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x69,0x70,0x00,0x30,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x70,0x6F,0x72,0x74,0x00,0x30,0x00,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x00,0x28,0x75,0x6E,0x6B,0x6E,0x6F,0x77,0x6E,0x20,0x67,0x61,0x6D,0x65,0x29,0x00,0x67,0x61,0x6D,0x65,0x6D,0x6F,0x64,0x65,0x00,0x6F,0x70,0x65,0x6E,0x73,0x74,0x61,0x67,0x69,0x6E,0x67,0x00,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x31,0x00,0x6D,0x61,0x78,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x34,0x00,0x67,0x61,0x6D,0x65,0x76,0x65,0x72,0x00,0x32,0x31,0x39,0x30,0x33,0x00,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x00,0x52,0x61,0x6E,0x64,0x6F,0x6D,0x20,0x6D,0x61,0x70,0x00,0x67,0x61,0x6D,0x65,0x74,0x79,0x70,0x65,0x00,0x45,0x61,0x73,0x79,0x00,0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64,0x00,0x30,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x6F,0x70,0x74,0x69,0x6F,0x6E,0x73,0x00,0x31,0x30,0x39,0x31,0x32,0x37,0x36,0x32,0x30,0x00,0x6E,0x75,0x6D,0x61,0x69,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x30,0x00,0x6F,0x70,0x65,0x6E,0x73,0x6C,0x6F,0x74,0x73,0x00,0x34,0x00,0x67,0x61,0x6D,0x65,0x76,0x61,0x72,0x69,0x61,0x6E,0x74,0x00,0x50,0x76,0x50,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x77,0x69,0x6E,0x63,0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x00,0x30,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x75,0x73,0x65,0x72,0x63,0x6F,0x6E,0x74,0x65,0x6E,0x74,0x5F,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x00,0x00,0x00,0x00,0x01,0x70,0x6C,0x61,0x79,0x65,0x72,0x5F,0x00,0x70,0x69,0x6E,0x67,0x5F,0x00,0x70,0x69,0x6E,0x67,0x5F,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x5F,0x32,0x32,0x30,0x00,0x30,0x00,0x30,0x00,0x00,0x01,0x00}, - new byte[] {0x03,0x1D,0x55,0xCC,0xCA,0x6C,0x6F,0x63,0x61,0x6C,0x69,0x70,0x30,0x00,0x31,0x39,0x32,0x2E,0x31,0x36,0x38,0x2E,0x30,0x2E,0x38,0x30,0x00,0x6C,0x6F,0x63,0x61,0x6C,0x70,0x6F,0x72,0x74,0x00,0x32,0x31,0x37,0x30,0x31,0x00,0x6E,0x61,0x74,0x6E,0x65,0x67,0x00,0x31,0x00,0x67,0x61,0x6D,0x65,0x6E,0x61,0x6D,0x65,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x69,0x70,0x00,0x30,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x70,0x6F,0x72,0x74,0x00,0x30,0x00,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x00,0x28,0x75,0x6E,0x6B,0x6E,0x6F,0x77,0x6E,0x20,0x67,0x61,0x6D,0x65,0x29,0x00,0x67,0x61,0x6D,0x65,0x6D,0x6F,0x64,0x65,0x00,0x6F,0x70,0x65,0x6E,0x73,0x74,0x61,0x67,0x69,0x6E,0x67,0x00,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x31,0x00,0x6D,0x61,0x78,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x34,0x00,0x67,0x61,0x6D,0x65,0x76,0x65,0x72,0x00,0x32,0x31,0x39,0x30,0x33,0x00,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x00,0x52,0x61,0x6E,0x64,0x6F,0x6D,0x20,0x6D,0x61,0x70,0x00,0x67,0x61,0x6D,0x65,0x74,0x79,0x70,0x65,0x00,0x45,0x61,0x73,0x79,0x00,0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64,0x00,0x30,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x6F,0x70,0x74,0x69,0x6F,0x6E,0x73,0x00,0x31,0x30,0x39,0x31,0x32,0x37,0x36,0x32,0x30,0x00,0x6E,0x75,0x6D,0x61,0x69,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x30,0x00,0x6F,0x70,0x65,0x6E,0x73,0x6C,0x6F,0x74,0x73,0x00,0x34,0x00,0x67,0x61,0x6D,0x65,0x76,0x61,0x72,0x69,0x61,0x6E,0x74,0x00,0x50,0x76,0x50,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x77,0x69,0x6E,0x63,0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x00,0x30,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x75,0x73,0x65,0x72,0x63,0x6F,0x6E,0x74,0x65,0x6E,0x74,0x5F,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x00,0x00,0x00,0x00,0x01,0x70,0x6C,0x61,0x79,0x65,0x72,0x5F,0x00,0x70,0x69,0x6E,0x67,0x5F,0x00,0x70,0x69,0x6E,0x67,0x5F,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x5F,0x32,0x32,0x30,0x00,0x30,0x00,0x30,0x00,0x00,0x01,0x00}, - new byte[] {0x03,0x1D,0x55,0xCC,0xCA,0x6C,0x6F,0x63,0x61,0x6C,0x69,0x70,0x30,0x00,0x31,0x39,0x32,0x2E,0x31,0x36,0x38,0x2E,0x30,0x2E,0x38,0x30,0x00,0x6C,0x6F,0x63,0x61,0x6C,0x70,0x6F,0x72,0x74,0x00,0x32,0x31,0x37,0x30,0x31,0x00,0x6E,0x61,0x74,0x6E,0x65,0x67,0x00,0x31,0x00,0x67,0x61,0x6D,0x65,0x6E,0x61,0x6D,0x65,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x69,0x70,0x00,0x30,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x70,0x6F,0x72,0x74,0x00,0x30,0x00,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x00,0x28,0x75,0x6E,0x6B,0x6E,0x6F,0x77,0x6E,0x20,0x67,0x61,0x6D,0x65,0x29,0x00,0x67,0x61,0x6D,0x65,0x6D,0x6F,0x64,0x65,0x00,0x6F,0x70,0x65,0x6E,0x73,0x74,0x61,0x67,0x69,0x6E,0x67,0x00,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x31,0x00,0x6D,0x61,0x78,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x34,0x00,0x67,0x61,0x6D,0x65,0x76,0x65,0x72,0x00,0x32,0x31,0x39,0x30,0x33,0x00,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x00,0x52,0x61,0x6E,0x64,0x6F,0x6D,0x20,0x6D,0x61,0x70,0x00,0x67,0x61,0x6D,0x65,0x74,0x79,0x70,0x65,0x00,0x45,0x61,0x73,0x79,0x00,0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64,0x00,0x30,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x6F,0x70,0x74,0x69,0x6F,0x6E,0x73,0x00,0x31,0x30,0x39,0x31,0x32,0x37,0x36,0x32,0x30,0x00,0x6E,0x75,0x6D,0x61,0x69,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x30,0x00,0x6F,0x70,0x65,0x6E,0x73,0x6C,0x6F,0x74,0x73,0x00,0x34,0x00,0x67,0x61,0x6D,0x65,0x76,0x61,0x72,0x69,0x61,0x6E,0x74,0x00,0x50,0x76,0x50,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x77,0x69,0x6E,0x63,0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x00,0x30,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x75,0x73,0x65,0x72,0x63,0x6F,0x6E,0x74,0x65,0x6E,0x74,0x5F,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x00,0x00,0x00,0x00,0x01,0x70,0x6C,0x61,0x79,0x65,0x72,0x5F,0x00,0x70,0x69,0x6E,0x67,0x5F,0x00,0x70,0x69,0x6E,0x67,0x5F,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x5F,0x32,0x32,0x30,0x00,0x30,0x00,0x30,0x00,0x00,0x01,0x00}, - new byte[] {0x03,0x1D,0x55,0xCC,0xCA,0x6C,0x6F,0x63,0x61,0x6C,0x69,0x70,0x30,0x00,0x31,0x39,0x32,0x2E,0x31,0x36,0x38,0x2E,0x30,0x2E,0x38,0x30,0x00,0x6C,0x6F,0x63,0x61,0x6C,0x70,0x6F,0x72,0x74,0x00,0x32,0x31,0x37,0x30,0x31,0x00,0x6E,0x61,0x74,0x6E,0x65,0x67,0x00,0x31,0x00,0x67,0x61,0x6D,0x65,0x6E,0x61,0x6D,0x65,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x69,0x70,0x00,0x30,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x70,0x6F,0x72,0x74,0x00,0x30,0x00,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x00,0x28,0x75,0x6E,0x6B,0x6E,0x6F,0x77,0x6E,0x20,0x67,0x61,0x6D,0x65,0x29,0x00,0x67,0x61,0x6D,0x65,0x6D,0x6F,0x64,0x65,0x00,0x6F,0x70,0x65,0x6E,0x73,0x74,0x61,0x67,0x69,0x6E,0x67,0x00,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x31,0x00,0x6D,0x61,0x78,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x34,0x00,0x67,0x61,0x6D,0x65,0x76,0x65,0x72,0x00,0x32,0x31,0x39,0x30,0x33,0x00,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x00,0x52,0x61,0x6E,0x64,0x6F,0x6D,0x20,0x6D,0x61,0x70,0x00,0x67,0x61,0x6D,0x65,0x74,0x79,0x70,0x65,0x00,0x45,0x61,0x73,0x79,0x00,0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64,0x00,0x30,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x6F,0x70,0x74,0x69,0x6F,0x6E,0x73,0x00,0x31,0x30,0x39,0x31,0x32,0x37,0x36,0x32,0x30,0x00,0x6E,0x75,0x6D,0x61,0x69,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x30,0x00,0x6F,0x70,0x65,0x6E,0x73,0x6C,0x6F,0x74,0x73,0x00,0x34,0x00,0x67,0x61,0x6D,0x65,0x76,0x61,0x72,0x69,0x61,0x6E,0x74,0x00,0x50,0x76,0x50,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x77,0x69,0x6E,0x63,0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x00,0x30,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x75,0x73,0x65,0x72,0x63,0x6F,0x6E,0x74,0x65,0x6E,0x74,0x5F,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x00,0x00,0x00,0x00,0x01,0x70,0x6C,0x61,0x79,0x65,0x72,0x5F,0x00,0x70,0x69,0x6E,0x67,0x5F,0x00,0x70,0x69,0x6E,0x67,0x5F,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x5F,0x32,0x32,0x30,0x00,0x30,0x00,0x30,0x00,0x00,0x01,0x00}, - new byte[] {0x03,0x1D,0x55,0xCC,0xCA,0x6C,0x6F,0x63,0x61,0x6C,0x69,0x70,0x30,0x00,0x31,0x39,0x32,0x2E,0x31,0x36,0x38,0x2E,0x30,0x2E,0x38,0x30,0x00,0x6C,0x6F,0x63,0x61,0x6C,0x70,0x6F,0x72,0x74,0x00,0x32,0x31,0x37,0x30,0x31,0x00,0x6E,0x61,0x74,0x6E,0x65,0x67,0x00,0x31,0x00,0x67,0x61,0x6D,0x65,0x6E,0x61,0x6D,0x65,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x69,0x70,0x00,0x30,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x70,0x6F,0x72,0x74,0x00,0x30,0x00,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x00,0x28,0x75,0x6E,0x6B,0x6E,0x6F,0x77,0x6E,0x20,0x67,0x61,0x6D,0x65,0x29,0x00,0x67,0x61,0x6D,0x65,0x6D,0x6F,0x64,0x65,0x00,0x6F,0x70,0x65,0x6E,0x73,0x74,0x61,0x67,0x69,0x6E,0x67,0x00,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x31,0x00,0x6D,0x61,0x78,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x34,0x00,0x67,0x61,0x6D,0x65,0x76,0x65,0x72,0x00,0x32,0x31,0x39,0x30,0x33,0x00,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x00,0x52,0x61,0x6E,0x64,0x6F,0x6D,0x20,0x6D,0x61,0x70,0x00,0x67,0x61,0x6D,0x65,0x74,0x79,0x70,0x65,0x00,0x45,0x61,0x73,0x79,0x00,0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64,0x00,0x30,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x6F,0x70,0x74,0x69,0x6F,0x6E,0x73,0x00,0x31,0x30,0x39,0x31,0x32,0x37,0x36,0x32,0x30,0x00,0x6E,0x75,0x6D,0x61,0x69,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x30,0x00,0x6F,0x70,0x65,0x6E,0x73,0x6C,0x6F,0x74,0x73,0x00,0x34,0x00,0x67,0x61,0x6D,0x65,0x76,0x61,0x72,0x69,0x61,0x6E,0x74,0x00,0x50,0x76,0x50,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x77,0x69,0x6E,0x63,0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x00,0x30,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x75,0x73,0x65,0x72,0x63,0x6F,0x6E,0x74,0x65,0x6E,0x74,0x5F,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x00,0x00,0x00,0x00,0x01,0x70,0x6C,0x61,0x79,0x65,0x72,0x5F,0x00,0x70,0x69,0x6E,0x67,0x5F,0x00,0x70,0x69,0x6E,0x67,0x5F,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x5F,0x32,0x32,0x30,0x00,0x30,0x00,0x30,0x00,0x00,0x01,0x00}, - //client message - new byte[] {0xFE,0xFD,0x03,0x1D,0x55,0xCC,0xCA,0x54,0x54,0x54,0x00,0x00,0x5B,0x2B,0x32,0xBA,0x00,0x00,0x00,0x00,0xC5,0x54,0x00,0x00}, - // keep alive - new byte[] {0x08,0x1D,0x55,0xCC,0xCA} - }; - - var sbRequests = new List() - { - new byte[] {0x00,0x9A,0x00,0x01,0x03,0x8F,0x55,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x44,0x3A,0x40,0x6F,0x29,0x4F,0x6B,0x68,0x67,0x72,0x6F,0x75,0x70,0x69,0x64,0x20,0x69,0x73,0x20,0x6E,0x75,0x6C,0x6C,0x00,0x5C,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x5C,0x67,0x61,0x6D,0x65,0x6D,0x6F,0x64,0x65,0x5C,0x67,0x61,0x6D,0x65,0x76,0x65,0x72,0x5C,0x67,0x61,0x6D,0x65,0x74,0x79,0x70,0x65,0x5C,0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64,0x5C,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x5C,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x5C,0x6E,0x75,0x6D,0x61,0x69,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x5C,0x6F,0x70,0x65,0x6E,0x73,0x6C,0x6F,0x74,0x73,0x5C,0x67,0x61,0x6D,0x65,0x76,0x61,0x72,0x69,0x61,0x6E,0x74,0x00,0x00,0x00,0x00,0x04}, - new byte[] {0x00,0x9A,0x00,0x01,0x03,0x8F,0x55,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x41,0x48,0x6C,0x3D,0x27,0x6C,0x68,0x49,0x67,0x72,0x6F,0x75,0x70,0x69,0x64,0x20,0x69,0x73,0x20,0x6E,0x75,0x6C,0x6C,0x00,0x5C,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x5C,0x67,0x61,0x6D,0x65,0x6D,0x6F,0x64,0x65,0x5C,0x67,0x61,0x6D,0x65,0x76,0x65,0x72,0x5C,0x67,0x61,0x6D,0x65,0x74,0x79,0x70,0x65,0x5C,0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64,0x5C,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x5C,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x5C,0x6E,0x75,0x6D,0x61,0x69,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x5C,0x6F,0x70,0x65,0x6E,0x73,0x6C,0x6F,0x74,0x73,0x5C,0x67,0x61,0x6D,0x65,0x76,0x61,0x72,0x69,0x61,0x6E,0x74,0x00,0x00,0x00,0x00,0x04}, - new byte[] {0x00,0x9A,0x00,0x01,0x03,0x8F,0x55,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x54,0x73,0x46,0x68,0x48,0x6A,0x76,0x51,0x67,0x72,0x6F,0x75,0x70,0x69,0x64,0x20,0x69,0x73,0x20,0x6E,0x75,0x6C,0x6C,0x00,0x5C,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x5C,0x67,0x61,0x6D,0x65,0x6D,0x6F,0x64,0x65,0x5C,0x67,0x61,0x6D,0x65,0x76,0x65,0x72,0x5C,0x67,0x61,0x6D,0x65,0x74,0x79,0x70,0x65,0x5C,0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64,0x5C,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x5C,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x5C,0x6E,0x75,0x6D,0x61,0x69,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x5C,0x6F,0x70,0x65,0x6E,0x73,0x6C,0x6F,0x74,0x73,0x5C,0x67,0x61,0x6D,0x65,0x76,0x61,0x72,0x69,0x61,0x6E,0x74,0x00,0x00,0x00,0x00,0x04}, - //! error occur in this request - new byte[] {0x00,0x09,0x01,0x5B,0x2B,0x32,0xBA,0x54,0xC5}, - // natneg request - new byte[] {0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x00,0x00,0x17,0x31} - }; - - foreach (var qrReq in qrRequests) - { - ((ITestClient)qrClient).TestReceived(qrReq); - } - - foreach (var sbReq in sbRequests) - { - ((ITestClient)sbClient).TestReceived(sbReq); - } - } - [Fact] - public void Anno1701Date20221104() - { - var qrClient1 = QueryReport.V2.Test.MockObject.CreateClient("79.209.224.29", 21701); - var qrClient2 = QueryReport.V2.Test.MockObject.CreateClient("31.18.120.193", 21701); - var sbClient1 = ServerBrowser.V2.Test.MockObject.CreateClient("79.209.224.29", 45340); - var sbclient2 = ServerBrowser.V2.Test.MockObject.CreateClient("31.18.120.193", 50587); - var requests = new List>(){ - new KeyValuePair("qr1",new byte[] {0x09,0x00,0x00,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x0}), - new KeyValuePair("qr1",new byte[] {0x03,0x98,0x92,0x25,0xA0,0x6C,0x6F,0x63,0x61,0x6C,0x69,0x70,0x30,0x00,0x31,0x39,0x32,0x2E,0x31,0x36,0x38,0x2E,0x30,0x2E,0x35,0x30,0x00,0x6C,0x6F,0x63,0x61,0x6C,0x69,0x70,0x31,0x00,0x31,0x39,0x32,0x2E,0x31,0x36,0x38,0x2E,0x31,0x32,0x32,0x2E,0x31,0x00,0x6C,0x6F,0x63,0x61,0x6C,0x70,0x6F,0x72,0x74,0x00,0x32,0x31,0x37,0x30,0x31,0x00,0x6E,0x61,0x74,0x6E,0x65,0x67,0x00,0x31,0x00,0x73,0x74,0x61,0x74,0x65,0x63,0x68,0x61,0x6E,0x67,0x65,0x64,0x00,0x33,0x00,0x67,0x61,0x6D,0x65,0x6E,0x61,0x6D,0x65,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x69,0x70,0x00,0x30,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x70,0x6F,0x72,0x74,0x00,0x30,0x00,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x00,0x28,0x75,0x6E,0x6B,0x6E,0x6F,0x77,0x6E,0x20,0x67,0x61,0x6D,0x65,0x29,0x00,0x67,0x61,0x6D,0x65,0x6D,0x6F,0x64,0x65,0x00,0x6F,0x70,0x65,0x6E,0x73,0x74,0x61,0x67,0x69,0x6E,0x67,0x00,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x31,0x00,0x6D,0x61,0x78,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x34,0x00,0x67,0x61,0x6D,0x65,0x76,0x65,0x72,0x00,0x32,0x31,0x39,0x30,0x33,0x00,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x00,0x52,0x61,0x6E,0x64,0x6F,0x6D,0x20,0x6D,0x61,0x70,0x00,0x67,0x61,0x6D,0x65,0x74,0x79,0x70,0x65,0x00,0x45,0x61,0x73,0x79,0x00,0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64,0x00,0x30,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x6F,0x70,0x74,0x69,0x6F,0x6E,0x73,0x00,0x33,0x36,0x39,0x31,0x37,0x34,0x34,0x36,0x38,0x00,0x6E,0x75,0x6D,0x61,0x69,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x00,0x6F,0x70,0x65,0x6E,0x73,0x6C,0x6F,0x74,0x73,0x00,0x00,0x67,0x61,0x6D,0x65,0x76,0x61,0x72,0x69,0x61,0x6E,0x74,0x00,0x50,0x76,0x50,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x77,0x69,0x6E,0x63,0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x00,0x30,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x75,0x73,0x65,0x72,0x63,0x6F,0x6E,0x74,0x65,0x6E,0x74,0x5F,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x00,0x00,0x00,0x00,0x01,0x70,0x6C,0x61,0x79,0x65,0x72,0x5F,0x00,0x70,0x69,0x6E,0x67,0x5F,0x00,0x70,0x69,0x6E,0x67,0x5F,0x00,0x00,0x73,0x70,0x6F,0x72,0x65,0x73,0x69,0x72,0x69,0x75,0x73,0x00,0x30,0x00,0x30,0x00,0x00,0x01,0x00}), - new KeyValuePair("sb1",new byte[] {0x00,0x9A,0x00,0x01,0x03,0x8F,0x55,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x52,0x63,0x58,0x3B,0x4D,0x28,0x7B,0x47,0x67,0x72,0x6F,0x75,0x70,0x69,0x64,0x20,0x69,0x73,0x20,0x6E,0x75,0x6C,0x6C,0x00,0x5C,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x5C,0x67,0x61,0x6D,0x65,0x6D,0x6F,0x64,0x65,0x5C,0x67,0x61,0x6D,0x65,0x76,0x65,0x72,0x5C,0x67,0x61,0x6D,0x65,0x74,0x79,0x70,0x65,0x5C,0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64,0x5C,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x5C,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x5C,0x6E,0x75,0x6D,0x61,0x69,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x5C,0x6F,0x70,0x65,0x6E,0x73,0x6C,0x6F,0x74,0x73,0x5C,0x67,0x61,0x6D,0x65,0x76,0x61,0x72,0x69,0x61,0x6E,0x74,0x00,0x00,0x00,0x00,0x04}), - new KeyValuePair("qr2",new byte[] {0x07,0x98,0x92,0x25,0xA0,0x00,0x00,0x00,0x00}), - - }; - } - } -} diff --git a/src/Servers/ServerBrowser/test/V2/MockObject.cs b/src/Servers/ServerBrowser/test/V2/MockObject.cs deleted file mode 100644 index 78a4d16af..000000000 --- a/src/Servers/ServerBrowser/test/V2/MockObject.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Net; -using Moq; -using UniSpy.Server.ServerBrowser.V2.Application; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.ServerBrowser.V2.Test -{ - public static class MockObject - { - public static IClient QRClient = QueryReport.V2.Test.MockObject.CreateClient(); - public static IClient SBClient = CreateClient(); - - public static Client CreateClient(string ipAddress = "192.168.1.2", int port = 9999) - { - var managerMock = new Mock(); - var connectionMock = new Mock(); - connectionMock.Setup(s => s.RemoteIPEndPoint).Returns(new IPEndPoint(IPAddress.Parse(ipAddress), port)); - connectionMock.Setup(s => s.Manager).Returns(managerMock.Object); - connectionMock.Setup(s => s.ConnectionType).Returns(NetworkConnectionType.Tcp); - var serverMock = new ServerBrowser.V2.Application.Server(managerMock.Object); - - return new Client(connectionMock.Object, serverMock); - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/test/V2/PeerRoomTest.cs b/src/Servers/ServerBrowser/test/V2/PeerRoomTest.cs deleted file mode 100644 index d4f4c04b7..000000000 --- a/src/Servers/ServerBrowser/test/V2/PeerRoomTest.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using UniSpy.Server.QueryReport.Aggregate.Redis.Channel; -using Xunit; - -namespace UniSpy.Server.ServerBrowser.Test.V2 -{ - public class PeerRoomTest - { - [Fact] - public void TestName() - { - var info = new ChannelInfo() - { - PreviousJoinedChannel = "", - ServerId = Guid.NewGuid(), - Name = "#GPG!622" - }; - QueryReport.Application.StorageOperation.UpdateChannel(info); - } - } -} \ No newline at end of file diff --git a/src/Servers/ServerBrowser/test/V2/RequestTest.cs b/src/Servers/ServerBrowser/test/V2/RequestTest.cs deleted file mode 100644 index 9ccf8ddde..000000000 --- a/src/Servers/ServerBrowser/test/V2/RequestTest.cs +++ /dev/null @@ -1,36 +0,0 @@ -using UniSpy.Server.ServerBrowser.V2.Enumerate; -using UniSpy.Server.ServerBrowser.V2.Contract.Request; -using Xunit; - -namespace UniSpy.Server.ServerBrowser.V2.Test -{ - public class RequestTest - { - [Fact] - public void ServerListTest() - { - var raw = new byte[]{0x00, 0x55, - 0x00, //command name - 0x01, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x67, 0x6d, 0x74, 0x65, 0x73, 0x74, 0x00, - 0x67, 0x6d, 0x74, 0x65, 0x73, 0x74, 0x00, 0x6e, - 0x29, 0x29, 0x34, 0x31, 0x58, 0x4d, 0x36, 0x00, - 0x5c, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, - 0x65, 0x5c, 0x67, 0x61, 0x6d, 0x65, 0x74, 0x79, - 0x70, 0x65, 0x5c, 0x6d, 0x61, 0x70, 0x6e, 0x61, - 0x6d, 0x65, 0x5c, 0x6e, 0x75, 0x6d, 0x70, 0x6c, - 0x61, 0x79, 0x65, 0x72, 0x73, 0x5c, 0x6d, 0x61, - 0x78, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, - 0x00, 0x00, 0x00, 0x00, 0x00}; - var request = new ServerListRequest(raw); - request.Parse(); - Assert.Equal(RequestType.ServerListRequest, request.CommandName); - - raw = new byte[] { 0x00, 0x58, - 0x00, - 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6d, 0x74, 0x65, 0x73, 0x74, 0x00, 0x67, 0x6d, 0x74, 0x65, 0x73, 0x74, 0x00, 0x42, 0x46, 0x5d, 0x6c, 0x6b, 0x22, 0x2c, 0x35, 0x31, 0x32, 0x33, 0x00, 0x5c, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x5c, 0x6e, 0x75, 0x6d, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x5c, 0x6d, 0x61, 0x78, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x5c, 0x6d, 0x61, 0x70, 0x6e, 0x61, 0x6d, 0x65, 0x5c, 0x67, 0x61, 0x6d, 0x65, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00 }; - request = new ServerListRequest(raw); - request.Parse(); - } - } -} diff --git a/src/Servers/WebServer/src/Abstraction/CmdHandlerBase.cs b/src/Servers/WebServer/src/Abstraction/CmdHandlerBase.cs deleted file mode 100644 index 7a2bbd156..000000000 --- a/src/Servers/WebServer/src/Abstraction/CmdHandlerBase.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.WebServer.Application; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.WebServer.Abstraction -{ - public abstract class CmdHandlerBase : UniSpy.Server.Core.Abstraction.BaseClass.CmdHandlerBase - { - protected new Client _client => (Client)base._client; - protected CmdHandlerBase(IClient client, IRequest request) : base(client, request) - { - } - } -} diff --git a/src/Servers/WebServer/src/Abstraction/RequestBase.cs b/src/Servers/WebServer/src/Abstraction/RequestBase.cs deleted file mode 100644 index bcaa0beba..000000000 --- a/src/Servers/WebServer/src/Abstraction/RequestBase.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Xml.Linq; - -namespace UniSpy.Server.WebServer.Abstraction -{ - public abstract class RequestBase : UniSpy.Server.Core.Abstraction.BaseClass.RequestBase - { - public new string RawRequest => (string)base.RawRequest; - protected XElement _contentElement { get; private set; } - public RequestBase(string rawRequest) : base(rawRequest) - { - } - - protected RequestBase() - { - } - public override void Parse() - { - dynamic xelements = XElement.Parse(RawRequest); - _contentElement = xelements.FirstNode.FirstNode; - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Abstraction/ResponseBase.cs b/src/Servers/WebServer/src/Abstraction/ResponseBase.cs deleted file mode 100644 index 63020e006..000000000 --- a/src/Servers/WebServer/src/Abstraction/ResponseBase.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace UniSpy.Server.WebServer.Abstraction -{ - public abstract class ResponseBase : UniSpy.Server.Core.Abstraction.BaseClass.ResponseBase - { - protected SoapEnvelopBase _content { get; set; } - public new string SendingBuffer { get => (string)base.SendingBuffer; set => base.SendingBuffer = value; } - public ResponseBase(RequestBase request, ResultBase result) : base(request, result) - { - } - public override void Build() - { - // Because the response is kind of soap object, so we did not use SoapXElement as a soap object - // SoapXElement only acts like XElement - // !! call at last - SendingBuffer = _content.ToString(); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Abstraction/ResultBase.cs b/src/Servers/WebServer/src/Abstraction/ResultBase.cs deleted file mode 100644 index 542bfd055..000000000 --- a/src/Servers/WebServer/src/Abstraction/ResultBase.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace UniSpy.Server.WebServer.Abstraction -{ - public abstract class ResultBase : UniSpy.Server.Core.Abstraction.BaseClass.ResultBase - { - protected ResultBase() - { - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Abstraction/SoapEnvelopBase.cs b/src/Servers/WebServer/src/Abstraction/SoapEnvelopBase.cs deleted file mode 100644 index 248fb1d30..000000000 --- a/src/Servers/WebServer/src/Abstraction/SoapEnvelopBase.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System.IO; -using System.Linq; -using System.Xml.Linq; - -namespace UniSpy.Server.WebServer.Abstraction -{ - public abstract class SoapEnvelopBase - { - private static XDeclaration _declaration = new XDeclaration("1.0", "utf-8", null); - public static XNamespace SoapEnvelopNamespace = "http://schemas.xmlsoap.org/soap/envelope/"; - public XElement SoapHeader = new XElement(SoapEnvelopNamespace + "Envelope", - new XAttribute(XNamespace.Xmlns + "SOAP-ENV", SoapEnvelopNamespace), - new XAttribute(XNamespace.Xmlns + "SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"), - new XAttribute(XNamespace.Xmlns + "xsi", "http://www.w3.org/2001/XMLSchema-instance"), - new XAttribute(XNamespace.Xmlns + "xsd", "http://www.w3.org/2001/XMLSchema")); - private XNamespace _bodyNamespace; - public XDocument Content { get; private set; } - public XElement Body => Content.Root.Descendants().First(p => p.Name.LocalName == "Body"); - public XElement CurrentElement { get; private set; } - public SoapEnvelopBase(string nsShortName, XNamespace bodyNamespace) - { - _bodyNamespace = bodyNamespace; - Content = new XDocument(_declaration); - Content.Declaration = _declaration; - SoapHeader.Add(new XAttribute(XNamespace.Xmlns + nsShortName, _bodyNamespace)); - Content.Add(SoapHeader); - Content.Root.Add(new XElement(SoapEnvelopNamespace + "Body")); - CurrentElement = Body; - } - public void FinishAddSubElement() - { - CurrentElement = Body; - } - public void ChangeToElement(string name) - { - CurrentElement = Content.Descendants().First(p => p.Name.LocalName == name); - } - public void BackToParentElement() - { - CurrentElement = CurrentElement.Parent; - } - public virtual void Add(string name) - { - CurrentElement.Add(new XElement(_bodyNamespace + name)); - ChangeToElement(name); - } - public virtual void Add(string name, object value) - { - CurrentElement.Add(new XElement(_bodyNamespace + name, value)); - } - // public virtual void Add(string name, List values) - // { - // throw new NotImplementedException(); - // } - // public virtual void Add(string name, List values) - // { - // throw new NotImplementedException(); - // } - - public override string ToString() - { - using (var writer = new StringWriter()) - { - Content.Save(writer); - return writer.ToString(); - } - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Application/Client.cs b/src/Servers/WebServer/src/Application/Client.cs deleted file mode 100644 index ff117b990..000000000 --- a/src/Servers/WebServer/src/Application/Client.cs +++ /dev/null @@ -1,24 +0,0 @@ -using UniSpy.Server.WebServer.Handler; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.WebServer.Application -{ - public sealed class Client : ClientBase - { - public Client(IConnection connection, IServer server) : base(connection, server) - { - Info = new ClientInfo(); - } - - protected override ISwitcher CreateSwitcher(object buffer) => new CmdSwitcher(this, (IHttpRequest)buffer); - - protected override void OnReceived(object buffer) - { - base.OnReceived(buffer); - var rq = (IHttpRequest)buffer; - if (!rq.KeepAlive) - ((IHttpConnection)Connection).Disconnect(); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Application/ClientInfo.cs b/src/Servers/WebServer/src/Application/ClientInfo.cs deleted file mode 100644 index a8152188c..000000000 --- a/src/Servers/WebServer/src/Application/ClientInfo.cs +++ /dev/null @@ -1,31 +0,0 @@ -using UniSpy.Server.Core.Abstraction.BaseClass; - -namespace UniSpy.Server.WebServer.Application -{ - /// - /// Note!! the public exponent on SDK must set to 000001 - /// because the multiple inverse of 1 is 1 - /// data^1 mod n = data - /// enc^1 mod n = data^1^1 mod n = data - /// I do not want let our server to compute the rsa encryption so I made this trick - /// I am very glad that my major is cryptography during my master degree - /// - public sealed class ClientInfo : ClientInfoBase - { - /// - /// RandomNumber - /// - public const string PeerKeyPrivate = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; - public const string PeerKeyPublicModulus = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; - /// - /// should be 256 characters - /// - public const string ServerData = - "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; - public const int ExpireTime = 0; - public const string SignaturePreFix = "0001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003020300C06082A864886F70D020505000410"; - public ClientInfo() - { - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Application/Program.cs b/src/Servers/WebServer/src/Application/Program.cs deleted file mode 100755 index 0332e7a1c..000000000 --- a/src/Servers/WebServer/src/Application/Program.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using UniSpy.Server.Core.Logging; - -namespace UniSpy.Server.WebServer.Application -{ - public class Program - { - static void Main(string[] args) - { - try - { - new ServerLauncher().Start(); - Console.WriteLine("Press < Q > to exit. "); - while (Console.ReadKey().Key != ConsoleKey.Q) { } - } - catch (System.Exception e) - { - LogWriter.LogError(e); - } - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Application/Server.cs b/src/Servers/WebServer/src/Application/Server.cs deleted file mode 100644 index c13d9522e..000000000 --- a/src/Servers/WebServer/src/Application/Server.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Net; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.Core.Network.Http.Server; - -namespace UniSpy.Server.WebServer.Application -{ - public sealed class Server : ServerBase - { - static Server() - { - _name = "WebServer"; - } - public Server(){ } - - public Server(IConnectionManager manager) : base(manager){} - - protected override IClient CreateClient(IConnection connection) => new Client(connection, this); - - protected override IConnectionManager CreateConnectionManager(IPEndPoint endPoint) => new HttpConnectionManager(endPoint); - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Application/ServerLauncher.cs b/src/Servers/WebServer/src/Application/ServerLauncher.cs deleted file mode 100644 index 0d01c5b71..000000000 --- a/src/Servers/WebServer/src/Application/ServerLauncher.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Core.Abstraction.BaseClass.Factory; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.WebServer.Application -{ - public sealed class ServerLauncher : ServerLauncherBase - { - public static IServer Server => ServerInstances[0]; - protected override List LaunchNetworkService() => new List { new Server() }; - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Dockerfile b/src/Servers/WebServer/src/Dockerfile deleted file mode 100644 index 522703b37..000000000 --- a/src/Servers/WebServer/src/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM mcr.microsoft.com/dotnet/runtime:6.0 AS base -WORKDIR /app -EXPOSE 80 - -FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build -WORKDIR /src -COPY ["src/Servers/WebServer/src/UniSpy.Server.WebServer.csproj", "src/Servers/WebServer/src/"] -COPY ["src/Libraries/Core/src/UniSpy.Server.Core.csproj", "src/Libraries/Core/src/"] -RUN dotnet restore "src/Servers/WebServer/src/UniSpy.Server.WebServer.csproj" -COPY . . -WORKDIR "/src/src/Servers/WebServer/src" -RUN dotnet build "UniSpy.Server.WebServer.csproj" -c Release -o /app/build - -FROM build AS publish -RUN dotnet publish "UniSpy.Server.WebServer.csproj" -c Release -o /app/publish - -FROM base AS final -WORKDIR /app -COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "UniSpy.Server.WebServer.dll"] \ No newline at end of file diff --git a/src/Servers/WebServer/src/Entity/Constant/WebEndpoints.cs b/src/Servers/WebServer/src/Entity/Constant/WebEndpoints.cs deleted file mode 100644 index 393a9236a..000000000 --- a/src/Servers/WebServer/src/Entity/Constant/WebEndpoints.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Collections.Generic; - -namespace UniSpy.Server.WebServer.Entity.Constant -{ - public class WebEndpoints - { - //Contains all endpoints of the web server - public static readonly List AvailableEndpoints = new List - { - // WSMotd Service - "/motd/motd.asp", - "/motd/vercheck.asp", - // WSAuth Service - "/AuthService/AuthService.asmx", - // WSSake Service - "/SakeStorageServer/StorageServer.asmx", - "/SakeFileServer/download.aspx", - "/SakeFileServer/upload.aspx", - // WSAtlas Service - "/CompetitionService/CompetitionService.asmx", - // WSDirect2Game Service - "/commerce/1.1/catalogservice.svc", - "/commerce/1.1/accountservice.svc", - "/commerce/1.1/purchaseservice.svc", - // WSIngameAd Service - "/IGNAdServer/service1.asmx", - // WSRacing Service - "/RaceService/NintendoRacingService.asmx", - }; - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Entity/Structure/SakeArrayObject.cs b/src/Servers/WebServer/src/Entity/Structure/SakeArrayObject.cs deleted file mode 100644 index 6489385f7..000000000 --- a/src/Servers/WebServer/src/Entity/Structure/SakeArrayObject.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace UniSpy.Server.WebServer.Contract -{ - public record RecordFieldObject : FieldObject - { - public string FieldValue { get; private set; } - public RecordFieldObject(string fieldValue, string fieldName, string filedType) : base(fieldName, filedType) - { - FieldValue = fieldValue; - } - } - - public record FieldObject - { - public string FieldName { get; private set; } - public string FiledType { get; private set; } - - public FieldObject(string fieldName, string filedType) - { - this.FieldName = fieldName; - this.FiledType = filedType; - } - } -} diff --git a/src/Servers/WebServer/src/Entity/Structure/SoapXElement.cs b/src/Servers/WebServer/src/Entity/Structure/SoapXElement.cs deleted file mode 100644 index 1976d6b2e..000000000 --- a/src/Servers/WebServer/src/Entity/Structure/SoapXElement.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Xml.Linq; - -namespace UniSpy.Server.WebServer.Contract -{ - public class SoapXElement : XElement - { - private static XDeclaration _declaration = new XDeclaration("1.0", "utf-8", null); - public static XNamespace SoapEnvelopNamespace = "http://schemas.xmlsoap.org/soap/envelope/"; - public static readonly XElement SoapHeader = new XElement(SoapEnvelopNamespace + "Envelope", - new XAttribute(XNamespace.Xmlns + "SOAP-ENV", SoapEnvelopNamespace), - new XAttribute(XNamespace.Xmlns + "SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"), - new XAttribute(XNamespace.Xmlns + "xsi", "http://www.w3.org/2001/XMLSchema-instance"), - new XAttribute(XNamespace.Xmlns + "xsd", "http://www.w3.org/2001/XMLSchema")); - public static XNamespace SakeNamespace = "http://gamespy.net/sake"; - public static XElement SakeSoapHeader - { - get - { - var element = new XElement(SoapHeader); - element.Add(new XAttribute(XNamespace.Xmlns + "ns1", SakeNamespace)); - return element; - } - } - public static XNamespace AuthNamespace = "http://gamespy.net/AuthService/"; - public static XElement AuthSoapHeader - { - get - { - var element = new XElement(SoapHeader); - element.Add(new XAttribute(XNamespace.Xmlns + "ns1", AuthNamespace)); - return element; - } - } - public static XNamespace Direct2GameNamespace = "http://gamespy.net/commerce/2009/02"; - public static XElement Direct2GameSoapHeader - { - get - { - var element = new XElement(SoapHeader); - element.Add(new XAttribute(XNamespace.Xmlns + "gsc", Direct2GameNamespace)); - return element; - } - } - public SoapXElement(XElement other) : base(other) { } - public SoapXElement(XName name) : base(name) { } - public SoapXElement(XName name, object content) : base(name, content) { } - public SoapXElement(XName name, params object[] content) : base(name, content) { } - public List GetArrayObjects() - { - throw new NotImplementedException(); - } - public XElement SetArrayObjects(List objects) - { - throw new NotImplementedException(); - } - - public override string ToString() - { - return _declaration + Environment.NewLine + base.ToString(); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Handler/CmdSwitcher.cs b/src/Servers/WebServer/src/Handler/CmdSwitcher.cs deleted file mode 100755 index 5b0196db2..000000000 --- a/src/Servers/WebServer/src/Handler/CmdSwitcher.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Xml.Linq; -using UniSpy.Server.WebServer.Module.Sake.Contract.Request; -using UniSpy.Server.Core.Abstraction.BaseClass; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.WebServer.Module.Sake.Handler; -using UniSpy.Server.WebServer.Module.Auth.Handler; -using UniSpy.Server.WebServer.Module.Auth.Contract.Request; -using UniSpy.Server.WebServer.Module.Direct2Game.Contract.Request; -using UniSpy.Server.WebServer.Module.Direct2Game.Handler; -using UniSpy.Server.Core.Logging; -using UniSpy.Server.WebServer.Application; - -namespace UniSpy.Server.WebServer.Handler -{ - public class CmdSwitcher : CmdSwitcherBase - { - private new IHttpRequest _rawRequest => (IHttpRequest)base._rawRequest; - private new Client _client => (Client)base._client; - public CmdSwitcher(Client client, IHttpRequest rawRequest) : base(client, rawRequest) - { - } - - protected override void ProcessRawRequest() - { - // var uri = new Uri(_rawRequest.Url); - // if (WebEndpoints.AvailableEndpoints.Contains(uri.LocalPath)) - // { - // throw new UniSpy.Exception($"Invalid http path access:{_rawRequest.Url}"); - // } - if (_rawRequest.Body == "") - { - return; - } - dynamic xelements = XElement.Parse(_rawRequest.Body); - var name = xelements.FirstNode.FirstNode.Name.LocalName; - _requests.Add(new KeyValuePair(name, _rawRequest.Body)); - } - - protected override IHandler CreateCmdHandlers(object name, object rawRequest) - { - switch ((string)name) - { - #region Altas - case "CreateMatchlessSession": - case "CreateSession": - case "SetReportIntention": - case "SubmitReport": - throw new NotImplementedException(); - #endregion - #region Auth - case "LoginProfile": - return new LoginProfileHandler(_client, new LoginProfileRequest((string)rawRequest)); - case "LoginProfileWithGameid": - return new LoginProfileWithGameIdHandler(_client, new LoginProfileWithGameIdRequest((string)rawRequest)); - case "LoginRemoteAuth": - return new LoginRemoteAuthHandler(_client, new LoginRemoteAuthRequest((string)rawRequest)); - case "LoginRemoteAuthWithGameid": - return new LoginRemoteAuthWithGameIdHandler(_client, new LoginRemoteAuthWithGameIdRequest((string)rawRequest)); - case "LoginUniqueNick": - return new LoginUniqueNickHandler(_client, new LoginUniqueNickRequest((string)rawRequest)); - case "LoginUniqueNickWithGameid": - return new LoginUniqueNickWithGameIdHandler(_client, new LoginUniqueNickWithGameIdRequest((string)rawRequest)); - #endregion - #region Direct2Game - case "GetStoreAvailability": - return new GetStoreAvailabilityHandler(_client, new GetStoreAvailabilityRequest((string)rawRequest)); - - case "GetPurchaseHistory": - return new GetPurchaseHistoryHandler(_client, new GetPurchaseHistoryRequest((string)rawRequest)); - case "GetTargettedAd": - throw new NotImplementedException(); - #endregion - #region InGameAd - case "ReportAdUsage": - throw new NotImplementedException(); - #endregion - #region PatchingAndTracking - case "Motd": - case "Vercheck": - throw new NotImplementedException(); - #endregion - #region Racing - case "GetContestData": - case "GetFriendRankings": - case "GetRegionalData": - case "GetTenAboveRankings": - case "GetTopTenRankings": - case "SubmitScores": - throw new NotImplementedException(); - #endregion - #region Sake - case "CreateRecord": - return new CreateRecordHandler(_client, new CreateRecordRequest((string)rawRequest)); - case "DeleteRecord": - throw new NotImplementedException(); - case "GetMyRecords": - return new GetMyRecordsHandler(_client, new GetMyRecordsRequest((string)rawRequest)); - case "GetRandomRecords": - throw new NotImplementedException(); - case "GetRecordLimit": - throw new NotImplementedException(); - case "RateRecord": - throw new NotImplementedException(); - case "SearchForRecords": - return new SearchForRecordsHandler(_client, new SearchForRecordsRequest((string)rawRequest)); - case "UpdateRecord": - // return new UpdateRecordHandler(_client, new UpdateRecordRequest((string)rawRequest)); - throw new NotImplementedException(); - #endregion - default: - _client.LogError($"Unkown {(string)name} request received"); - return null; - } - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Atlas/Contract/Request/CreateMatchlessSessionRequest.cs b/src/Servers/WebServer/src/Module/Atlas/Contract/Request/CreateMatchlessSessionRequest.cs deleted file mode 100644 index a34b057f1..000000000 --- a/src/Servers/WebServer/src/Module/Atlas/Contract/Request/CreateMatchlessSessionRequest.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Abstraction; - - -namespace UniSpy.Server.WebServer.Module.Atlas.Contract.Request -{ - - public class CreateMatchlessSessionRequest : RequestBase - { - public string Certificate { get; set; } - public string Proof { get; set; } - public int GameId { get; set; } - public CreateMatchlessSessionRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - var certificate = _contentElement.Descendants().Where(p => p.Name.LocalName == "certificate").First().Value; - Certificate = certificate; - var proof = _contentElement.Descendants().Where(p => p.Name.LocalName == "proof").First().Value; - Proof = proof; - var gameid = _contentElement.Descendants().Where(p => p.Name.LocalName == "gameid").First().Value; - GameId = int.Parse(gameid); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Atlas/Contract/Request/CreateSessionRequest.cs b/src/Servers/WebServer/src/Module/Atlas/Contract/Request/CreateSessionRequest.cs deleted file mode 100644 index edee2e652..000000000 --- a/src/Servers/WebServer/src/Module/Atlas/Contract/Request/CreateSessionRequest.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Abstraction; - - -namespace UniSpy.Server.WebServer.Module.Atlas.Contract.Request -{ - - public class CreateSessionRequest : RequestBase - { - public string Certificate { get; set; } - public string Proof { get; set; } - public int GameId { get; set; } - public CreateSessionRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - var certificate = _contentElement.Descendants().Where(p => p.Name.LocalName == "certificate").First().Value; - Certificate = certificate; - var proof = _contentElement.Descendants().Where(p => p.Name.LocalName == "proof").First().Value; - Proof = proof; - var gameid = _contentElement.Descendants().Where(p => p.Name.LocalName == "gameid").First().Value; - GameId = int.Parse(gameid); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Atlas/Contract/Request/SetReportIntentionRequest.cs b/src/Servers/WebServer/src/Module/Atlas/Contract/Request/SetReportIntentionRequest.cs deleted file mode 100644 index 82ea60e56..000000000 --- a/src/Servers/WebServer/src/Module/Atlas/Contract/Request/SetReportIntentionRequest.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Abstraction; - - -namespace UniSpy.Server.WebServer.Module.Atlas.Contract.Request -{ - - public class SetReportIntentionRequest : RequestBase - { - public string Certificate { get; set; } - public string Proof { get; set; } - public int CsId { get; set; } - public int CcId { get; set; } - public int GameId { get; set; } - public string Authoritative { get; set; } - public SetReportIntentionRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - var certificate = _contentElement.Descendants().Where(p => p.Name.LocalName == "certificate").First().Value; - Certificate = certificate; - var proof = _contentElement.Descendants().Where(p => p.Name.LocalName == "proof").First().Value; - Proof = proof; - var csid = _contentElement.Descendants().Where(p => p.Name.LocalName == "csid").First().Value; - CsId = int.Parse(csid); - var ccid = _contentElement.Descendants().Where(p => p.Name.LocalName == "ccid").First().Value; - CcId = int.Parse(ccid); - var gameid = _contentElement.Descendants().Where(p => p.Name.LocalName == "gameid").First().Value; - GameId = int.Parse(gameid); - var authoritative = _contentElement.Descendants().Where(p => p.Name.LocalName == "authoritative").First().Value; - Authoritative = authoritative; - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Atlas/Contract/Request/SubmitReportRequest.cs b/src/Servers/WebServer/src/Module/Atlas/Contract/Request/SubmitReportRequest.cs deleted file mode 100644 index a7cfa35e2..000000000 --- a/src/Servers/WebServer/src/Module/Atlas/Contract/Request/SubmitReportRequest.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Abstraction; - - -namespace UniSpy.Server.WebServer.Module.Atlas.Contract.Request -{ - - public class SubmitReportRequest : RequestBase - { - public string Certificate { get; set; } - public string Proof { get; set; } - public int CsId { get; set; } - public int CcId { get; set; } - public int GameId { get; set; } - public string Authoritative { get; set; } - public SubmitReportRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - var certificate = _contentElement.Descendants().Where(p => p.Name.LocalName == "certificate").First().Value; - Certificate = certificate; - var proof = _contentElement.Descendants().Where(p => p.Name.LocalName == "proof").First().Value; - Proof = proof; - var csid = _contentElement.Descendants().Where(p => p.Name.LocalName == "csid").First().Value; - CsId = int.Parse(csid); - var ccid = _contentElement.Descendants().Where(p => p.Name.LocalName == "ccid").First().Value; - CcId = int.Parse(ccid); - var gameid = _contentElement.Descendants().Where(p => p.Name.LocalName == "gameid").First().Value; - GameId = int.Parse(gameid); - var authoritative = _contentElement.Descendants().Where(p => p.Name.LocalName == "authoritative").First().Value; - Authoritative = authoritative; - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Abstraction/LoginRequestBase.cs b/src/Servers/WebServer/src/Module/Auth/Abstraction/LoginRequestBase.cs deleted file mode 100644 index 99c7f972d..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Abstraction/LoginRequestBase.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Abstraction; - - -namespace UniSpy.Server.WebServer.Module.Auth.Abstraction -{ - public abstract class LoginRequestBase : RequestBase - { - protected LoginRequestBase(string rawRequest) : base(rawRequest) - { - } - - public int Version { get; private set; } - public int PartnerCode { get; private set; } - public int NamespaceId { get; private set; } - public override void Parse() - { - base.Parse(); - if (!_contentElement.Descendants().Any(p => p.Name.LocalName == "version")) - { - throw new Auth.Exception("version is missing from the request"); - } - var version = _contentElement.Descendants().First(p => p.Name.LocalName == "version").Value; - Version = int.Parse(version); - - if (!_contentElement.Descendants().Any(p => p.Name.LocalName == "partnercode")) - { - throw new Auth.Exception("partnercode is missing from the request"); - } - var partnercode = _contentElement.Descendants().First(p => p.Name.LocalName == "partnercode").Value; - PartnerCode = int.Parse(partnercode); - - if (!_contentElement.Descendants().Any(p => p.Name.LocalName == "namespaceid")) - { - throw new Auth.Exception("namespaceid is missing from the request"); - } - var namespaceid = _contentElement.Descendants().First(p => p.Name.LocalName == "namespaceid").Value; - NamespaceId = int.Parse(namespaceid); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Abstraction/LoginResponseBase.cs b/src/Servers/WebServer/src/Module/Auth/Abstraction/LoginResponseBase.cs deleted file mode 100644 index a996676eb..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Abstraction/LoginResponseBase.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Security.Cryptography; -using System.Text; -using UniSpy.Server.WebServer.Abstraction; -using UniSpy.Server.WebServer.Application; -using UniSpy.Server.Core.Extension; - -namespace UniSpy.Server.WebServer.Module.Auth.Abstraction -{ - - public abstract class LoginResponseBase : ResponseBase - { - protected new LoginResultBase _result => (LoginResultBase)base._result; - protected new LoginRequestBase _request => (LoginRequestBase)base._request; - protected LoginResponseBase(RequestBase request, ResultBase result) : base(request, result) - { - } - - protected void BuildContext() - { - _content.Add("responseCode", _result.ResponseCode); - _content.Add("certificate"); - _content.Add("length", _result.Length); - _content.Add("version", _request.Version); - _content.Add("partnercode", _request.PartnerCode); - _content.Add("namespaceid", _request.NamespaceId); - _content.Add("userid", _result.UserId); - _content.Add("profileid", _result.ProfileId); - _content.Add("expiretime", ClientInfo.ExpireTime); - _content.Add("profilenick", _result.ProfileNick); - _content.Add("uniquenick", _result.UniqueNick); - _content.Add("cdkeyhash", _result.CdKeyHash); - _content.Add("peerkeymodulus", ClientInfo.PeerKeyPublicModulus); - _content.Add("peerkeyexponent", ClientInfo.PeerKeyPrivate); - _content.Add("serverdata", ClientInfo.ServerData); - - using (var md5 = MD5.Create()) - { - var dataToHash = new List(); - dataToHash.AddRange(BitConverter.GetBytes(_result.Length)); - dataToHash.AddRange(BitConverter.GetBytes(_request.Version)); - dataToHash.AddRange(BitConverter.GetBytes(_request.PartnerCode)); - dataToHash.AddRange(BitConverter.GetBytes(_request.NamespaceId)); - dataToHash.AddRange(BitConverter.GetBytes(_result.UserId)); - dataToHash.AddRange(BitConverter.GetBytes(_result.ProfileId)); - dataToHash.AddRange(BitConverter.GetBytes(ClientInfo.ExpireTime)); - dataToHash.AddRange(Encoding.ASCII.GetBytes(_result.ProfileNick)); - dataToHash.AddRange(Encoding.ASCII.GetBytes(_result.UniqueNick)); - dataToHash.AddRange(Encoding.ASCII.GetBytes(_result.CdKeyHash)); - - // if these 2 value be 0 we do not need to add them to the list - // dataToHash.AddRange(ClientInfo.PeerKeyPublicModulus.FromHexStringToBytes()); - // dataToHash.AddRange(ClientInfo.PeerKeyPrivate.FromHexStringToBytes()); - - // server data should be convert to bytes[128] then added to list - dataToHash.AddRange(ClientInfo.ServerData.FromHexStringToBytes()); - var hash = md5.ComputeHash(dataToHash.ToArray()); - var hashString = BitConverter.ToString(hash).Replace("-", string.Empty); - _content.Add("signature", ClientInfo.SignaturePreFix + hashString); - } - _content.BackToParentElement(); - _content.Add("peerkeyprivate", ClientInfo.PeerKeyPrivate); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Abstraction/LoginResultBase.cs b/src/Servers/WebServer/src/Module/Auth/Abstraction/LoginResultBase.cs deleted file mode 100644 index 067b6e449..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Abstraction/LoginResultBase.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.WebServer.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Auth.Abstraction -{ - public abstract class LoginResultBase : ResultBase - { - public int? ResponseCode { get; set; } - public int Length { get; set; } - public int UserId { get; set; } - public int ProfileId { get; set; } - public string ProfileNick { get; set; } - public string UniqueNick { get; set; } - public string CdKeyHash { get; set; } - public LoginResultBase() - { - ResponseCode = 0; - Length = 303; - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Abstraction/ResponseBase.cs b/src/Servers/WebServer/src/Module/Auth/Abstraction/ResponseBase.cs deleted file mode 100644 index 8c916e1c3..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Abstraction/ResponseBase.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.WebServer.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Contract; - -namespace UniSpy.Server.WebServer.Module.Auth.Abstraction -{ - public abstract class ResponseBase : WebServer.Abstraction.ResponseBase - { - public ResponseBase(RequestBase request, ResultBase result) : base(request, result) - { - _content = new AuthSoapEnvelope(); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Contract/AuthSoapEnvelope.cs b/src/Servers/WebServer/src/Module/Auth/Contract/AuthSoapEnvelope.cs deleted file mode 100644 index 9ab8742f4..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Contract/AuthSoapEnvelope.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Xml.Linq; -using UniSpy.Server.WebServer.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Auth.Contract -{ - public sealed class AuthSoapEnvelope : SoapEnvelopBase - { - public static XNamespace AuthNamespace = "http://gamespy.net/AuthService/"; - public AuthSoapEnvelope() : base("ns1", AuthNamespace) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginProfileRequest.cs b/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginProfileRequest.cs deleted file mode 100644 index d76806cff..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginProfileRequest.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Module.Auth.Abstraction; - - -namespace UniSpy.Server.WebServer.Module.Auth.Contract.Request -{ - - public class LoginProfileRequest : LoginRequestBase - { - public string Email { get; private set; } - public string Uniquenick { get; private set; } - public string CDKey { get; private set; } - public string Password { get; private set; } - public LoginProfileRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - if (!_contentElement.Descendants().Any(p => p.Name.LocalName == "email")) - { - throw new Auth.Exception("email is missing from the request"); - } - Email = _contentElement.Descendants().First(p => p.Name.LocalName == "email").Value; - - if (!_contentElement.Descendants().Any(p => p.Name.LocalName == "uniquenick")) - { - throw new Auth.Exception("uniquenick is missing from the request"); - } - Uniquenick = _contentElement.Descendants().First(p => p.Name.LocalName == "uniquenick").Value; - - if (!_contentElement.Descendants().Any(p => p.Name.LocalName == "cdkey")) - { - throw new Auth.Exception("cdkey is missing from the request"); - } - CDKey = _contentElement.Descendants().First(p => p.Name.LocalName == "cdkey").Value; - - if (!_contentElement.Descendants().Any(p => p.Name.LocalName == "password")) - { - throw new Auth.Exception("password is missing from the request"); - } - Password = _contentElement.Descendants().First(p => p.Name.LocalName == "password").Value; - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginProfileWithGameIdRequest.cs b/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginProfileWithGameIdRequest.cs deleted file mode 100644 index 3e5077f4d..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginProfileWithGameIdRequest.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Linq; - - -namespace UniSpy.Server.WebServer.Module.Auth.Contract.Request -{ - - public sealed class LoginProfileWithGameIdRequest : LoginProfileRequest - { - public int GameId { get; private set; } - public LoginProfileWithGameIdRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - if (!_contentElement.Descendants().Any(p => p.Name.LocalName == "gameid")) - { - throw new Auth.Exception("gameid is missing from the request"); - } - var gameid = _contentElement.Descendants().FirstOrDefault(p => p.Name.LocalName == "gameid").Value; - GameId = int.Parse(gameid); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginPs3CertRequest.cs b/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginPs3CertRequest.cs deleted file mode 100644 index 911dae6ae..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginPs3CertRequest.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Module.Auth.Abstraction; - - -namespace UniSpy.Server.WebServer.Module.Auth.Contract.Request -{ - - public class LoginPs3CertRequest : LoginRequestBase - { - public string PS3cert { get; private set; } - public LoginPs3CertRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - if (!_contentElement.Descendants().Any(p => p.Name.LocalName == "npticket")) - { - throw new Auth.Exception("ps3cert is missing from the request"); - } - PS3cert = _contentElement.Descendants().First(p => p.Name.LocalName == "npticket").Value; - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginPs3CertWithGameIdRequest.cs b/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginPs3CertWithGameIdRequest.cs deleted file mode 100644 index c76898cff..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginPs3CertWithGameIdRequest.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Linq; - - -namespace UniSpy.Server.WebServer.Module.Auth.Contract.Request -{ - - public sealed class LoginPs3CertWithGameIdRequest : LoginPs3CertRequest - { - public int? GameId { get; private set; } - public LoginPs3CertWithGameIdRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - if (!_contentElement.Descendants().Any(p => p.Name.LocalName == "gameid")) - { - throw new Auth.Exception("gameid is missing from the request"); - } - var gameid = _contentElement.Descendants().FirstOrDefault(p => p.Name.LocalName == "gameid").Value; - GameId = int.Parse(gameid); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginRemoteAuthRequest.cs b/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginRemoteAuthRequest.cs deleted file mode 100644 index 58c75f32f..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginRemoteAuthRequest.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Module.Auth.Abstraction; - - -namespace UniSpy.Server.WebServer.Module.Auth.Contract.Request -{ - - public class LoginRemoteAuthRequest : LoginRequestBase - { - public string AuthToken { get; private set; } - public string Challenge { get; private set; } - public LoginRemoteAuthRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - if (!_contentElement.Descendants().Any(p => p.Name.LocalName == "authtoken")) - { - throw new Auth.Exception("authtoken is missing from the request"); - } - AuthToken = _contentElement.Descendants().First(p => p.Name.LocalName == "authtoken").Value; - if (!_contentElement.Descendants().Any(p => p.Name.LocalName == "challenge")) - { - throw new Auth.Exception("challenge is missing from the request"); - } - Challenge = _contentElement.Descendants().First(p => p.Name.LocalName == "challenge").Value; - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginRemoteAuthWithGameIdRequest.cs b/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginRemoteAuthWithGameIdRequest.cs deleted file mode 100644 index 67b68f463..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginRemoteAuthWithGameIdRequest.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Linq; - - -namespace UniSpy.Server.WebServer.Module.Auth.Contract.Request -{ - - public class LoginRemoteAuthWithGameIdRequest : LoginRemoteAuthRequest - { - public int? GameId { get; private set; } - public LoginRemoteAuthWithGameIdRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - if (!_contentElement.Descendants().Any(p => p.Name.LocalName == "gameid")) - { - throw new Auth.Exception("gameid is missing from the request"); - } - var gameid = _contentElement.Descendants().FirstOrDefault(p => p.Name.LocalName == "gameid").Value; - GameId = int.Parse(gameid); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginUniqueNickRequest.cs b/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginUniqueNickRequest.cs deleted file mode 100644 index 658b15185..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginUniqueNickRequest.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Module.Auth.Abstraction; - - -namespace UniSpy.Server.WebServer.Module.Auth.Contract.Request -{ - - public class LoginUniqueNickRequest : LoginRequestBase - { - public string Uniquenick { get; private set; } - public string Password { get; private set; } - public LoginUniqueNickRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - if (!_contentElement.Descendants().Any(p => p.Name.LocalName == "uniquenick")) - { - throw new Auth.Exception("uniquenick is missing from the request"); - } - Uniquenick = _contentElement.Descendants().First(p => p.Name.LocalName == "uniquenick").Value; - if (!_contentElement.Descendants().Any(p => p.Name.LocalName == "password")) - { - throw new Auth.Exception("password is missing from the request"); - } - Password = _contentElement.Descendants().First(p => p.Name.LocalName == "password").Value; - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginUniqueNickWithGameId.cs b/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginUniqueNickWithGameId.cs deleted file mode 100644 index 24bb1f5cc..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Contract/Request/LoginUniqueNickWithGameId.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Linq; - - -namespace UniSpy.Server.WebServer.Module.Auth.Contract.Request -{ - - public class LoginUniqueNickWithGameIdRequest : LoginUniqueNickRequest - { - public int? GameId { get; private set; } - public LoginUniqueNickWithGameIdRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - if (!_contentElement.Descendants().Any(p => p.Name.LocalName == "gameid")) - { - throw new Auth.Exception("gameid is missing from the request"); - } - var gameid = _contentElement.Descendants().FirstOrDefault(p => p.Name.LocalName == "gameid").Value; - GameId = int.Parse(gameid); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginProfileResponse.cs b/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginProfileResponse.cs deleted file mode 100644 index 2ecb45d91..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginProfileResponse.cs +++ /dev/null @@ -1,22 +0,0 @@ -using UniSpy.Server.WebServer.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Contract.Request; - -namespace UniSpy.Server.WebServer.Module.Auth.Contract.Response -{ - public class LoginProfileResponse : LoginResponseBase - { - protected new LoginProfileRequest _request => (LoginProfileRequest)base._request; - protected new LoginResultBase _result => (LoginResultBase)base._result; - protected new AuthSoapEnvelope _content { get => (AuthSoapEnvelope)base._content; set => base._content = value; } - public LoginProfileResponse(RequestBase request, ResultBase result) : base(request, result) - { - } - public override void Build() - { - _content.Add("LoginProfileResult"); - BuildContext(); - base.Build(); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginProfileWithGameIdResponse.cs b/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginProfileWithGameIdResponse.cs deleted file mode 100644 index beb9b9a55..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginProfileWithGameIdResponse.cs +++ /dev/null @@ -1,21 +0,0 @@ -using UniSpy.Server.WebServer.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Contract.Request; - -namespace UniSpy.Server.WebServer.Module.Auth.Contract.Response -{ - public class LoginProfileWithGameIdResponse : LoginResponseBase - { - protected new LoginProfileWithGameIdRequest _request => (LoginProfileWithGameIdRequest)base._request; - protected new LoginResultBase _result => (LoginResultBase)base._result; - public LoginProfileWithGameIdResponse(RequestBase request, ResultBase result) : base(request, result) - { - } - public override void Build() - { - _content.Add("LoginProfileWithGameIdResult"); - BuildContext(); - base.Build(); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginPs3CertResponse.cs b/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginPs3CertResponse.cs deleted file mode 100644 index 257fc3446..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginPs3CertResponse.cs +++ /dev/null @@ -1,24 +0,0 @@ -using UniSpy.Server.WebServer.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Contract.Request; -using UniSpy.Server.WebServer.Module.Auth.Contract.Result; - -namespace UniSpy.Server.WebServer.Module.Auth.Contract.Response -{ - public class LoginPs3CertResponse : LoginResponseBase - { - protected new LoginPs3CertRequest _request => (LoginPs3CertRequest)base._request; - protected new LoginPs3CertResult _result => (LoginPs3CertResult)base._result; - public LoginPs3CertResponse(RequestBase request, ResultBase result) : base(request, result) - { - } - public override void Build() - { - _content.Add("LoginPs3CertResult"); - _content.Add("responseCode", _result.ResponseCode); - _content.Add("authToken", _result.AuthToken); - _content.Add("partnerChallenge", _result.PartnerChallenge); - base.Build(); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginPs3CertWithGameIdResponse.cs b/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginPs3CertWithGameIdResponse.cs deleted file mode 100644 index f06d94bd5..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginPs3CertWithGameIdResponse.cs +++ /dev/null @@ -1,24 +0,0 @@ -using UniSpy.Server.WebServer.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Contract.Request; -using UniSpy.Server.WebServer.Module.Auth.Contract.Result; - -namespace UniSpy.Server.WebServer.Module.Auth.Contract.Response -{ - public class LoginPs3CertWithGameIdResponse : LoginResponseBase - { - protected new LoginPs3CertWithGameIdRequest _request => (LoginPs3CertWithGameIdRequest)base._request; - protected new LoginPs3CertResult _result => (LoginPs3CertResult)base._result; - public LoginPs3CertWithGameIdResponse(RequestBase request, ResultBase result) : base(request, result) - { - } - public override void Build() - { - _content.Add("LoginPs3CertWithGameIdResult"); - _content.Add("responseCode", _result.ResponseCode); - _content.Add("authToken", _result.AuthToken); - _content.Add("partnerChallenge", _result.PartnerChallenge); - base.Build(); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginRemoteAuthResponse.cs b/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginRemoteAuthResponse.cs deleted file mode 100644 index 7ed17b154..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginRemoteAuthResponse.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.WebServer.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Contract.Request; -namespace UniSpy.Server.WebServer.Module.Auth.Contract.Response -{ - public class LoginRemoteAuthResponse : LoginResponseBase - { - protected new LoginRemoteAuthRequest _request => (LoginRemoteAuthRequest)base._request; - protected new LoginResultBase _result => (LoginResultBase)base._result; - public LoginRemoteAuthResponse(RequestBase request, ResultBase result) : base(request, result) - { - } - public override void Build() - { - _content.Add("LoginRemoteAuthResult"); - BuildContext(); - base.Build(); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginRemoteAuthWithGameIdResponse.cs b/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginRemoteAuthWithGameIdResponse.cs deleted file mode 100644 index 7d3a19413..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginRemoteAuthWithGameIdResponse.cs +++ /dev/null @@ -1,20 +0,0 @@ -using UniSpy.Server.WebServer.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Contract.Request; -namespace UniSpy.Server.WebServer.Module.Auth.Contract.Response -{ - public class LoginRemoteAuthWithGameIdResponse : LoginResponseBase - { - protected new LoginRemoteAuthWithGameIdRequest _request => (LoginRemoteAuthWithGameIdRequest)base._request; - protected new LoginResultBase _result => (LoginResultBase)base._result; - public LoginRemoteAuthWithGameIdResponse(RequestBase request, ResultBase result) : base(request, result) - { - } - public override void Build() - { - _content.Add("LoginRemoteAuthWithGameIdResult"); - BuildContext(); - base.Build(); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginUniqueNickResponse.cs b/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginUniqueNickResponse.cs deleted file mode 100644 index ffaa5b494..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginUniqueNickResponse.cs +++ /dev/null @@ -1,21 +0,0 @@ -using UniSpy.Server.WebServer.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Contract.Request; - -namespace UniSpy.Server.WebServer.Module.Auth.Contract.Response -{ - public class LoginUniqueNickResponse : LoginResponseBase - { - protected new LoginRemoteAuthRequest _request => (LoginRemoteAuthRequest)base._request; - protected new LoginResultBase _result => (LoginResultBase)base._result; - public LoginUniqueNickResponse(RequestBase request, ResultBase result) : base(request, result) - { - } - public override void Build() - { - _content.Add("LoginUniqueNickResult"); - BuildContext(); - base.Build(); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginUniqueNickWithGameIdResponse.cs b/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginUniqueNickWithGameIdResponse.cs deleted file mode 100644 index 8b59a3c60..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Contract/Response/LoginUniqueNickWithGameIdResponse.cs +++ /dev/null @@ -1,21 +0,0 @@ -using UniSpy.Server.WebServer.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Contract.Request; - -namespace UniSpy.Server.WebServer.Module.Auth.Contract.Response -{ - public class LoginUniqueNickWithGameIdResponse : LoginResponseBase - { - protected new LoginRemoteAuthRequest _request => (LoginRemoteAuthRequest)base._request; - protected new LoginResultBase _result => (LoginResultBase)base._result; - public LoginUniqueNickWithGameIdResponse(RequestBase request, ResultBase result) : base(request, result) - { - } - public override void Build() - { - _content.Add("LoginUniqueNickWithGameIdResult"); - BuildContext(); - base.Build(); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Contract/Result/LoginProfileResult.cs b/src/Servers/WebServer/src/Module/Auth/Contract/Result/LoginProfileResult.cs deleted file mode 100644 index c082817a6..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Contract/Result/LoginProfileResult.cs +++ /dev/null @@ -1,11 +0,0 @@ -using UniSpy.Server.WebServer.Module.Auth.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Auth.Contract.Result -{ - public sealed class LoginProfileResult : LoginResultBase - { - public LoginProfileResult() - { - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Contract/Result/LoginPs3CertResult.cs b/src/Servers/WebServer/src/Module/Auth/Contract/Result/LoginPs3CertResult.cs deleted file mode 100644 index 00c2b9789..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Contract/Result/LoginPs3CertResult.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UniSpy.Server.WebServer.Module.Auth.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Auth.Contract.Result -{ - public class LoginPs3CertResult : LoginResultBase - { - public string AuthToken { get; set; } - public string PartnerChallenge { get; set; } - public LoginPs3CertResult() - { - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Contract/Result/LoginRemoteAuthResult.cs b/src/Servers/WebServer/src/Module/Auth/Contract/Result/LoginRemoteAuthResult.cs deleted file mode 100644 index 6cf534af4..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Contract/Result/LoginRemoteAuthResult.cs +++ /dev/null @@ -1,11 +0,0 @@ -using UniSpy.Server.WebServer.Module.Auth.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Auth.Contract.Result -{ - public sealed class LoginRemoteAuthResult : LoginResultBase - { - public LoginRemoteAuthResult() - { - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Contract/Result/LoginUniqueNickResult.cs b/src/Servers/WebServer/src/Module/Auth/Contract/Result/LoginUniqueNickResult.cs deleted file mode 100644 index 6cb43b826..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Contract/Result/LoginUniqueNickResult.cs +++ /dev/null @@ -1,11 +0,0 @@ -using UniSpy.Server.WebServer.Module.Auth.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Auth.Contract.Result -{ - public sealed class LoginUniqueNickResult : LoginResultBase - { - public LoginUniqueNickResult() - { - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Exception/DatabaseException.cs b/src/Servers/WebServer/src/Module/Auth/Exception/DatabaseException.cs deleted file mode 100644 index 59dec49c3..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Exception/DatabaseException.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace UniSpy.Server.WebServer.Module.Auth -{ - public class DatabaseException : Auth.Exception - { - public DatabaseException() : base("Database error!", AuthErrorCode.DatabaseError) - { - } - public DatabaseException(string message) : base(message, AuthErrorCode.DatabaseError) - { - } - public DatabaseException(string message, System.Exception innerException) : base(message, AuthErrorCode.DatabaseError, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Exception/Exception.cs b/src/Servers/WebServer/src/Module/Auth/Exception/Exception.cs deleted file mode 100644 index c273a2f19..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Exception/Exception.cs +++ /dev/null @@ -1,53 +0,0 @@ -namespace UniSpy.Server.WebServer.Module.Auth -{ - public enum AuthErrorCode - { - Success = 0, - ServerInitFailed, - UserNotFound, - InvalidPassword, - InvalidProfile, - UniqueNickExpired, - - DatabaseError, - ServerError, - FailureMax, // must be the last failure - - // Login result (mLoginResult) - HttpError = 100, // ghttp reported an error, response ignored - ParseError, // couldn't parse http response - InvalidCertificate, // login success but certificate was invalid! - LoginFailed, // failed login or other error condition - OutOfMemory, // could not process due to insufficient memory - InvalidParameters, // check the function arguments - NoAvailabilityCheck,// No availability check was performed - Cancelled, // login request was cancelled - UnknownError, // error occured, but detailed information not available - - // response codes dealing with errors in response headers - InvalidGameID = 200, // make sure GameID is properly set with wsSetGameCredentials - InvalidAccessKey, // make sure Access Key is properly set with wsSetGameCredentials - - // login results dealing with errors in response headers - InvalidGameCredentials // check the parameters passed to wsSetGameCredentials - } - public class Exception : UniSpy.Exception - { - public AuthErrorCode ErrorCode { get; private set; } - public Exception() : this("Unkown Error!", AuthErrorCode.UnknownError) - { - } - - public Exception(string message) : this(message, AuthErrorCode.UnknownError) - { - } - public Exception(string message, AuthErrorCode code) - { - ErrorCode = code; - } - public Exception(string message, AuthErrorCode code, System.Exception innerException) : base(message, innerException) - { - ErrorCode = code; - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Exception/InvalidPasswordException.cs b/src/Servers/WebServer/src/Module/Auth/Exception/InvalidPasswordException.cs deleted file mode 100644 index 8518d3167..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Exception/InvalidPasswordException.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace UniSpy.Server.WebServer.Module.Auth -{ - public class InvalidPasswordException : Auth.Exception - { - public InvalidPasswordException() : base("Password is invalid!", AuthErrorCode.InvalidPassword) - { - } - public InvalidPasswordException(string message) : base(message, AuthErrorCode.InvalidPassword) - { - } - public InvalidPasswordException(string message, System.Exception innerException) : base(message, AuthErrorCode.InvalidPassword, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Exception/InvalidProfileException.cs b/src/Servers/WebServer/src/Module/Auth/Exception/InvalidProfileException.cs deleted file mode 100644 index 628215391..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Exception/InvalidProfileException.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace UniSpy.Server.WebServer.Module.Auth -{ - public class InvalidProfileException : Auth.Exception - { - public InvalidProfileException() : base("Profile is invalid!", AuthErrorCode.InvalidProfile) - { - } - public InvalidProfileException(string message) : base(message, AuthErrorCode.InvalidProfile) - { - } - public InvalidProfileException(string message, System.Exception innerException) : base(message, AuthErrorCode.InvalidProfile, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Exception/ParseException.cs b/src/Servers/WebServer/src/Module/Auth/Exception/ParseException.cs deleted file mode 100644 index 528bfef05..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Exception/ParseException.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace UniSpy.Server.WebServer.Module.Auth -{ - public class ParseException : Auth.Exception - { - public ParseException() : base("Parse error!", AuthErrorCode.ParseError) - { - } - public ParseException(string message) : base(message, AuthErrorCode.ParseError) - { - } - public ParseException(string message, System.Exception innerException) : base(message, AuthErrorCode.ParseError, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Exception/ServerException.cs b/src/Servers/WebServer/src/Module/Auth/Exception/ServerException.cs deleted file mode 100644 index 4fae7aa48..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Exception/ServerException.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace UniSpy.Server.WebServer.Module.Auth -{ - public class ServerException : Auth.Exception - { - public ServerException() : base("Server error!", AuthErrorCode.ServerError) - { - } - public ServerException(string message) : base(message, AuthErrorCode.ServerError) - { - } - public ServerException(string message, System.Exception innerException) : base(message, AuthErrorCode.ServerError, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Exception/ServerInitException.cs b/src/Servers/WebServer/src/Module/Auth/Exception/ServerInitException.cs deleted file mode 100644 index 0e6cfb7d9..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Exception/ServerInitException.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace UniSpy.Server.WebServer.Module.Auth -{ - public class ServerInitException : Auth.Exception - { - public ServerInitException() : base("An unknown error occur when initializing server!", AuthErrorCode.ServerError) - { - } - public ServerInitException(string message) : base(message, AuthErrorCode.ServerError) - { - } - public ServerInitException(string message, System.Exception innerException) : base(message, AuthErrorCode.ServerError, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Exception/UniqueNickExpredException.cs b/src/Servers/WebServer/src/Module/Auth/Exception/UniqueNickExpredException.cs deleted file mode 100644 index aa622a8fc..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Exception/UniqueNickExpredException.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace UniSpy.Server.WebServer.Module.Auth -{ - public class UniqueNickExpredException : Auth.Exception - { - public UniqueNickExpredException() : base("Nickname is invalid at creating new profile!", AuthErrorCode.UniqueNickExpired) - { - } - public UniqueNickExpredException(string message) : base(message, AuthErrorCode.UniqueNickExpired) - { - } - public UniqueNickExpredException(string message, System.Exception innerException) : base(message, AuthErrorCode.UniqueNickExpired, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Exception/UserNotFoundException.cs b/src/Servers/WebServer/src/Module/Auth/Exception/UserNotFoundException.cs deleted file mode 100644 index f010feeee..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Exception/UserNotFoundException.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace UniSpy.Server.WebServer.Module.Auth -{ - public class UserNotFoundException : Auth.Exception - { - public UserNotFoundException() : base("User not found!", AuthErrorCode.UserNotFound) - { - } - public UserNotFoundException(string message) : base(message, AuthErrorCode.UserNotFound) - { - } - public UserNotFoundException(string message, System.Exception innerException) : base(message, AuthErrorCode.UserNotFound, innerException) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Handler/LoginProfileHandler.cs b/src/Servers/WebServer/src/Module/Auth/Handler/LoginProfileHandler.cs deleted file mode 100644 index f5d11fdd8..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Handler/LoginProfileHandler.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Contract.Request; -using UniSpy.Server.WebServer.Module.Auth.Contract.Response; -using UniSpy.Server.WebServer.Module.Auth.Contract.Result; -using UniSpy.Server.Core.Database.DatabaseModel; -using UniSpy.Server.WebServer.Application; - -namespace UniSpy.Server.WebServer.Module.Auth.Handler -{ - - public class LoginProfileHandler : CmdHandlerBase - { - protected new LoginProfileRequest _request => (LoginProfileRequest)base._request; - protected new LoginResultBase _result { get => (LoginResultBase)base._result; set => base._result = value; } - public LoginProfileHandler(Client client, LoginProfileRequest request) : base(client, request) - { - _result = new LoginProfileResult(); - } - protected override void DataOperation() - { - using (var db = new UniSpyContext()) - { - var result = from p in db.Profiles - join u in db.Users on p.Userid equals u.UserId - join sp in db.Subprofiles on p.ProfileId equals sp.ProfileId - where sp.Uniquenick == _request.Uniquenick - && sp.Cdkeyenc == _request.CDKey - && sp.PartnerId == _request.PartnerCode - && sp.NamespaceId == _request.NamespaceId - && u.Email == _request.Email - select new { u, p, sp }; - if (result.Count() != 1) - { - throw new Auth.Exception("No account exists with the provided email address."); - } - var data = result.First(); - _result.UserId = data.u.UserId; - _result.ProfileId = data.p.ProfileId; - _result.CdKeyHash = data.sp.Cdkeyenc; - // currently we set this to uniquenick - _result.ProfileNick = data.sp.Uniquenick; - } - } - protected override void ResponseConstruct() - { - _response = new LoginProfileResponse(_request, _result); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Handler/LoginProfileWithGameIdHandler.cs b/src/Servers/WebServer/src/Module/Auth/Handler/LoginProfileWithGameIdHandler.cs deleted file mode 100644 index c5d07aad6..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Handler/LoginProfileWithGameIdHandler.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Module.Auth.Contract.Request; -using UniSpy.Server.WebServer.Module.Auth.Contract.Response; -using UniSpy.Server.Core.Database.DatabaseModel; -using UniSpy.Server.WebServer.Application; - -namespace UniSpy.Server.WebServer.Module.Auth.Handler -{ - - public sealed class LoginProfileWithGameIdHandler : LoginProfileHandler - { - private new LoginProfileWithGameIdRequest _request => (LoginProfileWithGameIdRequest)base._request; - public LoginProfileWithGameIdHandler(Client client, LoginProfileWithGameIdRequest request) : base(client, request) - { - } - protected override void DataOperation() - { - using (var db = new UniSpyContext()) - { - var result = from p in db.Profiles - join u in db.Users on p.Userid equals u.UserId - join sp in db.Subprofiles on p.ProfileId equals sp.ProfileId - where sp.Uniquenick == _request.Uniquenick - && sp.Cdkeyenc == _request.CDKey - && sp.PartnerId == _request.PartnerCode - && sp.NamespaceId == _request.NamespaceId - && u.Email == _request.Email - // we do not care about game id now - select new { u, p, sp }; - if (result.Count() != 1) - { - throw new Auth.Exception("No account exists with the provided email address."); - } - var data = result.First(); - _result.UserId = data.u.UserId; - _result.ProfileId = data.p.ProfileId; - _result.CdKeyHash = data.sp.Cdkeyenc; - // currently we set this to uniquenick - _result.ProfileNick = data.sp.Uniquenick; - } - } - - protected override void ResponseConstruct() - { - // base.ResponseConstruct(); - _response = new LoginProfileWithGameIdResponse(_request, _result); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Handler/LoginPs3CertHandler.cs b/src/Servers/WebServer/src/Module/Auth/Handler/LoginPs3CertHandler.cs deleted file mode 100644 index 3bf5ebbde..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Handler/LoginPs3CertHandler.cs +++ /dev/null @@ -1,17 +0,0 @@ -using UniSpy.Server.WebServer.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Contract.Request; -using UniSpy.Server.WebServer.Module.Auth.Contract.Result; -using UniSpy.Server.WebServer.Application; - -namespace UniSpy.Server.WebServer.Module.Auth.Handler -{ - - public class LoginPs3CertHandler : CmdHandlerBase - { - protected new LoginPs3CertRequest _request => (LoginPs3CertRequest)base._request; - protected new LoginPs3CertResult _result => (LoginPs3CertResult)base._result; - public LoginPs3CertHandler(Client client, LoginPs3CertRequest request) : base(client, request) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Handler/LoginPs3CertWithGameIdHandler.cs b/src/Servers/WebServer/src/Module/Auth/Handler/LoginPs3CertWithGameIdHandler.cs deleted file mode 100644 index 99ad582db..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Handler/LoginPs3CertWithGameIdHandler.cs +++ /dev/null @@ -1,15 +0,0 @@ - -using UniSpy.Server.WebServer.Module.Auth.Contract.Request; -using UniSpy.Server.WebServer.Application; - -namespace UniSpy.Server.WebServer.Module.Auth.Handler -{ - - public sealed class LoginPs3CertWithGameIdHandler : LoginPs3CertHandler - { - private new LoginPs3CertWithGameIdRequest _request => (LoginPs3CertWithGameIdRequest)base._request; - public LoginPs3CertWithGameIdHandler(Client client, LoginPs3CertWithGameIdRequest request) : base(client, request) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Handler/LoginRemoteAuthHandler.cs b/src/Servers/WebServer/src/Module/Auth/Handler/LoginRemoteAuthHandler.cs deleted file mode 100644 index b4b797056..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Handler/LoginRemoteAuthHandler.cs +++ /dev/null @@ -1,53 +0,0 @@ -using UniSpy.Server.WebServer.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Contract.Request; -using UniSpy.Server.WebServer.Module.Auth.Contract.Response; -using UniSpy.Server.WebServer.Module.Auth.Contract.Result; -using UniSpy.Server.Core.Database.DatabaseModel; -using UniSpy.Server.WebServer.Application; - -namespace UniSpy.Server.WebServer.Module.Auth.Handler -{ - - public class LoginRemoteAuthHandler : CmdHandlerBase - { - protected new LoginRemoteAuthRequest _request => (LoginRemoteAuthRequest)base._request; - protected new LoginResultBase _result { get => (LoginResultBase)base._result; set => base._result = value; } - public LoginRemoteAuthHandler(Client client, LoginRemoteAuthRequest request) : base(client, request) - { - _result = new LoginRemoteAuthResult(); - } - protected override void DataOperation() - { - using (var db = new UniSpyContext()) - { - // var result = from p in db.Profiles - // join u in db.Users on p.Userid equals u.UserId - // join sp in db.Subprofiles on p.ProfileId equals sp.ProfileId - // where sp.Authtoken == _request.AuthToken && - // sp.PartnerId == _request.GameId - // select new { u, p, sp }; - // if (result.Count() != 1) - // { - // throw new System.Exception("No account exists with the provided email address."); - // } - - // var data = result.First(); - // _result.UserId = data.u.UserId; - // _result.ProfileId = data.p.ProfileId; - // _result.CdKeyHash = data.sp.Cdkeyenc; - // currently we set this to uniquenick - // _result.ProfileNick = data.sp.Uniquenick; - _result.UserId = 1; - _result.ProfileId = 1; - _result.CdKeyHash = "00000000000000s"; - _result.ProfileNick = "xiaojiuwo"; - _result.UniqueNick = "xiaojiuwo"; - } - } - protected override void ResponseConstruct() - { - _response = new LoginRemoteAuthResponse(_request, _result); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Handler/LoginRemoteAuthWithGameIdHandler.cs b/src/Servers/WebServer/src/Module/Auth/Handler/LoginRemoteAuthWithGameIdHandler.cs deleted file mode 100644 index 1e5403dce..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Handler/LoginRemoteAuthWithGameIdHandler.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Module.Auth.Contract.Request; -using UniSpy.Server.WebServer.Module.Auth.Contract.Response; -using UniSpy.Server.Core.Database.DatabaseModel; -using UniSpy.Server.WebServer.Application; - -namespace UniSpy.Server.WebServer.Module.Auth.Handler -{ - - public sealed class LoginRemoteAuthWithGameIdHandler : LoginRemoteAuthHandler - { - private new LoginRemoteAuthWithGameIdRequest _request => (LoginRemoteAuthWithGameIdRequest)base._request; - public LoginRemoteAuthWithGameIdHandler(Client client, LoginRemoteAuthWithGameIdRequest request) : base(client, request) - { - } - protected override void DataOperation() - { - using (var db = new UniSpyContext()) - { - var result = from p in db.Profiles - join u in db.Users on p.Userid equals u.UserId - join sp in db.Subprofiles on p.ProfileId equals sp.ProfileId - where sp.Authtoken == _request.AuthToken && - sp.PartnerId == _request.GameId - select new { u, p, sp }; - if (result.Count() != 1) - { - throw new System.Exception("No account exists with the provided email address."); - } - - var data = result.First(); - _result.UserId = data.u.UserId; - _result.ProfileId = data.p.ProfileId; - _result.CdKeyHash = data.sp.Cdkeyenc; - // currently we set this to uniquenick - _result.ProfileNick = data.sp.Uniquenick; - _result.UniqueNick = data.sp.Uniquenick; - } - } - protected override void ResponseConstruct() - { - // base.ResponseConstruct(); - _response = new LoginRemoteAuthWithGameIdResponse(_request, _result); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Handler/LoginUniqueNickHandler.cs b/src/Servers/WebServer/src/Module/Auth/Handler/LoginUniqueNickHandler.cs deleted file mode 100644 index 5d63120c6..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Handler/LoginUniqueNickHandler.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Abstraction; -using UniSpy.Server.WebServer.Module.Auth.Contract.Request; -using UniSpy.Server.WebServer.Module.Auth.Contract.Response; -using UniSpy.Server.WebServer.Module.Auth.Contract.Result; -using UniSpy.Server.Core.Database.DatabaseModel; -using UniSpy.Server.WebServer.Application; - -namespace UniSpy.Server.WebServer.Module.Auth.Handler -{ - - public class LoginUniqueNickHandler : CmdHandlerBase - { - protected new LoginUniqueNickRequest _request => (LoginUniqueNickRequest)base._request; - protected new LoginResultBase _result { get => (LoginResultBase)base._result; set => base._result = value; } - public LoginUniqueNickHandler(Client client, LoginUniqueNickRequest request) : base(client, request) - { - _result = new LoginUniqueNickResult(); - } - protected override void DataOperation() - { - using (var db = new UniSpyContext()) - { - var result = from p in db.Profiles - join u in db.Users on p.Userid equals u.UserId - join sp in db.Subprofiles on p.ProfileId equals sp.ProfileId - where sp.Uniquenick == _request.Uniquenick - && sp.NamespaceId == _request.NamespaceId - // && u.Password == _request.Password - select new { u, p, sp }; - if (result.Count() != 1) - { - throw new Auth.Exception("No account exists with the provided email address."); - } - var data = result.First(); - _result.UserId = data.u.UserId; - _result.ProfileId = data.p.ProfileId; - // _result.CdKeyHash = data.sp.Cdkeyenc; - _result.CdKeyHash = "xxxxxxxxxxx"; - // currently we set this to uniquenick - _result.ProfileNick = data.p.Nick; - _result.UniqueNick = data.sp.Uniquenick; - } - } - protected override void ResponseConstruct() - { - _response = new LoginUniqueNickResponse(_request, _result); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Auth/Handler/LoginUniqueNickWithGameIdHandler.cs b/src/Servers/WebServer/src/Module/Auth/Handler/LoginUniqueNickWithGameIdHandler.cs deleted file mode 100644 index f0f49911d..000000000 --- a/src/Servers/WebServer/src/Module/Auth/Handler/LoginUniqueNickWithGameIdHandler.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Module.Auth.Contract.Request; -using UniSpy.Server.WebServer.Module.Auth.Contract.Response; -using UniSpy.Server.Core.Database.DatabaseModel; -using UniSpy.Server.WebServer.Application; - -namespace UniSpy.Server.WebServer.Module.Auth.Handler -{ - - public sealed class LoginUniqueNickWithGameIdHandler : LoginUniqueNickHandler - { - private new LoginUniqueNickRequest _request => (LoginUniqueNickRequest)base._request; - public LoginUniqueNickWithGameIdHandler(Client client, LoginUniqueNickRequest request) : base(client, request) - { - } - protected override void DataOperation() - { - using (var db = new UniSpyContext()) - { - var result = from p in db.Profiles - join u in db.Users on p.Userid equals u.UserId - join sp in db.Subprofiles on p.ProfileId equals sp.ProfileId - where sp.Uniquenick == _request.Uniquenick && - sp.NamespaceId == _request.NamespaceId - select new { u, p, sp }; - if (result.Count() != 1) - { - throw new System.Exception("No account exists with the provided email address."); - } - var data = result.First(); - _result.UserId = data.u.UserId; - _result.ProfileId = data.p.ProfileId; - // _result.CdKeyHash = data.sp.Cdkeyenc; - _result.CdKeyHash = "xxxxxxxxxxx"; - // currently we set this to uniquenick - _result.ProfileNick = data.p.Nick; - _result.UniqueNick = data.sp.Uniquenick; - } - } - protected override void ResponseConstruct() - { - // base.ResponseConstruct(); - _response = new LoginUniqueNickWithGameIdResponse(_request, _result); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Direct2Game/Abstraction/RequestBase.cs b/src/Servers/WebServer/src/Module/Direct2Game/Abstraction/RequestBase.cs deleted file mode 100644 index 3d598a433..000000000 --- a/src/Servers/WebServer/src/Module/Direct2Game/Abstraction/RequestBase.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace UniSpy.Server.WebServer.Module.Direct2Game.Abstraction; - -public class RequestBase : UniSpy.Server.WebServer.Abstraction.RequestBase -{ - public RequestBase(string rawRequest) : base(rawRequest) - { - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Direct2Game/Abstraction/ResponseBase.cs b/src/Servers/WebServer/src/Module/Direct2Game/Abstraction/ResponseBase.cs deleted file mode 100644 index f797222b8..000000000 --- a/src/Servers/WebServer/src/Module/Direct2Game/Abstraction/ResponseBase.cs +++ /dev/null @@ -1,10 +0,0 @@ -using UniSpy.Server.WebServer.Module.Direct2Game.Contract; - -namespace UniSpy.Server.WebServer.Module.Direct2Game.Abstraction; -public class ResponseBase : UniSpy.Server.WebServer.Abstraction.ResponseBase -{ - public ResponseBase(RequestBase request, ResultBase result) : base(request, result) - { - _content = new Direct2GameSoapEnvelope(); - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Direct2Game/Abstraction/ResultBase.cs b/src/Servers/WebServer/src/Module/Direct2Game/Abstraction/ResultBase.cs deleted file mode 100644 index d4dda2698..000000000 --- a/src/Servers/WebServer/src/Module/Direct2Game/Abstraction/ResultBase.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace UniSpy.Server.WebServer.Module.Direct2Game.Abstraction; -public class ResultBase : UniSpy.Server.WebServer.Abstraction.ResultBase -{ - public ResultBase() - { - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Direct2Game/Contract/Direct2GameSoapEnvelope.cs b/src/Servers/WebServer/src/Module/Direct2Game/Contract/Direct2GameSoapEnvelope.cs deleted file mode 100644 index 2b9a7e923..000000000 --- a/src/Servers/WebServer/src/Module/Direct2Game/Contract/Direct2GameSoapEnvelope.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Xml.Linq; -using UniSpy.Server.WebServer.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Direct2Game.Contract -{ - public sealed class Direct2GameSoapEnvelope : SoapEnvelopBase - { - public static XNamespace Direct2GameNamespace = "http://gamespy.net/commerce/2009/02"; - public Direct2GameSoapEnvelope() : base("gsc", Direct2GameNamespace) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Direct2Game/Contract/Request/GetPurchaseHistoryRequest.cs b/src/Servers/WebServer/src/Module/Direct2Game/Contract/Request/GetPurchaseHistoryRequest.cs deleted file mode 100644 index 47ffb73c6..000000000 --- a/src/Servers/WebServer/src/Module/Direct2Game/Contract/Request/GetPurchaseHistoryRequest.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Module.Direct2Game.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Direct2Game.Contract.Request -{ - - public class GetPurchaseHistoryRequest : RequestBase - { - public int GameId { get; private set; } - - public string AccessToken { get; private set; } - - public string Proof { get; private set; } - - public GetPurchaseHistoryRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - if (!_contentElement.Descendants().Any(p => p.Name.LocalName == "gameid")) - { - throw new Exception("gameid is missing from the request"); - } - var gameid = _contentElement.Descendants().First(p => p.Name.LocalName == "gameid").Value; - GameId = int.Parse(gameid); - - if (!_contentElement.Descendants().Any(p => p.Name.LocalName == "proof")) - { - throw new Exception("proof is missing from the request"); - } - Proof = _contentElement.Descendants().First(p => p.Name.LocalName == "proof").Value; - - if (!_contentElement.Descendants().Any(p => p.Name.LocalName == "accesstoken")) - { - throw new Exception("accesstoken is missing from the request"); - } - AccessToken = _contentElement.Descendants().First(p => p.Name.LocalName == "accesstoken").Value; - } - - } -} diff --git a/src/Servers/WebServer/src/Module/Direct2Game/Contract/Request/GetStoreAvailabilityRequest.cs b/src/Servers/WebServer/src/Module/Direct2Game/Contract/Request/GetStoreAvailabilityRequest.cs deleted file mode 100644 index 354d6a266..000000000 --- a/src/Servers/WebServer/src/Module/Direct2Game/Contract/Request/GetStoreAvailabilityRequest.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Module.Direct2Game.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Direct2Game.Contract.Request -{ - - public class GetStoreAvailabilityRequest : RequestBase - { - public int GameId { get; private set; } - public int Version { get; private set; } - public string Region { get; private set; } - public string AccessToken { get; private set; } - - public GetStoreAvailabilityRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - if (!_contentElement.Descendants().Any(p => p.Name.LocalName == "gameid")) - { - throw new Exception("gameid is missing from the request"); - } - var gameid = _contentElement.Descendants().First(p => p.Name.LocalName == "gameid").Value; - GameId = int.Parse(gameid); - - if (!_contentElement.Descendants().Any(p => p.Name.LocalName == "version")) - { - throw new Exception("version is missing from the request"); - } - var version = _contentElement.Descendants().First(p => p.Name.LocalName == "version").Value; - Version = int.Parse(version); - - if (!_contentElement.Descendants().Any(p => p.Name.LocalName == "region")) - { - throw new Exception("region is missing from the request"); - } - Region = _contentElement.Descendants().First(p => p.Name.LocalName == "region").Value; - - if (!_contentElement.Descendants().Any(p => p.Name.LocalName == "accesstoken")) - { - throw new Exception("accesstoken is missing from the request"); - } - AccessToken = _contentElement.Descendants().First(p => p.Name.LocalName == "accesstoken").Value; - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Direct2Game/Contract/Response/GetPurchaseHistoryResponse.cs b/src/Servers/WebServer/src/Module/Direct2Game/Contract/Response/GetPurchaseHistoryResponse.cs deleted file mode 100644 index e8258e710..000000000 --- a/src/Servers/WebServer/src/Module/Direct2Game/Contract/Response/GetPurchaseHistoryResponse.cs +++ /dev/null @@ -1,26 +0,0 @@ - -using UniSpy.Server.WebServer.Module.Direct2Game.Abstraction; -using UniSpy.Server.WebServer.Module.Direct2Game.Contract.Result; - -namespace UniSpy.Server.WebServer.Module.Direct2Game.Contract.Response -{ - public class GetPurchaseHistoryResponse : ResponseBase - { - private new GetPurchaseHistoryResult _result => (GetPurchaseHistoryResult)base._result; - - public GetPurchaseHistoryResponse(RequestBase request, ResultBase result) : base(request, result) - { - } - - public override void Build() - { - _content.Add("GetPurchaseHistoryResult"); - _content.Add("status"); - _content.Add("code", _result.Status); - _content.ChangeToElement("GetPurchaseHistoryResult"); - _content.Add("orderpurchases"); - _content.Add("count", 0); - base.Build(); - } - } -} diff --git a/src/Servers/WebServer/src/Module/Direct2Game/Contract/Response/GetStoreAvailabilityResponse.cs b/src/Servers/WebServer/src/Module/Direct2Game/Contract/Response/GetStoreAvailabilityResponse.cs deleted file mode 100644 index 000a19c3b..000000000 --- a/src/Servers/WebServer/src/Module/Direct2Game/Contract/Response/GetStoreAvailabilityResponse.cs +++ /dev/null @@ -1,24 +0,0 @@ -using UniSpy.Server.WebServer.Module.Direct2Game.Abstraction; -using UniSpy.Server.WebServer.Module.Direct2Game.Contract.Result; - -namespace UniSpy.Server.WebServer.Module.Direct2Game.Contract.Request -{ - public class GetStoreAvailabilityResponse : ResponseBase - { - private new GetStoreAvailabilityResult _result => (GetStoreAvailabilityResult)base._result; - - public GetStoreAvailabilityResponse(RequestBase request, ResultBase result) : base(request, result) - { - } - - public override void Build() - { - _content.Add("GetStoreAvailabilityResult"); - _content.Add("status"); - _content.Add("code", _result.Status); - _content.ChangeToElement("GetStoreAvailabilityResult"); - _content.Add("storestatusid", _result.StoreResult); - base.Build(); - } - } -} diff --git a/src/Servers/WebServer/src/Module/Direct2Game/Contract/Result/GetPurchaseHistoryResult.cs b/src/Servers/WebServer/src/Module/Direct2Game/Contract/Result/GetPurchaseHistoryResult.cs deleted file mode 100644 index 9bc9060e4..000000000 --- a/src/Servers/WebServer/src/Module/Direct2Game/Contract/Result/GetPurchaseHistoryResult.cs +++ /dev/null @@ -1,9 +0,0 @@ -using UniSpy.Server.WebServer.Module.Direct2Game.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Direct2Game.Contract.Result -{ - public class GetPurchaseHistoryResult : ResultBase - { - public int Status { get; set; } - } -} diff --git a/src/Servers/WebServer/src/Module/Direct2Game/Contract/Result/GetStoreAvailabilityResult.cs b/src/Servers/WebServer/src/Module/Direct2Game/Contract/Result/GetStoreAvailabilityResult.cs deleted file mode 100644 index ea9659d92..000000000 --- a/src/Servers/WebServer/src/Module/Direct2Game/Contract/Result/GetStoreAvailabilityResult.cs +++ /dev/null @@ -1,14 +0,0 @@ -using UniSpy.Server.WebServer.Module.Direct2Game.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Direct2Game.Contract.Result -{ - public class GetStoreAvailabilityResult : ResultBase - { - public int Status { get; set; } - public int StoreResult { get; set; } - - public GetStoreAvailabilityResult() - { - } - } -} diff --git a/src/Servers/WebServer/src/Module/Direct2Game/Handler/GetPurchaseHistoryHandler.cs b/src/Servers/WebServer/src/Module/Direct2Game/Handler/GetPurchaseHistoryHandler.cs deleted file mode 100644 index 3d92db8d1..000000000 --- a/src/Servers/WebServer/src/Module/Direct2Game/Handler/GetPurchaseHistoryHandler.cs +++ /dev/null @@ -1,32 +0,0 @@ -using UniSpy.Server.WebServer.Abstraction; -using UniSpy.Server.WebServer.Module.Direct2Game.Contract.Request; -using UniSpy.Server.WebServer.Module.Direct2Game.Contract.Response; -using UniSpy.Server.WebServer.Module.Direct2Game.Contract.Result; -using UniSpy.Server.WebServer.Application; - -namespace UniSpy.Server.WebServer.Module.Direct2Game.Handler -{ - - internal class GetPurchaseHistoryHandler : CmdHandlerBase - { - protected new GetPurchaseHistoryRequest _request => (GetPurchaseHistoryRequest)base._request; - protected new GetPurchaseHistoryResult _result = new GetPurchaseHistoryResult(); - - public GetPurchaseHistoryHandler(Client client, GetPurchaseHistoryRequest request) : base(client, request) - { - - } - - protected override void DataOperation() - { - - } - - protected override void ResponseConstruct() - { - _result.Status = 0; - - _response = new GetPurchaseHistoryResponse(_request, _result); - } - } -} diff --git a/src/Servers/WebServer/src/Module/Direct2Game/Handler/GetStoreAvailabilityHandler.cs b/src/Servers/WebServer/src/Module/Direct2Game/Handler/GetStoreAvailabilityHandler.cs deleted file mode 100644 index cb7678ce9..000000000 --- a/src/Servers/WebServer/src/Module/Direct2Game/Handler/GetStoreAvailabilityHandler.cs +++ /dev/null @@ -1,35 +0,0 @@ -using UniSpy.Server.WebServer.Abstraction; -using UniSpy.Server.WebServer.Module.Direct2Game.Contract.Request; -using UniSpy.Server.WebServer.Module.Direct2Game.Contract.Result; -using UniSpy.Server.WebServer.Application; - -namespace UniSpy.Server.WebServer.Module.Direct2Game.Handler -{ - - public class GetStoreAvailabilityHandler : CmdHandlerBase - { - protected new GetStoreAvailabilityRequest _request => (GetStoreAvailabilityRequest)base._request; - protected new GetStoreAvailabilityResult _result = new GetStoreAvailabilityResult(); - public GetStoreAvailabilityHandler(Client client, GetStoreAvailabilityRequest request) : base(client, request) - { - - } - - protected override void DataOperation() - { - _result.Status = 0; - _result.StoreResult = 10; - /* - * 10 -> Store is available - * 50 -> ERROR - * 100 -> Cannot download DLC information from backend server - */ - } - - protected override void ResponseConstruct() - { - _response = new GetStoreAvailabilityResponse(_request, _result); - } - - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/IngameAd/Contract/Request/GetTargettedAdRequest.cs b/src/Servers/WebServer/src/Module/IngameAd/Contract/Request/GetTargettedAdRequest.cs deleted file mode 100644 index ebeee71e3..000000000 --- a/src/Servers/WebServer/src/Module/IngameAd/Contract/Request/GetTargettedAdRequest.cs +++ /dev/null @@ -1,14 +0,0 @@ -using UniSpy.Server.WebServer.Abstraction; - - -namespace UniSpy.Server.WebServer.Module.IngameAd.Contract.Request -{ - - public class GetTargettedAdRequest : RequestBase - { - public override void Parse() - { - throw new System.NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/IngameAd/Contract/Request/ReportAdUsageRequest.cs b/src/Servers/WebServer/src/Module/IngameAd/Contract/Request/ReportAdUsageRequest.cs deleted file mode 100644 index 9a7ee4dfe..000000000 --- a/src/Servers/WebServer/src/Module/IngameAd/Contract/Request/ReportAdUsageRequest.cs +++ /dev/null @@ -1,14 +0,0 @@ -using UniSpy.Server.WebServer.Abstraction; - - -namespace UniSpy.Server.WebServer.Module.IngameAd.Contract.Request -{ - - public class ReportAdUsageRequest : RequestBase - { - public override void Parse() - { - throw new System.NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/PatchingAndTracking/Contract/Request/MotdRequest.cs b/src/Servers/WebServer/src/Module/PatchingAndTracking/Contract/Request/MotdRequest.cs deleted file mode 100644 index cd1832df7..000000000 --- a/src/Servers/WebServer/src/Module/PatchingAndTracking/Contract/Request/MotdRequest.cs +++ /dev/null @@ -1,14 +0,0 @@ -using UniSpy.Server.WebServer.Abstraction; - - -namespace UniSpy.Server.WebServer.Module.PatchingAndTracking.Contract.Request -{ - - public class MotdRequest : RequestBase - { - public override void Parse() - { - throw new System.NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/PatchingAndTracking/Contract/Request/VercheckRequest.cs b/src/Servers/WebServer/src/Module/PatchingAndTracking/Contract/Request/VercheckRequest.cs deleted file mode 100644 index b8ba41a9f..000000000 --- a/src/Servers/WebServer/src/Module/PatchingAndTracking/Contract/Request/VercheckRequest.cs +++ /dev/null @@ -1,14 +0,0 @@ -using UniSpy.Server.WebServer.Abstraction; - - -namespace UniSpy.Server.WebServer.Module.PatchingAndTracking.Contract.Request -{ - - public class VercheckRequest : RequestBase - { - public override void Parse() - { - throw new System.NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Racing/Contract/Request/GetContestDataRequest.cs b/src/Servers/WebServer/src/Module/Racing/Contract/Request/GetContestDataRequest.cs deleted file mode 100644 index b6975b981..000000000 --- a/src/Servers/WebServer/src/Module/Racing/Contract/Request/GetContestDataRequest.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Abstraction; - - -namespace UniSpy.Server.WebServer.Module.Racing.Contract.Request -{ - - public class GetContestDataRequest : RequestBase - { - public int GameId { get; set; } - public int RegionId { get; set; } - public int CourseId { get; set; } - public GetContestDataRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - var gameid = _contentElement.Descendants().Where(p => p.Name.LocalName == "gameid").First().Value; - GameId = int.Parse(gameid); - var regionid = _contentElement.Descendants().Where(p => p.Name.LocalName == "regionid").First().Value; - RegionId = int.Parse(regionid); - var courseid = _contentElement.Descendants().Where(p => p.Name.LocalName == "courseid").First().Value; - CourseId = int.Parse(courseid); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Racing/Contract/Request/GetFriendRankingsRequest.cs b/src/Servers/WebServer/src/Module/Racing/Contract/Request/GetFriendRankingsRequest.cs deleted file mode 100644 index 5a2d7dc23..000000000 --- a/src/Servers/WebServer/src/Module/Racing/Contract/Request/GetFriendRankingsRequest.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Abstraction; - - -namespace UniSpy.Server.WebServer.Module.Racing.Contract.Request -{ - - public class GetFriendRankingsRequest : RequestBase - { - public int GameId { get; set; } - public int RegionId { get; set; } - public int CourseId { get; set; } - public int ProfileId { get; set; } - public GetFriendRankingsRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - var gameid = _contentElement.Descendants().Where(p => p.Name.LocalName == "gameid").First().Value; - GameId = int.Parse(gameid); - var regionid = _contentElement.Descendants().Where(p => p.Name.LocalName == "regionid").First().Value; - RegionId = int.Parse(regionid); - var courseid = _contentElement.Descendants().Where(p => p.Name.LocalName == "courseid").First().Value; - CourseId = int.Parse(courseid); - var profileid = _contentElement.Descendants().Where(p => p.Name.LocalName == "profileid").First().Value; - ProfileId = int.Parse(profileid); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Racing/Contract/Request/GetRegionalDataRequest.cs b/src/Servers/WebServer/src/Module/Racing/Contract/Request/GetRegionalDataRequest.cs deleted file mode 100644 index cf75cbb9a..000000000 --- a/src/Servers/WebServer/src/Module/Racing/Contract/Request/GetRegionalDataRequest.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Abstraction; - - -namespace UniSpy.Server.WebServer.Module.Racing.Contract.Request -{ - - public class GetRegionalDataRequest : RequestBase - { - public int GameId { get; set; } - public int RegionId { get; set; } - public GetRegionalDataRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - var gameid = _contentElement.Descendants().Where(p => p.Name.LocalName == "gameid").First().Value; - GameId = int.Parse(gameid); - var regionid = _contentElement.Descendants().Where(p => p.Name.LocalName == "regionid").First().Value; - RegionId = int.Parse(regionid); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Racing/Contract/Request/GetTenAboveRankingsRequest.cs b/src/Servers/WebServer/src/Module/Racing/Contract/Request/GetTenAboveRankingsRequest.cs deleted file mode 100644 index 716691514..000000000 --- a/src/Servers/WebServer/src/Module/Racing/Contract/Request/GetTenAboveRankingsRequest.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Abstraction; - - -namespace UniSpy.Server.WebServer.Module.Racing.Contract.Request -{ - - public class GetTenAboveRankingsRequest : RequestBase - { - public int GameId { get; set; } - public int RegionId { get; set; } - public int CourseId { get; set; } - public int ProfileId { get; set; } - public GetTenAboveRankingsRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - var gameid = _contentElement.Descendants().Where(p => p.Name.LocalName == "gameid").First().Value; - GameId = int.Parse(gameid); - var regionid = _contentElement.Descendants().Where(p => p.Name.LocalName == "regionid").First().Value; - RegionId = int.Parse(regionid); - var courseid = _contentElement.Descendants().Where(p => p.Name.LocalName == "courseid").First().Value; - CourseId = int.Parse(courseid); - var profileid = _contentElement.Descendants().Where(p => p.Name.LocalName == "profileid").First().Value; - ProfileId = int.Parse(profileid); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Racing/Contract/Request/GetTopTenRankingsRequest.cs b/src/Servers/WebServer/src/Module/Racing/Contract/Request/GetTopTenRankingsRequest.cs deleted file mode 100644 index 4a0da75b4..000000000 --- a/src/Servers/WebServer/src/Module/Racing/Contract/Request/GetTopTenRankingsRequest.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Abstraction; - - -namespace UniSpy.Server.WebServer.Module.Racing.Contract.Request -{ - - public class GetTopTenRankingsRequest : RequestBase - { - public int GameId { get; set; } - public int RegionId { get; set; } - public int CourseId { get; set; } - public GetTopTenRankingsRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - var gameid = _contentElement.Descendants().Where(p => p.Name.LocalName == "gameid").First().Value; - GameId = int.Parse(gameid); - var regionid = _contentElement.Descendants().Where(p => p.Name.LocalName == "regionid").First().Value; - RegionId = int.Parse(regionid); - var courseid = _contentElement.Descendants().Where(p => p.Name.LocalName == "courseid").First().Value; - CourseId = int.Parse(courseid); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Racing/Contract/Request/SubmitGhostRequest.cs b/src/Servers/WebServer/src/Module/Racing/Contract/Request/SubmitGhostRequest.cs deleted file mode 100644 index 2579c459f..000000000 --- a/src/Servers/WebServer/src/Module/Racing/Contract/Request/SubmitGhostRequest.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Abstraction; - - -namespace UniSpy.Server.WebServer.Module.Racing.Contract.Request -{ - - public class SubmitGhostRequest : RequestBase - { - public int GameId { get; set; } - public int RegionId { get; set; } - public int CourseId { get; set; } - public int ProfileId { get; set; } - public string Score { get; set; } - public int FileId { get; set; } - public SubmitGhostRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - var gameid = _contentElement.Descendants().Where(p => p.Name.LocalName == "gameid").First().Value; - GameId = int.Parse(gameid); - var regionid = _contentElement.Descendants().Where(p => p.Name.LocalName == "regionid").First().Value; - RegionId = int.Parse(regionid); - var courseid = _contentElement.Descendants().Where(p => p.Name.LocalName == "courseid").First().Value; - CourseId = int.Parse(courseid); - var profileid = _contentElement.Descendants().Where(p => p.Name.LocalName == "profileid").First().Value; - ProfileId = int.Parse(profileid); - var score = _contentElement.Descendants().Where(p => p.Name.LocalName == "score").First().Value; - Score = score; - var fileid = _contentElement.Descendants().Where(p => p.Name.LocalName == "fileid").First().Value; - FileId = int.Parse(fileid); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Racing/Contract/Request/SubmitScoresRequest.cs b/src/Servers/WebServer/src/Module/Racing/Contract/Request/SubmitScoresRequest.cs deleted file mode 100644 index a22944dd6..000000000 --- a/src/Servers/WebServer/src/Module/Racing/Contract/Request/SubmitScoresRequest.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Abstraction; - - -namespace UniSpy.Server.WebServer.Module.Racing.Contract.Request -{ - - public class SubmitScoresRequest : RequestBase - { - public int GameData { get; set; } - public int RegionId { get; set; } - public int ProfileId { get; set; } - public int GameId { get; set; } - public int ScoreMode { get; set; } - public string ScoreDatas { get; set; } - public SubmitScoresRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - var gamedata = _contentElement.Descendants().Where(p => p.Name.LocalName == "gamedata").First().Value; - GameData = int.Parse(gamedata); - var regionid = _contentElement.Descendants().Where(p => p.Name.LocalName == "regionid").First().Value; - RegionId = int.Parse(regionid); - var gameid = _contentElement.Descendants().Where(p => p.Name.LocalName == "gameid").First().Value; - GameId = int.Parse(gameid); - var scoremode = _contentElement.Descendants().Where(p => p.Name.LocalName == "scoremode").First().Value; - ScoreMode = int.Parse(scoremode); - var scoredatas = _contentElement.Descendants().Where(p => p.Name.LocalName == "scoredatas").First().Value; - ScoreDatas = scoredatas; - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Sake/Abstraction/CmdHandlerBase.cs b/src/Servers/WebServer/src/Module/Sake/Abstraction/CmdHandlerBase.cs deleted file mode 100644 index 3d9ef2a14..000000000 --- a/src/Servers/WebServer/src/Module/Sake/Abstraction/CmdHandlerBase.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using Newtonsoft.Json; -using UniSpy.Server.WebServer.Contract; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.WebServer.Module.Sake.Abstraction -{ - public abstract class CmdHandlerBase : WebServer.Abstraction.CmdHandlerBase - { - protected new RequestBase _request => (RequestBase)base._request; - protected string _sakeFilePath => $"./sake_storage/{_request.GameId}/{_request.TableId}/sake_storage.json"; - protected List _sakeData { get; private set; } - protected CmdHandlerBase(IClient client, IRequest request) : base(client, request) - { - } - - protected override void RequestCheck() - { - base.RequestCheck(); - //todo get secretkey from database where gameid - } - protected override void DataOperation() - { - if (!File.Exists(_sakeFilePath)) - { - new FileInfo(_sakeFilePath).Directory.Create(); - } - else - { - _sakeData = JsonConvert.DeserializeObject>(File.ReadAllText(_sakeFilePath)); - } - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Sake/Abstraction/RequestBase.cs b/src/Servers/WebServer/src/Module/Sake/Abstraction/RequestBase.cs deleted file mode 100644 index 9d52e3482..000000000 --- a/src/Servers/WebServer/src/Module/Sake/Abstraction/RequestBase.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Linq; - -namespace UniSpy.Server.WebServer.Module.Sake.Abstraction -{ - public abstract class RequestBase : WebServer.Abstraction.RequestBase - { - public int GameId { get; set; } - public string SecretKey { get; set; } - public string LoginTicket { get; set; } - public string TableId { get; set; } - - public RequestBase(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - var gameId = _contentElement.Descendants().Where(p => p.Name.LocalName == "gameid").First().Value; - GameId = int.Parse(gameId); - var secretKey = _contentElement.Descendants().Where(p => p.Name.LocalName == "secretKey").First().Value; - SecretKey = secretKey; - var loginTicket = _contentElement.Descendants().Where(p => p.Name.LocalName == "loginTicket").First().Value; - LoginTicket = loginTicket; - var tableid = _contentElement.Descendants().Where(p => p.Name.LocalName == "tableid").First().Value; - TableId = tableid; - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Sake/Abstraction/ResponseBase.cs b/src/Servers/WebServer/src/Module/Sake/Abstraction/ResponseBase.cs deleted file mode 100644 index f9b513a92..000000000 --- a/src/Servers/WebServer/src/Module/Sake/Abstraction/ResponseBase.cs +++ /dev/null @@ -1,12 +0,0 @@ -using UniSpy.Server.WebServer.Module.Sake.Contract; - -namespace UniSpy.Server.WebServer.Module.Sake.Abstraction -{ - public abstract class ResponseBase : WebServer.Abstraction.ResponseBase - { - public ResponseBase(RequestBase request, ResultBase result) : base(request, result) - { - _content = new SakeSoapEnvelope(); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Sake/Abstraction/ResultBase.cs b/src/Servers/WebServer/src/Module/Sake/Abstraction/ResultBase.cs deleted file mode 100644 index cb4adaa82..000000000 --- a/src/Servers/WebServer/src/Module/Sake/Abstraction/ResultBase.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace UniSpy.Server.WebServer.Module.Sake.Abstraction; - -public class ResultBase : UniSpy.Server.WebServer.Abstraction.ResultBase -{ -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Sake/Contract/Request/CreateRecordRequest.cs b/src/Servers/WebServer/src/Module/Sake/Contract/Request/CreateRecordRequest.cs deleted file mode 100644 index 0c7fafb3b..000000000 --- a/src/Servers/WebServer/src/Module/Sake/Contract/Request/CreateRecordRequest.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Xml.Linq; -using UniSpy.Server.WebServer.Contract; -using UniSpy.Server.WebServer.Module.Sake.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Sake.Contract.Request -{ - - public class CreateRecordRequest : RequestBase - { - public List Values { get; set; } - public CreateRecordRequest(string rawRequest) : base(rawRequest) - { - Values = new List(); - } - - public override void Parse() - { - base.Parse(); - var valuesNode = _contentElement.Descendants().Where(p => p.Name.LocalName == "values").First(); - foreach (XElement element in valuesNode.Nodes()) - { - // TODO move this code to RecordFieldObject as static method which takes XElement as input returns a List - // first we find the value name by string "name" - var name = element.Descendants().Where(p => p.Name.LocalName == "name").First().Value; - // then we get the value type by string "value" - var type = element.Descendants().Where(p => p.Name.LocalName == "value").First().Descendants().First().Name.LocalName; - // then we get the actual value by its type we get before - var value = element.Descendants().Where(p => p.Name.LocalName == type).First().Value; - Values.Add(new RecordFieldObject(value, name, type)); - } - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Sake/Contract/Request/DeleteRecordRequest.cs b/src/Servers/WebServer/src/Module/Sake/Contract/Request/DeleteRecordRequest.cs deleted file mode 100644 index 0d3930fb8..000000000 --- a/src/Servers/WebServer/src/Module/Sake/Contract/Request/DeleteRecordRequest.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Module.Sake.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Sake.Contract.Request -{ - - public class DeleteRecordRequest : RequestBase - { - public string RecordId { get; set; } - public DeleteRecordRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - var recordid = _contentElement.Descendants().Where(p => p.Name.LocalName == "recordid").First().Value; - RecordId = recordid; - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Sake/Contract/Request/GetMyRecordsRequest.cs b/src/Servers/WebServer/src/Module/Sake/Contract/Request/GetMyRecordsRequest.cs deleted file mode 100644 index d4b73e907..000000000 --- a/src/Servers/WebServer/src/Module/Sake/Contract/Request/GetMyRecordsRequest.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Xml.Linq; -using UniSpy.Server.WebServer.Contract; -using UniSpy.Server.WebServer.Module.Sake.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Sake.Contract.Request -{ - - public class GetMyRecordsRequest : RequestBase - { - public List Fields { get; set; } - public GetMyRecordsRequest(string rawRequest) : base(rawRequest) - { - Fields = new List(); - } - - public override void Parse() - { - base.Parse(); - var fieldsNode = _contentElement.Descendants().Where(p => p.Name.LocalName == "fields").First(); - foreach (XElement element in fieldsNode.Nodes()) - { - Fields.Add(new FieldObject(element.Value, element.Name.LocalName)); - } - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Sake/Contract/Request/GetRandomRecordsRequest.cs b/src/Servers/WebServer/src/Module/Sake/Contract/Request/GetRandomRecordsRequest.cs deleted file mode 100644 index a8d2f8d34..000000000 --- a/src/Servers/WebServer/src/Module/Sake/Contract/Request/GetRandomRecordsRequest.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Xml.Linq; -using UniSpy.Server.WebServer.Contract; -using UniSpy.Server.WebServer.Module.Sake.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Sake.Contract.Request -{ - - public class GetRandomRecordsRequest : RequestBase - { - public string Max { get; set; } - public List Fields { get; set; } - public GetRandomRecordsRequest(string rawRequest) : base(rawRequest) - { - Fields = new List(); - } - - public override void Parse() - { - base.Parse(); - var max = _contentElement.Descendants().Where(p => p.Name.LocalName == "max").First().Value; - Max = max; - var fieldsNode = _contentElement.Descendants().Where(p => p.Name.LocalName == "fields").First(); - foreach (XElement element in fieldsNode.Nodes()) - { - Fields.Add(new FieldObject(element.Value, element.Name.LocalName)); - } - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Sake/Contract/Request/GetRecordLimitRequest.cs b/src/Servers/WebServer/src/Module/Sake/Contract/Request/GetRecordLimitRequest.cs deleted file mode 100644 index 0403556ff..000000000 --- a/src/Servers/WebServer/src/Module/Sake/Contract/Request/GetRecordLimitRequest.cs +++ /dev/null @@ -1,13 +0,0 @@ - -using UniSpy.Server.WebServer.Module.Sake.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Sake.Contract.Request -{ - - public class GetRecordLimitRequest : RequestBase - { - public GetRecordLimitRequest(string rawRequest) : base(rawRequest) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Sake/Contract/Request/GetSpecificRecordsRequest.cs b/src/Servers/WebServer/src/Module/Sake/Contract/Request/GetSpecificRecordsRequest.cs deleted file mode 100644 index 1af9cfa02..000000000 --- a/src/Servers/WebServer/src/Module/Sake/Contract/Request/GetSpecificRecordsRequest.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Xml.Linq; -using UniSpy.Server.WebServer.Contract; -using UniSpy.Server.WebServer.Module.Sake.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Sake.Contract.Request -{ - - public class GetSpecificRecordsRequest : RequestBase - { - public List RecordIds { get; set; } - public List Fields { get; set; } - public GetSpecificRecordsRequest(string rawRequest) : base(rawRequest) - { - RecordIds = new List(); - Fields = new List(); - } - - public override void Parse() - { - base.Parse(); - var recordidsNode = _contentElement.Descendants().Where(p => p.Name.LocalName == "recordids").First(); - foreach (XElement element in recordidsNode.Nodes()) - { - RecordIds.Add(new FieldObject(element.Value, element.Name.LocalName)); - } - var fieldsNode = _contentElement.Descendants().Where(p => p.Name.LocalName == "fields").First(); - foreach (XElement element in fieldsNode.Nodes()) - { - Fields.Add(new FieldObject(element.Value, element.Name.LocalName)); - } - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Sake/Contract/Request/RateRecordRequest.cs b/src/Servers/WebServer/src/Module/Sake/Contract/Request/RateRecordRequest.cs deleted file mode 100644 index d2da530c7..000000000 --- a/src/Servers/WebServer/src/Module/Sake/Contract/Request/RateRecordRequest.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Module.Sake.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Sake.Contract.Request -{ - - public class RateRecordRequest : RequestBase - { - public string RecordId { get; set; } - public string Rating { get; set; } - public RateRecordRequest(string rawRequest) : base(rawRequest) - { - } - - public override void Parse() - { - base.Parse(); - var recordid = _contentElement.Descendants().Where(p => p.Name.LocalName == "recordid").First().Value; - RecordId = recordid; - var rating = _contentElement.Descendants().Where(p => p.Name.LocalName == "rating").First().Value; - Rating = rating; - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Sake/Contract/Request/SearchForRecordsRequest.cs b/src/Servers/WebServer/src/Module/Sake/Contract/Request/SearchForRecordsRequest.cs deleted file mode 100644 index 668bbb39c..000000000 --- a/src/Servers/WebServer/src/Module/Sake/Contract/Request/SearchForRecordsRequest.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Xml.Linq; -using UniSpy.Server.WebServer.Contract; -using UniSpy.Server.WebServer.Module.Sake.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Sake.Contract.Request -{ - - public class SearchForRecordsRequest : RequestBase - { - public string Filter { get; set; } - public string Sort { get; set; } - public string Offset { get; set; } - public string Max { get; set; } - public string Surrounding { get; set; } - public string OwnerIds { get; set; } - public string CacheFlag { get; set; } - - public List Fields { get; set; } - public SearchForRecordsRequest(string rawRequest) : base(rawRequest) - { - Fields = new List(); - } - - public override void Parse() - { - base.Parse(); - var filter = _contentElement.Descendants().Where(p => p.Name.LocalName == "filter").First().Value; - Filter = filter; - var sort = _contentElement.Descendants().Where(p => p.Name.LocalName == "sort").First().Value; - Sort = sort; - var offset = _contentElement.Descendants().Where(p => p.Name.LocalName == "offset").First().Value; - Offset = offset; - var max = _contentElement.Descendants().Where(p => p.Name.LocalName == "max").First().Value; - Max = max; - var surrounding = _contentElement.Descendants().Where(p => p.Name.LocalName == "surrounding").First().Value; - Surrounding = surrounding; - var ownerids = _contentElement.Descendants().Where(p => p.Name.LocalName == "ownerids").First().Value; - OwnerIds = ownerids; - var cacheFlag = _contentElement.Descendants().Where(p => p.Name.LocalName == "cacheFlag").First().Value; - CacheFlag = cacheFlag; - var fieldsNode = _contentElement.Descendants().Where(p => p.Name.LocalName == "fields").First(); - foreach (XElement element in fieldsNode.Nodes()) - { - Fields.Add(new FieldObject(element.Value, element.Name.LocalName)); - } - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Sake/Contract/Request/UpdateRecordRequest.cs b/src/Servers/WebServer/src/Module/Sake/Contract/Request/UpdateRecordRequest.cs deleted file mode 100644 index c01daba4b..000000000 --- a/src/Servers/WebServer/src/Module/Sake/Contract/Request/UpdateRecordRequest.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Xml.Linq; -using UniSpy.Server.WebServer.Contract; -using UniSpy.Server.WebServer.Module.Sake.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Sake.Contract.Request -{ - - public class UpdateRecordRequest : RequestBase - { - public string RecordId { get; set; } - - public List Values { get; set; } - public UpdateRecordRequest(string rawRequest) : base(rawRequest) - { - Values = new List(); - } - - public override void Parse() - { - base.Parse(); - var recordid = _contentElement.Descendants().Where(p => p.Name.LocalName == "recordid").First().Value; - RecordId = recordid; - var valuesNode = _contentElement.Descendants().Where(p => p.Name.LocalName == "values").First(); - foreach (XElement element in valuesNode.Nodes()) - { - // TODO move this code to RecordFieldObject as static method which takes XElement as input returns a List - // first we find the value name by string "name" - var name = element.Descendants().Where(p => p.Name.LocalName == "name").First().Value; - // then we get the value type by string "value" - var type = element.Descendants().Where(p => p.Name.LocalName == "value").First().Descendants().First().Name.LocalName; - // then we get the actual value by its type we get before - var value = element.Descendants().Where(p => p.Name.LocalName == type).First().Value; - Values.Add(new RecordFieldObject(value, name, type)); - } - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Sake/Contract/Response/CreateRecordResponse.cs b/src/Servers/WebServer/src/Module/Sake/Contract/Response/CreateRecordResponse.cs deleted file mode 100644 index 2af6986da..000000000 --- a/src/Servers/WebServer/src/Module/Sake/Contract/Response/CreateRecordResponse.cs +++ /dev/null @@ -1,28 +0,0 @@ -using UniSpy.Server.WebServer.Module.Sake.Abstraction; -using UniSpy.Server.WebServer.Module.Sake.Contract.Request; -using UniSpy.Server.WebServer.Module.Sake.Contract.Result; - -namespace UniSpy.Server.WebServer.Module.Sake.Contract.Response -{ - public sealed class CreateRecordResponse : ResponseBase - { - public new CreateRecordResult _result => (CreateRecordResult)base._result; - public new CreateRecordRequest _request => (CreateRecordRequest)base._request; - public CreateRecordResponse(RequestBase request, ResultBase result) : base(request, result) - { - } - public override void Build() - { - base.Build(); - _content.Add("CreateRecordResult"); - _content.Add("tableid", _result.TableID); - _content.Add("recordid", _result.RecordID); - - foreach (var field in _result.Fields) - { - _content.Add("fileds", field); - } - base.Build(); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Sake/Contract/Response/GetMyRecordResponse.cs b/src/Servers/WebServer/src/Module/Sake/Contract/Response/GetMyRecordResponse.cs deleted file mode 100644 index 3c1735594..000000000 --- a/src/Servers/WebServer/src/Module/Sake/Contract/Response/GetMyRecordResponse.cs +++ /dev/null @@ -1,16 +0,0 @@ -using UniSpy.Server.WebServer.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Sake.Contract.Response -{ - public class GetMyRecordResponse : ResponseBase - { - public GetMyRecordResponse(RequestBase request, ResultBase result) : base(request, result) - { - } - - public override void Build() - { - throw new System.NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Sake/Contract/Response/SearchForRecordResponse.cs b/src/Servers/WebServer/src/Module/Sake/Contract/Response/SearchForRecordResponse.cs deleted file mode 100644 index 1f49fdabc..000000000 --- a/src/Servers/WebServer/src/Module/Sake/Contract/Response/SearchForRecordResponse.cs +++ /dev/null @@ -1,22 +0,0 @@ -using UniSpy.Server.WebServer.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Sake.Contract.Response -{ - internal class SearchForRecordResponse : ResponseBase - { - public SearchForRecordResponse(RequestBase request, ResultBase result) : base(request, result) - { - } - - public override void Build() - { - SendingBuffer = "Success" + - "" + - "ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg" + - "0" + - "" + - ""; - // base.Build(); - } - } -} diff --git a/src/Servers/WebServer/src/Module/Sake/Contract/Result/CreateRecordResult.cs b/src/Servers/WebServer/src/Module/Sake/Contract/Result/CreateRecordResult.cs deleted file mode 100644 index ea3be3757..000000000 --- a/src/Servers/WebServer/src/Module/Sake/Contract/Result/CreateRecordResult.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.WebServer.Module.Sake.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Sake.Contract.Result -{ - public sealed class CreateRecordResult : ResultBase - { - public string TableID { get; init; } - public string RecordID { get; init; } - public List Fields { get; private set; } - public CreateRecordResult() - { - Fields = new List(); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Sake/Contract/Result/GetMyRecordsResult.cs b/src/Servers/WebServer/src/Module/Sake/Contract/Result/GetMyRecordsResult.cs deleted file mode 100644 index 5d04d883a..000000000 --- a/src/Servers/WebServer/src/Module/Sake/Contract/Result/GetMyRecordsResult.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.WebServer.Abstraction; -using UniSpy.Server.WebServer.Contract; - -namespace UniSpy.Server.WebServer.Module.Sake.Contract.Result -{ - public class GetMyRecordsResult : ResultBase - { - public List Records { get; private set; } - public GetMyRecordsResult() - { - Records = new List(); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Sake/Contract/SakeSoapEnvelope.cs b/src/Servers/WebServer/src/Module/Sake/Contract/SakeSoapEnvelope.cs deleted file mode 100644 index 3b65b7f7c..000000000 --- a/src/Servers/WebServer/src/Module/Sake/Contract/SakeSoapEnvelope.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Xml.Linq; -using UniSpy.Server.WebServer.Abstraction; - -namespace UniSpy.Server.WebServer.Module.Sake.Contract -{ - public sealed class SakeSoapEnvelope : SoapEnvelopBase - { - public static XNamespace SakeNamespace = "http://gamespy.net/sake"; - public SakeSoapEnvelope() : base("ns1", SakeNamespace) - { - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Sake/Handler/CreateRecordHandler.cs b/src/Servers/WebServer/src/Module/Sake/Handler/CreateRecordHandler.cs deleted file mode 100644 index 5e035d6ea..000000000 --- a/src/Servers/WebServer/src/Module/Sake/Handler/CreateRecordHandler.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Newtonsoft.Json; -using UniSpy.Server.WebServer.Module.Sake.Abstraction; -using UniSpy.Server.WebServer.Module.Sake.Contract.Request; -using UniSpy.Server.WebServer.Application; - -namespace UniSpy.Server.WebServer.Module.Sake.Handler -{ - - public class CreateRecordHandler : CmdHandlerBase - { - protected new CreateRecordRequest _request => (CreateRecordRequest)base._request; - public CreateRecordHandler(Client client, CreateRecordRequest request) : base(client, request) - { - } - protected override void DataOperation() - { - base.DataOperation(); - var jsonStr = JsonConvert.SerializeObject(_request.Values); - // File.WriteAllText(_sakeFilePath, jsonStr); - throw new System.NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/src/Module/Sake/Handler/GetMyRecordsHandler.cs b/src/Servers/WebServer/src/Module/Sake/Handler/GetMyRecordsHandler.cs deleted file mode 100644 index 0bb210cc6..000000000 --- a/src/Servers/WebServer/src/Module/Sake/Handler/GetMyRecordsHandler.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Linq; -using UniSpy.Server.WebServer.Module.Sake.Abstraction; -using UniSpy.Server.WebServer.Module.Sake.Contract.Request; -using UniSpy.Server.WebServer.Module.Sake.Contract.Result; -using UniSpy.Server.WebServer.Application; - -namespace UniSpy.Server.WebServer.Module.Sake.Handler -{ - - public class GetMyRecordsHandler : CmdHandlerBase - { - private new GetMyRecordsRequest _request => (GetMyRecordsRequest)base._request; - private new GetMyRecordsResult _result { get => (GetMyRecordsResult)base._result; set => base._result = value; } - public GetMyRecordsHandler(Client client, GetMyRecordsRequest request) : base(client, request) - { - } - protected override void DataOperation() - { - base.DataOperation(); - _result = new GetMyRecordsResult(); - - foreach (var field in _request.Fields) - { - var record = _sakeData.FirstOrDefault(x => x.FieldName == field.FieldName && x.FiledType == field.FiledType); - if (record is not null) - { - _result.Records.Add(record); - } - } - } - } -} diff --git a/src/Servers/WebServer/src/Module/Sake/Handler/SearchForRecordsHandler.cs b/src/Servers/WebServer/src/Module/Sake/Handler/SearchForRecordsHandler.cs deleted file mode 100644 index 8425a9ddf..000000000 --- a/src/Servers/WebServer/src/Module/Sake/Handler/SearchForRecordsHandler.cs +++ /dev/null @@ -1,22 +0,0 @@ -using UniSpy.Server.WebServer.Abstraction; -using UniSpy.Server.WebServer.Module.Sake.Contract.Response; -using UniSpy.Server.WebServer.Module.Sake.Contract.Request; -using UniSpy.Server.WebServer.Application; - -namespace UniSpy.Server.WebServer.Module.Sake.Handler -{ - - internal class SearchForRecordsHandler : CmdHandlerBase - { - protected new SearchForRecordsRequest _request => (SearchForRecordsRequest)base._request; - public SearchForRecordsHandler(Client client, SearchForRecordsRequest request) : base(client, request) - { - - } - - protected override void ResponseConstruct() - { - _response = new SearchForRecordResponse(_request, null); - } - } -} diff --git a/src/Servers/WebServer/src/UniSpy.Server.WebServer.csproj b/src/Servers/WebServer/src/UniSpy.Server.WebServer.csproj deleted file mode 100755 index 8b9381e25..000000000 --- a/src/Servers/WebServer/src/UniSpy.Server.WebServer.csproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - Exe - net6.0 - ..\..\..\..\common\Icon\UniSpy_Logo.ico - Linux - ..\..\..\.. - - - ..\..\..\..\build\$(Configuration) - - - ..\..\..\..\build\$(Configuration) - - - - - - - - \ No newline at end of file diff --git a/src/Servers/WebServer/src/UniSpy_Logo.ico b/src/Servers/WebServer/src/UniSpy_Logo.ico deleted file mode 100644 index 0bdce3c8c..000000000 Binary files a/src/Servers/WebServer/src/UniSpy_Logo.ico and /dev/null differ diff --git a/src/Servers/WebServer/test/Atlas/RawRequests.cs b/src/Servers/WebServer/test/Atlas/RawRequests.cs deleted file mode 100644 index 816fa0784..000000000 --- a/src/Servers/WebServer/test/Atlas/RawRequests.cs +++ /dev/null @@ -1,75 +0,0 @@ -namespace UniSpy.Server.WebServer.Test.Atlas -{ - public class RawRequests - { - public const string CreateMatchlessSession = - @" - - - - XXXXXX - XXXXXX - 0 - - - "; - - public const string CreateSession = - @" - - - - XXXXXX - XXXXXX - 0 - - - "; - - public const string SetReportIntention = - @" - - - - XXXXXX - XXXXXX - 0 - 0 - 0 - XXXXXX - - - "; - - public const string SubmitReport = - @" - - - - XXXXXX - XXXXXX - 0 - 0 - 0 - XXXXXX - - - "; - } -} diff --git a/src/Servers/WebServer/test/Atlas/RequestsTest.cs b/src/Servers/WebServer/test/Atlas/RequestsTest.cs deleted file mode 100644 index 366020b21..000000000 --- a/src/Servers/WebServer/test/Atlas/RequestsTest.cs +++ /dev/null @@ -1,55 +0,0 @@ -using Xunit; -using UniSpy.Server.WebServer.Module.Atlas.Contract.Request; - -namespace UniSpy.Server.WebServer.Test.Atlas -{ - public class RequestsTest - { - // - // These are the SOAP requests of ATLAS (Competition) - // Endpoint: {FQDN}/competition/ - // - [Fact] - public void CreateMatchlessSession() - { - var request = new CreateMatchlessSessionRequest(RawRequests.CreateMatchlessSession); - request.Parse(); - Assert.Equal("XXXXXX", request.Certificate); - Assert.Equal("XXXXXX", request.Proof); - Assert.Equal("0", request.GameId.ToString()); - } - [Fact] - public void CreateSession() - { - var request = new CreateSessionRequest(RawRequests.CreateSession); - request.Parse(); - Assert.Equal("XXXXXX", request.Certificate); - Assert.Equal("XXXXXX", request.Proof); - Assert.Equal("0", request.GameId.ToString()); - } - [Fact] - public void SetReportIntention() - { - var request = new SetReportIntentionRequest(RawRequests.SetReportIntention); - request.Parse(); - Assert.Equal("XXXXXX", request.Certificate); - Assert.Equal("XXXXXX", request.Proof); - Assert.Equal("0", request.CsId.ToString()); - Assert.Equal("0", request.CcId.ToString()); - Assert.Equal("0", request.GameId.ToString()); - Assert.Equal("XXXXXX", request.Authoritative); - } - [Fact] - public void SubmitReport() - { - var request = new SubmitReportRequest(RawRequests.SubmitReport); - request.Parse(); - Assert.Equal("XXXXXX", request.Certificate); - Assert.Equal("XXXXXX", request.Proof); - Assert.Equal("0", request.CsId.ToString()); - Assert.Equal("0", request.CcId.ToString()); - Assert.Equal("0", request.GameId.ToString()); - Assert.Equal("XXXXXX", request.Authoritative); - } - } -} diff --git a/src/Servers/WebServer/test/Auth/HandlerTest.cs b/src/Servers/WebServer/test/Auth/HandlerTest.cs deleted file mode 100644 index 384ceaf79..000000000 --- a/src/Servers/WebServer/test/Auth/HandlerTest.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Collections.Generic; -using Moq; -using UniSpy.Server.WebServer.Handler; -using UniSpy.Server.WebServer.Test.Auth; -using UniSpy.Server.Core.Abstraction.Interface; -using Xunit; -using UniSpy.Server.WebServer.Application; - -namespace UniSpy.Server.WebServer.Test -{ - public class HandlerTest - { - private Client _client = MokeObject.CreateClient(); - - [Fact] - public void SwitcherTest() - { - // Given - var requests = new List(){ - RawRequests.LoginProfile, - RawRequests.LoginPs3Cert, - RawRequests.LoginRemoteAuth, - RawRequests.LoginUniqueNick - }; - foreach (var req in requests) - { - var requestMock = new Mock(); - requestMock.Setup(r => r.Body).Returns(req); - var sw = new CmdSwitcher(_client, requestMock.Object); - sw.Handle(); - } - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/test/Auth/RawRequests.cs b/src/Servers/WebServer/test/Auth/RawRequests.cs deleted file mode 100644 index 80463d8fe..000000000 --- a/src/Servers/WebServer/test/Auth/RawRequests.cs +++ /dev/null @@ -1,86 +0,0 @@ -namespace UniSpy.Server.WebServer.Test.Auth -{ - public class RawRequests - { - public const string LoginProfile = - @" - - - - 1 - 0 - 0 - 0 - spyguy@unispy.org - spyguy - XXXXXXXXXXX - - XXXXXXXXXXX - - - - "; - - public const string LoginPs3Cert = - @" - - - - 0 - 0 - 0 - 0001 - 0 - 0001 - - - "; - - public const string LoginRemoteAuth = - @" - - - - 1 - 0 - 0 - 0 - XXXXXXXXXXX - XXXXXXXXXXX - - - "; - - public const string LoginUniqueNick = - @" - - - - 1 - 0 - 0 - spyguy - - XXXXXXXXXXX - - - - "; - } -} diff --git a/src/Servers/WebServer/test/Auth/RequestsTest.cs b/src/Servers/WebServer/test/Auth/RequestsTest.cs deleted file mode 100644 index 96b68812f..000000000 --- a/src/Servers/WebServer/test/Auth/RequestsTest.cs +++ /dev/null @@ -1,163 +0,0 @@ -using System; -using System.Numerics; -using UniSpy.Server.WebServer.Application; -using UniSpy.Server.WebServer.Module.Auth.Contract; -using UniSpy.Server.WebServer.Module.Auth.Contract.Request; -using UniSpy.Server.WebServer.Module.Direct2Game.Contract.Response; -using UniSpy.Server.Core.Extension; -using Xunit; - -namespace UniSpy.Server.WebServer.Test.Auth -{ - public class RequestsTest - { - // - // These are the SOAP requests of AUTH - // Endpoint: {FQDN}/AuthService/ - // - [Fact] - public void LoginProfile() - { - var request = new LoginProfileWithGameIdRequest(RawRequests.LoginProfile); - request.Parse(); - Assert.Equal("1", request.Version.ToString()); - Assert.Equal("0", request.GameId.ToString()); - Assert.Equal("0", request.PartnerCode.ToString()); - Assert.Equal("0", request.NamespaceId.ToString()); - Assert.Equal("spyguy@unispy.org", request.Email); - Assert.Equal("spyguy", request.Uniquenick); - Assert.Equal("XXXXXXXXXXX", request.CDKey); - Assert.Equal("XXXXXXXXXXX", request.Password); - } - [Fact] - public void LoginPs3Cert() - { - var request = new LoginPs3CertWithGameIdRequest(RawRequests.LoginPs3Cert); - request.Parse(); - Assert.Equal(0, request.GameId); - Assert.Equal(1, request.PartnerCode); - Assert.Equal("0001", request.PS3cert); - } - [Fact] - public void LoginRemoteAuth() - { - var request = new LoginRemoteAuthWithGameIdRequest(RawRequests.LoginRemoteAuth); - request.Parse(); - Assert.Equal("1", request.Version.ToString()); - Assert.Equal("0", request.GameId.ToString()); - Assert.Equal("0", request.PartnerCode.ToString()); - Assert.Equal("0", request.NamespaceId.ToString()); - Assert.Equal("XXXXXXXXXXX", request.AuthToken); - Assert.Equal("XXXXXXXXXXX", request.Challenge); - } - [Fact] - public void LoginUniqueNick() - { - var request = new LoginUniqueNickRequest(RawRequests.LoginUniqueNick); - request.Parse(); - Assert.Equal("1", request.Version.ToString()); - Assert.Equal("0", request.PartnerCode.ToString()); - Assert.Equal("0", request.NamespaceId.ToString()); - Assert.Equal("spyguy", request.Uniquenick); - Assert.Equal("XXXXXXXXXXX", request.Password); - } - - [Fact] - public void CustomRSATest() - { - BigInteger publicExponent = BigInteger.Parse("010001", System.Globalization.NumberStyles.AllowHexSpecifier); - BigInteger privateExponent = BigInteger.Parse("00af12efb486a5f594f4b86d153cef694fba59bde5005411e271ad9e53ae41bd3183b3b06459de85907bfdcee256180bd450f7f547dd1c81f57e14b477a48cef415f957de5ea723a0050be386fd2c1369761340f23ed43aa4299926107e3c56845ea32685a7ced12a32bfd6b6a2aefe8b8b9fdf0893f486342f36fd6000d691ee1", System.Globalization.NumberStyles.AllowHexSpecifier); - - BigInteger Modulo = BigInteger.Parse("00e2201247fcb3ef29e45e842eee4a1b072ae59c115de6f4e0bb857b4e9282b2ee2b6ce1aef46a5eea7ad7bd0a5a4a969a186e2dd1e379e4a27a0e2120f49da702d4a3b892f5c776fee869d218f145b6e32f32b71063a0222addc256e8fdc977b2324a71370777295d45240f4f5fdf7cd7ab9c2393fdce0781c5118b9e1e905537", System.Globalization.NumberStyles.AllowHexSpecifier); - - var data = new BigInteger(123); - - var enc = BigInteger.ModPow(data, privateExponent, Modulo); - var dec = BigInteger.ModPow(enc, publicExponent, Modulo); - - var signature = enc.ToString("x"); - var bytes = enc.ToByteArray(isBigEndian: true); - var gamespyFormat = BitConverter.ToString(bytes).Replace("-", string.Empty); - - var sigbytes = "0001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003020300C06082A864886F70D020505000410".FromHexStringToBytes(); - } - - - [Fact] - public void XmlTest() - { - // XNamespace SoapEnvelopNamespace = "http://schemas.xmlsoap.org/soap/envelope/"; - - // var env = new XElement(SoapEnvelopNamespace + "Envelope", - // new XAttribute(XNamespace.Xmlns + "SOAP-ENV", SoapEnvelopNamespace), - // new XAttribute(XNamespace.Xmlns + "SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"), - // new XAttribute(XNamespace.Xmlns + "xsi", "http://www.w3.org/2001/XMLSchema-instance"), - // new XAttribute(XNamespace.Xmlns + "xsd", "http://www.w3.org/2001/XMLSchema")); - // XNamespace SakeNamespace = "http://gamespy.net/sake"; - // var attri = new XAttribute(XNamespace.Xmlns + "ns1", SakeNamespace); - // env.Add(attri); - // env.SetAttributeValue(XNamespace.Xmlns + "ns1", SakeNamespace); - // var soapEnvelop = new XElement(SoapXElement.Direct2GameSoapHeader); - // soapEnvelop.Add(new XElement(SoapXElement.SoapEnvelopNamespace + "Body")); - // var nn1 = soapEnvelop.NextNode; - - // var _soapBody = new XElement(SoapXElement.SoapEnvelopNamespace + "Body"); - // _soapBody.Add(new XElement(SoapXElement.Direct2GameNamespace + "GetStoreAvailabilityResult")); - - // var e = _soapBody.Elements().First(); - // e.Add(new XElement(SoapXElement.Direct2GameNamespace + "status")); - // e.Elements().First().Add(new XElement(SoapXElement.Direct2GameNamespace + "code", 0)); - // e.Add(new XElement(SoapXElement.Direct2GameNamespace + "storestatusid", 1)); - - // _soapBody.Add(e); - // soapEnvelop.Add(e); - // soapEnvelop.DescendantNodes(); - // soapEnvelop.Descendants(); - // soapEnvelop.Nodes(); - // var nn = soapEnvelop.NextNode; - // var auth = new AuthSoapEnvelope(); - // auth.Add("heello", "hello"); - // auth.Add("bitch", "bitch"); - // // var nn2 = soapEnvelop.FirstNode.NextNode.FirstNode; - // // Given - // var authEle = new AuthXElement("certificate"); - // authEle.Add("authtoken", "XXXXXXXXXXX"); - // authEle.Add("challenge", "XXXXXXXXXXX"); - // authEle.Add("email", "xiaojiuwo@gamspy.com"); - // authEle.Add("password", "XXXXXXXXXXX"); - // authEle.Add("partnercode", "0"); - // authEle.Add("uniquenick", "xiaojiuwo"); - // auth.Add("element", authEle.InnerElement); - - // When - var _content = new AuthSoapEnvelope(); - _content.Add("responseCode", 0); - _content.Add("certificate"); - _content.Add("length", 0); - _content.Add("version", 2); - _content.Add("partnercode", 2); - _content.Add("namespaceid", 4); - _content.Add("userid", 1); - _content.Add("profileid", 1); - _content.Add("expretime", ClientInfo.ExpireTime); - _content.Add("uniqueid", "xiaojiuwo"); - _content.ChangeToElement("Body"); - _content.Add("values"); - _content.Add("value1", 1); - _content.Add("value2", 2); - _content.Add("value3", 3); - // Then - } - - [Fact(Skip = "not implemented")] - public void TestName() - { - // Given - var resp = new GetPurchaseHistoryResponse(null, null); - resp.Build(); - // When - - // Then - } - } -} diff --git a/src/Servers/WebServer/test/Racing/RawRequests.cs b/src/Servers/WebServer/test/Racing/RawRequests.cs deleted file mode 100644 index 02726389d..000000000 --- a/src/Servers/WebServer/test/Racing/RawRequests.cs +++ /dev/null @@ -1,124 +0,0 @@ -namespace UniSpy.Server.WebServer.Test.Racing -{ - public class RawRequests - { - public const string GetContestData = - @" - - - - 0 - 0 - 0 - - - "; - - public const string GetFriendRankings = - @" - - - - 0 - 0 - 0 - 0 - - - "; - - public const string GetRegionalData = - @" - - - - 0 - 0 - - - "; - - public const string GetTenAboveRankings = - @" - - - - 0 - 0 - 0 - 0 - - - "; - - public const string GetTopTenRankings = - @" - - - - 0 - 0 - 0 - - - "; - - public const string SubmitGhost = - @" - - - - 0 - 0 - 0 - 0 - XXXXXX - 0 - - - "; - - public const string SubmitScores = - @" - - - - 0 - 0 - 0 - 0 - 0 - XXXXXX - - - "; - } -} diff --git a/src/Servers/WebServer/test/Racing/RequestsTest.cs b/src/Servers/WebServer/test/Racing/RequestsTest.cs deleted file mode 100644 index ba212838a..000000000 --- a/src/Servers/WebServer/test/Racing/RequestsTest.cs +++ /dev/null @@ -1,83 +0,0 @@ -using Xunit; -using UniSpy.Server.WebServer.Module.Racing.Contract.Request; - -namespace UniSpy.Server.WebServer.Test.Racing -{ - public class RequestsTest - { - // - // These are the SOAP requests of RACE - // Endpoint: {FQDN}/RaceService/ - // - [Fact] - public void GetContestData() - { - var request = new GetContestDataRequest(RawRequests.GetContestData); - request.Parse(); - Assert.Equal("0", request.GameId.ToString()); - Assert.Equal("0", request.RegionId.ToString()); - Assert.Equal("0", request.CourseId.ToString()); - } - [Fact] - public void GetFriendRankings() - { - var request = new GetFriendRankingsRequest(RawRequests.GetFriendRankings); - request.Parse(); - Assert.Equal("0", request.GameId.ToString()); - Assert.Equal("0", request.RegionId.ToString()); - Assert.Equal("0", request.CourseId.ToString()); - Assert.Equal("0", request.ProfileId.ToString()); - } - [Fact] - public void GetRegionalData() - { - var request = new GetRegionalDataRequest(RawRequests.GetRegionalData); - request.Parse(); - Assert.Equal("0", request.GameId.ToString()); - Assert.Equal("0", request.RegionId.ToString()); - } - [Fact] - public void GetTenAboveRankings() - { - var request = new GetTenAboveRankingsRequest(RawRequests.GetTenAboveRankings); - request.Parse(); - Assert.Equal("0", request.GameId.ToString()); - Assert.Equal("0", request.RegionId.ToString()); - Assert.Equal("0", request.CourseId.ToString()); - Assert.Equal("0", request.ProfileId.ToString()); - } - [Fact] - public void GetTopTenRankings() - { - var request = new GetTopTenRankingsRequest(RawRequests.GetTopTenRankings); - request.Parse(); - Assert.Equal("0", request.GameId.ToString()); - Assert.Equal("0", request.RegionId.ToString()); - Assert.Equal("0", request.CourseId.ToString()); - } - [Fact] - public void SubmitGhost() - { - var request = new SubmitGhostRequest(RawRequests.SubmitGhost); - request.Parse(); - Assert.Equal("0", request.GameId.ToString()); - Assert.Equal("0", request.RegionId.ToString()); - Assert.Equal("0", request.CourseId.ToString()); - Assert.Equal("0", request.ProfileId.ToString()); - Assert.Equal("XXXXXX", request.Score); - Assert.Equal("0", request.FileId.ToString()); - } - [Fact] - public void SubmitScores() - { - var request = new SubmitScoresRequest(RawRequests.SubmitScores); - request.Parse(); - Assert.Equal("0", request.GameData.ToString()); - Assert.Equal("0", request.RegionId.ToString()); - Assert.Equal("0", request.ProfileId.ToString()); - Assert.Equal("0", request.GameId.ToString()); - Assert.Equal("0", request.ScoreMode.ToString()); - Assert.Equal("XXXXXX", request.ScoreDatas); - } - } -} diff --git a/src/Servers/WebServer/test/Sake/HandlerTest.cs b/src/Servers/WebServer/test/Sake/HandlerTest.cs deleted file mode 100644 index 139648997..000000000 --- a/src/Servers/WebServer/test/Sake/HandlerTest.cs +++ /dev/null @@ -1,18 +0,0 @@ -using UniSpy.Server.WebServer.Module.Sake.Handler; -using UniSpy.Server.WebServer.Module.Sake.Contract.Request; -using Xunit; - -namespace UniSpy.Server.WebServer.Test.Sake -{ - public class HandlerTest - { - [Fact] - public void CreateRecordTest() - { - var client = MokeObject.CreateClient(); - var request = new CreateRecordRequest(RawRequests.CreateRecord); - var handler = new CreateRecordHandler(client, request); - Assert.Throws(() => handler.Handle()); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/test/Sake/RawRequests.cs b/src/Servers/WebServer/test/Sake/RawRequests.cs deleted file mode 100644 index 09e057360..000000000 --- a/src/Servers/WebServer/test/Sake/RawRequests.cs +++ /dev/null @@ -1,289 +0,0 @@ -namespace UniSpy.Server.WebServer.Test.Sake -{ - public class RawRequests - { - public const string GetRecordLimit = - @" - - - - 0 - XXXXXX - xxxxxxxx_YYYYYYYYYY__ - nicks - - - "; - - public const string RateRecord = - @" - - - - 0 - XXXXXX - xxxxxxxx_YYYYYYYYYY__ - test - 158 - 200 - - - "; - - public const string GetRandomRecords = - @" - - - - 0 - XXXXXX - xxxxxxxx_YYYYYYYYYY__ - levels - 1 - - recordid - score - - - - "; - - public const string GetSpecificRecords = - @" - - - - 0 - XXXXXX - xxxxxxxx_YYYYYYYYYY__ - scores - - 1 - 2 - 4 - 5 - - - recordid - ownerid - score - - - - "; - - public const string GetMyRecords = - @" - - - - 0 - XXXXXX - xxxxxxxx_YYYYYYYYYY__ - test - - recordid - ownerid - MyByte - MyShort - MyInt - MyFloat - MyAsciiString - MyUnicodeString - MyBoolean - MyDateAndTime - MyBinaryData - MyFileID - num_ratings - average_rating - - - - "; - - public const string SearchForRecords = - @" - - - - 0 - XXXXXX - xxxxxxxx_YYYYYYYYYY__ - scores - - - 0 - 3 - 0 - - 0 - - score - recordid - - - - "; - - public const string DeleteRecord = - @" - - - - 0 - XXXXXX - xxxxxxxx_YYYYYYYYYY__ - test - 150 - - - "; - - public const string UpdateRecord = - @" - - - - 0 - XXXXXX - xxxxxxxx_YYYYYYYYYY__ - test - 158 - - - MyByte - - - 123 - - - - - MyShort - - - 12345 - - - - - MyInt - - - 123456789 - - - - - MyFloat - - - 3.141593 - - - - - MyAsciiString - - - ascii - - - - - MyUnicodeString - - - unicode - - - - - MyBoolean - - - 1 - - - - - MyDateAndTime - - - 2020-05-21T11:13:41Z - - - - - MyBinaryData - - - EjRWq80= - - - - - - - "; - - public const string CreateRecord = - @" - - - - 0 - XXXXXX - xxxxxxxx_YYYYYYYYYY__ - test - - - MyAsciiString - - - this is a record - - - - - - - "; - } -} diff --git a/src/Servers/WebServer/test/Sake/RequestsTest.cs b/src/Servers/WebServer/test/Sake/RequestsTest.cs deleted file mode 100644 index 0a64118e7..000000000 --- a/src/Servers/WebServer/test/Sake/RequestsTest.cs +++ /dev/null @@ -1,181 +0,0 @@ -using UniSpy.Server.WebServer.Module.Sake.Contract.Request; -using Xunit; - -namespace UniSpy.Server.WebServer.Test.Sake -{ - public class RequestsTest - { - // - // These are the SOAP requests of SAKE - // Endpoint: {FQDN}/sake/ - // - [Fact] - public void GetRecordLimit() - { - var request = new GetRecordLimitRequest(RawRequests.GetRecordLimit); - request.Parse(); - Assert.Equal("0", request.GameId.ToString()); - Assert.Equal("XXXXXX", request.SecretKey); - Assert.Equal("xxxxxxxx_YYYYYYYYYY__", request.LoginTicket); - Assert.Equal("nicks", request.TableId); - } - [Fact] - public void RateRecord() - { - var request = new RateRecordRequest(RawRequests.RateRecord); - request.Parse(); - Assert.Equal("0", request.GameId.ToString()); - Assert.Equal("XXXXXX", request.SecretKey); - Assert.Equal("xxxxxxxx_YYYYYYYYYY__", request.LoginTicket); - Assert.Equal("test", request.TableId); - Assert.Equal("158", request.RecordId); - Assert.Equal("200", request.Rating); - } - [Fact] - public void GetRandomRecords() - { - var request = new GetRandomRecordsRequest(RawRequests.GetRandomRecords); - request.Parse(); - Assert.Equal("0", request.GameId.ToString()); - Assert.Equal("XXXXXX", request.SecretKey); - Assert.Equal("xxxxxxxx_YYYYYYYYYY__", request.LoginTicket); - Assert.Equal("levels", request.TableId); - Assert.Equal("1", request.Max); - Assert.Equal("recordid", request.Fields[0].FieldName); - Assert.Equal("string", request.Fields[0].FiledType); - Assert.Equal("score", request.Fields[1].FieldName); - Assert.Equal("string", request.Fields[1].FiledType); - } - [Fact] - public void GetSpecificRecords() - { - var request = new GetSpecificRecordsRequest(RawRequests.GetSpecificRecords); - request.Parse(); - Assert.Equal("0", request.GameId.ToString()); - Assert.Equal("XXXXXX", request.SecretKey); - Assert.Equal("xxxxxxxx_YYYYYYYYYY__", request.LoginTicket); - Assert.Equal("scores", request.TableId); - Assert.Equal("1", request.RecordIds[0].FieldName); - Assert.Equal("int", request.RecordIds[0].FiledType); - Assert.Equal("2", request.RecordIds[1].FieldName); - Assert.Equal("int", request.RecordIds[1].FiledType); - Assert.Equal("4", request.RecordIds[2].FieldName); - Assert.Equal("int", request.RecordIds[2].FiledType); - Assert.Equal("5", request.RecordIds[3].FieldName); - Assert.Equal("int", request.RecordIds[3].FiledType); - Assert.Equal("recordid", request.Fields[0].FieldName); - Assert.Equal("string", request.Fields[0].FiledType); - Assert.Equal("ownerid", request.Fields[1].FieldName); - Assert.Equal("string", request.Fields[1].FiledType); - Assert.Equal("score", request.Fields[2].FieldName); - Assert.Equal("string", request.Fields[2].FiledType); - } - [Fact] - public void GetMyRecords() - { - var request = new GetMyRecordsRequest(RawRequests.GetMyRecords); - request.Parse(); - Assert.Equal("0", request.GameId.ToString()); - Assert.Equal("XXXXXX", request.SecretKey); - Assert.Equal("xxxxxxxx_YYYYYYYYYY__", request.LoginTicket); - Assert.Equal("test", request.TableId); - Assert.Equal("recordid", request.Fields[0].FieldName); - Assert.Equal("string", request.Fields[0].FiledType); - Assert.Equal("ownerid", request.Fields[1].FieldName); - Assert.Equal("string", request.Fields[1].FiledType); - Assert.Equal("MyByte", request.Fields[2].FieldName); - Assert.Equal("string", request.Fields[2].FiledType); - Assert.Equal("MyShort", request.Fields[3].FieldName); - Assert.Equal("string", request.Fields[3].FiledType); - Assert.Equal("MyInt", request.Fields[4].FieldName); - Assert.Equal("string", request.Fields[4].FiledType); - Assert.Equal("MyFloat", request.Fields[5].FieldName); - Assert.Equal("string", request.Fields[5].FiledType); - Assert.Equal("MyAsciiString", request.Fields[6].FieldName); - Assert.Equal("string", request.Fields[6].FiledType); - Assert.Equal("MyUnicodeString", request.Fields[7].FieldName); - Assert.Equal("string", request.Fields[7].FiledType); - Assert.Equal("MyBoolean", request.Fields[8].FieldName); - Assert.Equal("string", request.Fields[8].FiledType); - Assert.Equal("MyDateAndTime", request.Fields[9].FieldName); - Assert.Equal("string", request.Fields[9].FiledType); - Assert.Equal("MyBinaryData", request.Fields[10].FieldName); - Assert.Equal("string", request.Fields[10].FiledType); - Assert.Equal("MyFileID", request.Fields[11].FieldName); - Assert.Equal("string", request.Fields[11].FiledType); - Assert.Equal("num_ratings", request.Fields[12].FieldName); - Assert.Equal("string", request.Fields[12].FiledType); - Assert.Equal("average_rating", request.Fields[13].FieldName); - Assert.Equal("string", request.Fields[13].FiledType); - } - [Fact] - public void SearchForRecords() - { - var request = new SearchForRecordsRequest(RawRequests.SearchForRecords); - request.Parse(); - Assert.Equal("0", request.GameId.ToString()); - Assert.Equal("XXXXXX", request.SecretKey); - Assert.Equal("xxxxxxxx_YYYYYYYYYY__", request.LoginTicket); - Assert.Equal("scores", request.TableId); - Assert.Equal("", request.Filter); - Assert.Equal("", request.Sort); - Assert.Equal("0", request.Offset); - Assert.Equal("3", request.Max); - Assert.Equal("0", request.Surrounding); - Assert.Equal("", request.OwnerIds); - Assert.Equal("0", request.CacheFlag); - Assert.Equal("score", request.Fields[0].FieldName); - Assert.Equal("string", request.Fields[0].FiledType); - Assert.Equal("recordid", request.Fields[1].FieldName); - Assert.Equal("string", request.Fields[1].FiledType); - } - [Fact] - public void DeleteRecord() - { - var request = new DeleteRecordRequest(RawRequests.DeleteRecord); - request.Parse(); - Assert.Equal("0", request.GameId.ToString()); - Assert.Equal("XXXXXX", request.SecretKey); - Assert.Equal("xxxxxxxx_YYYYYYYYYY__", request.LoginTicket); - Assert.Equal("test", request.TableId); - Assert.Equal("150", request.RecordId); - } - // - // TODO: Deserialization of RecordFields - // - [Fact] - public void UpdateRecord() - { - var request = new UpdateRecordRequest(RawRequests.UpdateRecord); - request.Parse(); - Assert.Equal("0", request.GameId.ToString()); - Assert.Equal("XXXXXX", request.SecretKey); - Assert.Equal("xxxxxxxx_YYYYYYYYYY__", request.LoginTicket); - Assert.Equal("test", request.TableId); - Assert.Equal("158", request.RecordId); - - // Assert.Equal("score", request.Values[0].FieldName); - // Assert.Equal("string", request.Values[0].FiledType); - // Assert.Equal("recordid", request.Values[1].FieldName); - // Assert.Equal("string", request.Values[1].FiledType); - } - // - // TODO: Deserialization of RecordFields - // - [Fact] - public void CreateRecord() - { - var request = new CreateRecordRequest(RawRequests.CreateRecord); - request.Parse(); - Assert.Equal("0", request.GameId.ToString()); - Assert.Equal("XXXXXX", request.SecretKey); - Assert.Equal("xxxxxxxx_YYYYYYYYYY__", request.LoginTicket); - Assert.Equal("test", request.TableId); - - // Assert.Equal("score", request.Values[0].FieldName); - // Assert.Equal("string", request.Values[0].FiledType); - // Assert.Equal("recordid", request.Values[1].FieldName); - // Assert.Equal("string", request.Values[1].FiledType); - } - } -} diff --git a/src/Servers/WebServer/test/Sake/ResponseTest.cs b/src/Servers/WebServer/test/Sake/ResponseTest.cs deleted file mode 100644 index b14d2505d..000000000 --- a/src/Servers/WebServer/test/Sake/ResponseTest.cs +++ /dev/null @@ -1,27 +0,0 @@ -using UniSpy.Server.WebServer.Module.Sake.Contract.Request; -using UniSpy.Server.WebServer.Module.Sake.Contract.Response; -using UniSpy.Server.WebServer.Module.Sake.Contract.Result; -using Xunit; - -namespace UniSpy.Server.WebServer.Test.Sake -{ - public class ResponseTest - { - [Fact] - public void CreateRecordTest() - { - var request = new CreateRecordRequest(RawRequests.CreateRecord); - request.Parse(); - var result = new CreateRecordResult() - { - RecordID = "0", - TableID = "0", - }; - result.Fields.Add("hello0"); - result.Fields.Add("hello1"); - result.Fields.Add("hello2"); - var response = new CreateRecordResponse(request, result); - response.Build(); - } - } -} diff --git a/src/Servers/WebServer/test/TestClasses.cs b/src/Servers/WebServer/test/TestClasses.cs deleted file mode 100644 index a0aaed468..000000000 --- a/src/Servers/WebServer/test/TestClasses.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Net; -using Moq; -using UniSpy.Server.Core.Abstraction.Interface; -using UniSpy.Server.WebServer.Application; - -namespace UniSpy.Server.WebServer.Test -{ - public static class MokeObject - { - public static IClient Client = CreateClient(); - - public static Client CreateClient(string ipAddress = "192.168.1.2", int port = 9999) - { - var managerMock = new Mock(); - var connectionMock = new Mock(); - connectionMock.Setup(s => s.RemoteIPEndPoint).Returns(new IPEndPoint(IPAddress.Parse(ipAddress), port)); - connectionMock.Setup(s => s.Manager).Returns(managerMock.Object); - connectionMock.Setup(s => s.ConnectionType).Returns(NetworkConnectionType.Http); - var serverMock = new WebServer.Application.Server(managerMock.Object); - return new Client(connectionMock.Object, serverMock); - } - } -} \ No newline at end of file diff --git a/src/Servers/WebServer/test/UniSpy.Server.WebServer.Test.csproj b/src/Servers/WebServer/test/UniSpy.Server.WebServer.Test.csproj deleted file mode 100644 index 9b120467c..000000000 --- a/src/Servers/WebServer/test/UniSpy.Server.WebServer.Test.csproj +++ /dev/null @@ -1,31 +0,0 @@ - - - - net6.0 - false - ..\..\..\..\common\Icon\UniSpy_Logo.ico - - - AnyCPU - ..\..\..\..\build\$(Configuration) - - - ..\..\..\..\build\$(Configuration) - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - \ No newline at end of file diff --git a/src/backends/__init__.py b/src/backends/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backends/library/abstractions/contracts.py b/src/backends/library/abstractions/contracts.py new file mode 100644 index 000000000..aa1437c6f --- /dev/null +++ b/src/backends/library/abstractions/contracts.py @@ -0,0 +1,46 @@ +from typing import Dict +from pydantic import BaseModel, UUID4 + + +class RequestBase(BaseModel): + """ + The ultimate request base class of all gamespy requests + """ + + server_id: UUID4 + raw_request: str + """ + if the raw_request is bytes, we decode it to decode("ascii","backslashreplace") str + """ + client_ip: str + client_port: int + + +class Response(BaseModel): + message: str + + def to_json_dict(self) -> dict[str, object]: + return self.model_dump(mode="json") + + +class OKResponse(Response): + message: str = "ok" + + +class DataResponse(OKResponse): + result: BaseModel + pass + + +class ErrorResponse(Response): + exception_name: str + pass + + +RESPONSES_DEF: Dict = { + 400: {"model": ErrorResponse}, + 422: {"model": ErrorResponse}, + 500: {"model": ErrorResponse}, + 450: {"model": ErrorResponse} +} +"""Dict type is using to compatible with language checking""" diff --git a/src/backends/library/abstractions/handler_base.py b/src/backends/library/abstractions/handler_base.py new file mode 100644 index 000000000..93dfec2b0 --- /dev/null +++ b/src/backends/library/abstractions/handler_base.py @@ -0,0 +1,79 @@ +from typing import final +from backends.library.abstractions.contracts import ( + DataResponse, + OKResponse, + RequestBase, + Response, +) +from backends.library.database.pg_orm import ENGINE +from frontends.gamespy.library.abstractions.contracts import ResultBase + +import logging +from sqlalchemy.orm import Session + +from frontends.gamespy.library.exceptions.general import UniSpyException + + +class HandlerBase: + """ + The ultimate handler base of backend service + """ + + _request: RequestBase + _result: ResultBase | None + response: Response + """ + response is created by child class annotation + the response using to wrap data + """ + # _data: object + """ + the data get from database, can be any type + """ + + def __init__(self, request: RequestBase) -> None: + assert issubclass(type(request), RequestBase) + self._request = request + # decoupling the logging in home.py + self.logger = logging.getLogger("backend") + self._result = None + self.response = OKResponse() + + def handle(self) -> None: + with Session(ENGINE) as session: + self._session = session + self._request_check() + self._data_operate() + self._result_construct() + self._response_construct() + + def _request_check(self) -> None: + """virtual method""" + + def _data_operate(self) -> None: + """virtual method\n + override by child class to perform database operations + """ + + def _result_construct(self) -> None: + """virtual method\n + can override by child class to create self._result + """ + + @final + def _response_construct(self) -> None: + """ + _response_construct can not be overrided + """ + # if there are no result, we send ok response + if self._result is None: + return + if "response" not in self.__class__.__annotations__: + raise UniSpyException( + "write response type annotation in child class to create response instance.") + response_cls = self.__class__.__annotations__['response'] + if not issubclass(response_cls, DataResponse): + raise UniSpyException( + "response type annotation must be a subclass of DataResponse") + self.response = response_cls(result=self._result) + # self.response = DataResponse(result=self._result) diff --git a/src/backends/library/abstractions/websocket_manager.py b/src/backends/library/abstractions/websocket_manager.py new file mode 100644 index 000000000..1a76e8e5c --- /dev/null +++ b/src/backends/library/abstractions/websocket_manager.py @@ -0,0 +1,84 @@ +# from logging import getLogger +# from uuid import UUID +# from fastapi import WebSocket + +# from frontends.gamespy.library.exceptions.general import UniSpyException +# from frontends.gamespy.protocols.chat.abstractions.contract import BrockerMessage + + +# class WebSocketClient: +# server_id: UUID +# ip: str +# port: int +# ws: WebSocket + +# def __init__(self, ws: WebSocket) -> None: +# assert ws.client +# ip, port = ws.client +# self.ip = ip +# self.port = port +# self.ws = ws + +# @property +# def ip_port(self) -> str: +# return f"{self.ip}:{self.port}" + +# @staticmethod +# def get_ip_port_str(ws: WebSocket): +# assert ws.client +# ip, port = ws.client +# return f"{ip}:{port}" + + +# class WebSocketManager: +# client_pool: dict[str, WebSocketClient] + +# def __init__(self) -> None: +# self.client_pool = {} + +# def create_client(self, ws: WebSocket) -> WebSocketClient: +# client = WebSocketClient(ws) +# return client + +# def get_client(self, ws: WebSocket) -> WebSocketClient: +# ip_port = WebSocketClient.get_ip_port_str(ws) +# client = None +# if ip_port in self.client_pool: +# client = self.client_pool[ip_port] +# if client is None: +# raise UniSpyException( +# "client is not existed in client pool. skip deleting." +# ) +# return client + +# def connect(self, ws: WebSocket): +# client = self.create_client(ws) +# if client.ip_port not in self.client_pool: +# self.client_pool[client.ip_port] = client + +# def disconnect(self, ws: WebSocket): +# """ +# call at last in inherited classs +# """ +# temp = self.create_client(ws) +# if temp.ip_port in self.client_pool: +# del self.client_pool[temp.ip_port] +# # todo remove record in database + +# # todo check channelcache,usercache,channelusercache + +# async def broadcast(self, message: BrockerMessage, ws: list[str] | None = None): +# if ws is None: +# clients = self.client_pool.values() +# else: +# clients = [] +# for w in ws: +# if w in self.client_pool: +# clients.append(self.client_pool[w]) +# else: +# logger = getLogger("backend") +# logger.info(f"{ws} not in websocket client list") + +# for client in clients: +# await client.ws.send_json(message.model_dump_json()) + diff --git a/src/backends/library/database/pg_orm.py b/src/backends/library/database/pg_orm.py new file mode 100644 index 000000000..775014087 --- /dev/null +++ b/src/backends/library/database/pg_orm.py @@ -0,0 +1,346 @@ +from frontends.gamespy.library.configs import CONFIG +from datetime import datetime +from sqlalchemy import ( + Boolean, + SmallInteger, + Text, + create_engine, + Column, + Integer, + String, + ForeignKey, + DateTime, + text, + UUID, +) +from sqlalchemy.orm.session import Session +from sqlalchemy.dialects.postgresql import JSONB, INET +from sqlalchemy.types import TypeDecorator +from frontends.gamespy.protocols.natneg.aggregations.enums import ( + NatClientIndex, + NatPortMappingScheme, + NatPortType, + NatType, +) +from frontends.gamespy.protocols.presence_connection_manager.aggregates.enums import ( + FriendRequestStatus, + GPStatusCode, +) + +import sqlalchemy as sa +import enum +from sqlalchemy.orm.decl_api import DeclarativeBase + +from frontends.gamespy.protocols.query_report.aggregates.enums import GameServerStatus + + +class IntEnum(TypeDecorator): + impl = sa.Integer + + def __init__(self, enumtype, *args, **kwargs): + super().__init__(*args, **kwargs) + self._enumtype = enumtype + + def process_bind_param(self, value: enum.Enum, dialect): + return value.value + + def process_result_value(self, value, dialect): + return self._enumtype(value) + + +# Base: DeclarativeMeta = declarative_base() +# if TYPE_CHECKING: +# Base = cast(DeclarativeMeta, Base) +class Base(DeclarativeBase): + pass + + +class Users(Base): + __tablename__ = "users" + + userid: Column[int] = Column(Integer, primary_key=True, autoincrement=True) + email: Column[str] = Column(String, nullable=False) + password: Column[str] = Column(String, nullable=False) + emailverified: Column[bool] = Column(Boolean, default=True, nullable=False) + lastip: Column[str] = Column(INET) + lastonline: Column[datetime] = Column(DateTime, default=datetime.now()) + createddate: Column[datetime] = Column( + DateTime, default=datetime.now(), nullable=False + ) + banned: Column[bool] = Column(Boolean, default=False, nullable=False) + deleted: Column[bool] = Column(Boolean, default=False, nullable=False) + + +class Profiles(Base): + __tablename__ = "profiles" + + profileid: Column[int] = Column( + Integer, primary_key=True, autoincrement=True) + userid: Column[int] = Column( + Integer, ForeignKey("users.userid"), nullable=False) + nick: Column[str] = Column(String, nullable=False) + serverflag: Column[int] = Column(Integer, nullable=False, default=0) + status = Column(IntEnum(GPStatusCode), default=GPStatusCode.OFFLINE) + statstring: Column[str] = Column(String, default="I love UniSpy") + extra_info: Column[JSONB] = Column(JSONB) + + +class SubProfiles(Base): + __tablename__ = "subprofiles" + + subprofileid = Column( + Integer, ForeignKey("profiles.profileid"), primary_key=True, autoincrement=True + ) + profileid: Column[int] = Column(Integer, nullable=False) + uniquenick: Column[str] = Column(String) + namespaceid: Column[int] = Column(Integer, nullable=False, default=0) + partnerid: Column[int] = Column(Integer, nullable=False, default=0) + productid: Column[int] = Column(Integer) + gamename: Column[str] = Column(Text) + cdkeyenc: Column[str] = Column(String) + firewall: Column[int] = Column(SmallInteger, default=0) + port: Column[int] = Column(Integer, default=0) + authtoken: Column[str] = Column(String) + session_key: Column[str] = Column(String) + + +class Blocked(Base): + __tablename__ = "blocked" + + blockid = Column(Integer, primary_key=True, autoincrement=True) + profileid = Column(Integer, ForeignKey( + "profiles.profileid"), nullable=False) + namespaceid = Column(Integer, nullable=False) + targetid = Column(Integer, nullable=False) + + +class Friends(Base): + __tablename__ = "friends" + + friendid = Column(Integer, primary_key=True, autoincrement=True) + profileid = Column(Integer, ForeignKey( + "profiles.profileid"), nullable=False) + targetid = Column(Integer, nullable=False) + namespaceid = Column(Integer, nullable=False) + + +class FriendAddRequest(Base): + __tablename__ = "addrequests" + + addrequestid = Column(Integer, primary_key=True, autoincrement=True) + profileid = Column(Integer, ForeignKey( + "profiles.profileid"), nullable=False) + targetid = Column(Integer, ForeignKey( + "profiles.profileid"), nullable=False) + namespaceid = Column(Integer, nullable=False) + reason = Column(String, nullable=False) + status = Column( + IntEnum(FriendRequestStatus), + nullable=False, + default=FriendRequestStatus.PENDING, + ) + + +class Games(Base): + __tablename__ = "games" + gameid = Column(Integer, primary_key=True) + gamename = Column(String, nullable=False) + secretkey = Column(String, nullable=False) + description = Column(String(4095), nullable=False) + disabled = Column(Boolean, nullable=False) + + +class GroupList(Base): + __tablename__ = "grouplist" + groupid = Column(Integer, primary_key=True) + gameid = Column(Integer, ForeignKey("games.gameid"), nullable=False) + roomname = Column(Text, nullable=False) + + +class Messages(Base): + __tablename__ = "messages" + id = Column(Integer, primary_key=True, autoincrement=True) + namespaceid = Column(Integer, nullable=False) + type = Column(Integer) + from_user = Column(Integer, nullable=False) + to_user = Column(Integer, nullable=False) + date = Column(DateTime, nullable=False, default=datetime.now()) + message = Column(Text, nullable=False) + + +class Partner(Base): + __tablename__ = "partner" + partnerid = Column(Integer, primary_key=True) + partnername = Column(String, nullable=False) + + +class PStorage(Base): + __tablename__ = "pstorage" + id = Column(Integer, primary_key=True, autoincrement=True) + profileid = Column(Integer, ForeignKey( + "profiles.profileid"), nullable=False) + ptype = Column(Integer, nullable=False) + dindex = Column(Integer, nullable=False) + data = Column(String, nullable=False) + update_time = Column(DateTime, nullable=False, default=datetime.now()) + + +class GameStatusSnapShot(Base): + __tablename__ = "game_status_snapshot" + id = Column(Integer, primary_key=True, autoincrement=True) + connection_id = Column(Integer) + session_key = Column(String) + game_name = Column(String) + game_data = Column(JSONB) + update_time = Column(DateTime, nullable=False, default=datetime.now()) + + +class SakeStorage(Base): + __tablename__ = "sakestorage" + id = Column(Integer, primary_key=True, autoincrement=True) + tableid = Column(Integer, nullable=False) + data: Column[JSONB] = Column(JSONB, nullable=False) + + +class InitPacketCaches(Base): + __tablename__ = "init_packet_caches" + id = Column(Integer, primary_key=True, autoincrement=True) + cookie = Column(SmallInteger, nullable=False) + server_id = Column(UUID, nullable=False) + version = Column(Integer, nullable=False) + port_type = Column(IntEnum(NatPortType), nullable=False) + client_index = Column(IntEnum(NatClientIndex), nullable=False) + game_name = Column(String, nullable=True) + use_game_port = Column(Boolean, nullable=False) + public_ip = Column(String, nullable=False) + public_port = Column(Integer, nullable=False) + private_ip = Column(String, nullable=False) + private_port = Column(Integer, nullable=False) + update_time = Column(DateTime, nullable=False, default=datetime.now()) + + +class NatResultCaches(Base): + __tablename__ = "nat_result_caches" + id = Column(Integer, primary_key=True, autoincrement=True) + cookie = Column(SmallInteger, nullable=False) + public_ip = Column(INET, nullable=False) + private_ip = Column(INET, nullable=False) + is_success = Column(Boolean, nullable=False) + port_mapping_scheme = Column(IntEnum(NatPortMappingScheme), nullable=False) + nat_type = Column(IntEnum(NatType), nullable=False) + port_type = Column(IntEnum(NatPortType), nullable=False) + client_index = Column(IntEnum(NatClientIndex), nullable=False) + game_name = Column(String, nullable=True) + update_time = Column(DateTime, nullable=False, default=datetime.now()) + + +class RelayServerCaches(Base): + __tablename__ = "relay_server_caches" + id = Column(Integer, primary_key=True, autoincrement=True) + server_id = Column(UUID, primary_key=True, nullable=False) + public_ip = Column(String, nullable=False) + public_port = Column(Integer, nullable=False) + client_count = Column(Integer, nullable=False) + update_time = Column(DateTime, nullable=False, default=datetime.now()) + + +class ChatChannelCaches(Base): + __tablename__ = "chat_channel_caches" + channel_name = Column(String, primary_key=True, nullable=False) + server_id = Column(UUID, nullable=False) + creator = Column(String, nullable=False) + game_name = Column(String, nullable=False) + creator = Column(String, nullable=True) + room_name = Column(String, nullable=False) + topic = Column(String, nullable=True) + password = Column(String, nullable=True) + group_id = Column(Integer, nullable=False) + max_num_user = Column(Integer, nullable=False) + key_values = Column(JSONB, default={}) + invited_nicks = Column(JSONB, default=[]) + modes = Column(JSONB, default=[]) + banned_nicks = Column(JSONB, default=[]) + update_time = Column(DateTime, nullable=False, default=datetime.now()) + + +class ChatUserCaches(Base): + """ + each user only have a unique nick caches, but have multiple user caches + """ + + __tablename__ = "chat_user_caches" + nick_name = Column(String, primary_key=True, nullable=True) + server_id = Column(UUID, nullable=False) + user_name = Column(String, nullable=True) + game_name = Column(String, nullable=True) + remote_ip = Column(INET, nullable=False) + remote_port = Column(Integer, nullable=False) + websocket_address = Column(String, nullable=False) + key_value = Column(JSONB, default={}) + update_time = Column(DateTime, nullable=False, default=datetime.now()) + + +class ChatChannelUserCaches(Base): + __tablename__ = "chat_channel_user_caches" + id = Column(Integer, primary_key=True, autoincrement=True) + nick_name = Column( + String, + ForeignKey("chat_user_caches.nick_name"), + nullable=False, + ) + user_name = Column( + String, + ForeignKey("chat_user_caches.user_name"), + nullable=False, + ) + channel_name = Column( + String, ForeignKey("chat_channel_caches.channel_name"), nullable=False + ) + server_id = Column(UUID, nullable=False) + update_time = Column(DateTime, nullable=False, default=datetime.now()) + # can we directly store the flags? + is_voiceable = Column(Boolean, nullable=False) + is_channel_operator = Column(Boolean, nullable=False) + is_channel_creator = Column(Boolean, nullable=False) + remote_ip = Column(INET, nullable=False) + remote_port = Column(Integer, nullable=False) + key_values = Column(JSONB, default={}) + + +class GameServerCaches(Base): + __tablename__ = "game_server_caches" + id = Column(Integer, primary_key=True) + instant_key = Column(String, nullable=True) + server_id = Column(UUID, nullable=False) + host_ip_address = Column(INET, nullable=False) + game_name = Column(String, nullable=False) + query_report_port = Column(Integer, nullable=False) + status = Column(IntEnum(GameServerStatus)) + data = Column(JSONB, nullable=False, default={}) + avaliable = Column(Boolean, nullable=True) + update_time = Column(DateTime, nullable=False, default=datetime.now()) + + +class FrontendInfo(Base): + __tablename__ = "frontend_info" + id = Column(Integer, primary_key=True, autoincrement=True) + server_id = Column(UUID, nullable=False) + server_name = Column(String, nullable=False) + external_ip = Column(String, nullable=False) + listening_ip = Column(INET, nullable=False) + listening_port = Column(Integer, nullable=False) + update_time = Column(DateTime, nullable=False, default=datetime.now()) + + +ENGINE = create_engine(CONFIG.postgresql.url) +with ENGINE.connect() as conn: + conn.execute(text("SELECT 1")).first() + +if __name__ == "__main__": + with Session(ENGINE) as session: + session.query(Users.userid == 0).all() # type:ignore + # profile = Profiles(userid=1, nick="spyguy", + # extra_info={}, status=GPStatusCode.OFFLINE) + # PG_SESSION.add(profile) + # PG_SESSION.commit() + pass diff --git a/src/backends/library/networks/redis_brocker.py b/src/backends/library/networks/redis_brocker.py new file mode 100644 index 000000000..66d253f51 --- /dev/null +++ b/src/backends/library/networks/redis_brocker.py @@ -0,0 +1,51 @@ + +import threading +from redis.client import PubSub +from typing import Callable +from redis import Redis + +from frontends.gamespy.library.abstractions.brocker import BrockerBase +from frontends.gamespy.library.configs import CONFIG + + +class RedisBrocker(BrockerBase): + _client: Redis + _subscriber: PubSub + + def subscribe(self): + self.is_started = True + self._client = Redis.from_url(self.url, socket_timeout=5) + self._client.ping() + self._subscriber = self._client.pubsub() + th = threading.Thread(target=self.get_message) + th.start() + + def get_message(self): + self._subscriber.subscribe(self._name) + while True: + m = self._subscriber.get_message(timeout=10) + if m is not None: + if "data" not in m: + continue + if not isinstance(m['data'], bytes): + continue + msg = m['data'].decode("utf-8") + threading.Thread(target=self.receive_message, + args=[msg]).start() + + def unsubscribe(self): + self.is_started = False + self._subscriber.unsubscribe(self._name) + self._subscriber.close() + + def publish_message(self, message: str): + assert isinstance(message, str) + self._client.publish(self._name, message) + + +if __name__ == "__main__": + pass + + brocker = RedisBrocker("master", CONFIG.redis.url, print) + brocker.subscribe() + pass diff --git a/src/backends/library/networks/ws_manager.py b/src/backends/library/networks/ws_manager.py new file mode 100644 index 000000000..949b68ce2 --- /dev/null +++ b/src/backends/library/networks/ws_manager.py @@ -0,0 +1,85 @@ +import asyncio +import logging +from fastapi import WebSocket, WebSocketDisconnect + +from frontends.gamespy.library.log.log_manager import GLOBAL_LOGGER + + +class WebsocketManager: + """ + current: single server mode + client1 -> frontend1 -> backend1 (rest api) + client2 <- | <- + client3 <- | + """ + + """ + future: distributed mode + client1 -> frontend1 -> backend1 (rest api) + client2 <- | <- + client3 <- | + -> (websocket) -> redis + client2 -> frontend2 <- backend2 <- | + client3 -> frontend3 <- backend3 <- | + client4 -> frontend4 <- backend4 <- | + """ + client_pool: dict[str, WebSocket] + logger: logging.Logger + + def __init__(self) -> None: + self.client_pool = {} + self.logger = logging.getLogger("backend") + + def get_address_str(self, ws: WebSocket) -> str: + assert ws.client is not None + ws_address = f"{ws.client.host}:{ws.client.port}" + return ws_address + + def connect(self, ws: WebSocket): + assert ws.client is not None + ws_address = self.get_address_str(ws) + self.client_pool[ws_address] = ws + + def disconnect(self, ws: WebSocket): + assert ws.client is not None + ws_address = self.get_address_str(ws) + if ws_address in self.client_pool: + del self.client_pool[ws_address] + + def get_websocket(self, ws_address: str) -> WebSocket | None: + if ws_address in self.client_pool: + return self.client_pool[ws_address] + + def broadcast(self, message: str): + self._broadcast(message, list(self.client_pool.values())) + + def _broadcast(self, message: str, wss: list[WebSocket]): + loop = asyncio.get_event_loop() + self.logger.info(f"[cast] [send] {message}") + for ws in wss: + loop.create_task(ws.send_json(message)) + + def broadcast_except(self, message: str, wss: list[WebSocket], except_ip: list[str]): + filtered_wss = [] + for ws in wss: + assert ws.client is not None + if ws.client.host not in except_ip: + filtered_wss.append(ws) + self._broadcast(message, filtered_wss) + + async def process_websocket(self, ws: WebSocket): + """ + process websocket connection here + """ + await ws.accept() + if isinstance(ws, WebSocket) and ws.client is not None: + self.connect(ws) + try: + while True: + _ = await ws.receive_json() + except WebSocketDisconnect: + if ws.client is not None: + # remove chat info by websocket + self.disconnect(ws) + GLOBAL_LOGGER.info( + f"websocket client: [{ws.client.host}:{ws.client.port} is disconnected") diff --git a/src/backends/library/utils/misc.py b/src/backends/library/utils/misc.py new file mode 100644 index 000000000..2f96c2bc7 --- /dev/null +++ b/src/backends/library/utils/misc.py @@ -0,0 +1,9 @@ +from frontends.gamespy.library.configs import CONFIG +from frontends.gamespy.library.exceptions.general import UniSpyException + + +def check_public_ip(real_ip: str, report_ip: str): + if CONFIG.backend.is_check_public_ip: + if real_ip != report_ip: + raise UniSpyException( + "client real ip is not equal to its config ip") diff --git a/src/backends/protocols/__init__.py b/src/backends/protocols/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backends/protocols/gamespy/chat/brocker.py b/src/backends/protocols/gamespy/chat/brocker.py new file mode 100644 index 000000000..92a0de020 --- /dev/null +++ b/src/backends/protocols/gamespy/chat/brocker.py @@ -0,0 +1,69 @@ +from contextlib import asynccontextmanager +from fastapi import APIRouter, WebSocket +from backends.library.database.pg_orm import ENGINE +from backends.library.networks.redis_brocker import RedisBrocker +from frontends.gamespy.library.configs import CONFIG + +import backends.protocols.gamespy.chat.data as data +from sqlalchemy.orm import Session +from backends.library.networks.ws_manager import WebsocketManager as WsManager +from frontends.gamespy.library.log.log_manager import GLOBAL_LOGGER + + +class WebsocketManager(WsManager): + """ + current: single server mode + client1 -> frontend1 -> backend1 (rest api) + client2 <- | <- + client3 <- | + """ + + """ + future: distributed mode + client1 -> frontend1 -> backend1 (rest api) + client2 <- | <- + client3 <- | + -> (websocket) -> redis + client2 -> frontend2 <- backend2 <- | + client3 -> frontend3 <- backend3 <- | + client4 -> frontend4 <- backend4 <- | + """ + + def _get_wss_in_channel(self, channel_name: str) -> list[WebSocket]: + with Session(ENGINE) as session: + ws_addrss = data.get_websocket_addr_by_channel_name( + channel_name, session) + wss = [] + for addr in ws_addrss: + if addr in self.client_pool: + wss.append(self.client_pool[addr]) + return wss + + def broadcast_channel_message(self, channel_name: str, message: str, ws_client: WebSocket): + """ + create redis pubsub to share message cross all backends + currently we simply implement without redis pubsub + """ + exclude_addr = self.get_address_str(ws_client) + wss = self._get_wss_in_channel(channel_name) + self.broadcast_except(message, wss, [exclude_addr]) + + +def handle_client_message(message: str): + from backends.protocols.gamespy.chat.requests import PublishMessageRequest + from backends.protocols.gamespy.chat.handlers import PublishMessageHandler + try: + request = PublishMessageRequest.model_validate(message) + PublishMessageHandler.broad_cast_loacl(request) + except Exception as e: + GLOBAL_LOGGER.error(str(e)) + + +MANAGER = WebsocketManager() +BROCKER = RedisBrocker("chat", CONFIG.redis.url, handle_client_message) + + +@asynccontextmanager +async def launch_brocker(_: APIRouter): + BROCKER.subscribe() + yield diff --git a/src/backends/protocols/gamespy/chat/data.py b/src/backends/protocols/gamespy/chat/data.py new file mode 100644 index 000000000..06ee402c5 --- /dev/null +++ b/src/backends/protocols/gamespy/chat/data.py @@ -0,0 +1,610 @@ +from datetime import datetime, timedelta +from typing import TYPE_CHECKING, cast + +from sqlalchemy import Column, func +from backends.library.database.pg_orm import ( + ENGINE, + ChatChannelCaches, + ChatUserCaches, + ChatChannelUserCaches, + Games, + Users, + Profiles, + SubProfiles, +) +from frontends.gamespy.protocols.chat.aggregates.exceptions import ( + ChatException, + NoSuchNickException, +) +from sqlalchemy.orm import Session + +from frontends.gamespy.protocols.chat.contracts.results import WhoIsResult + + +def is_nick_exist(nick_name: str, session: Session) -> bool: + c = session.query(ChatUserCaches.nick_name).count() + if c == 1: + return True + else: + return False + + +def get_secret_key_by_game_name(game_name: str, session: Session) -> str | None: + result = session.query(Games).where(Games.gamename == game_name).first() + if result is None: + return None + else: + assert isinstance(result.secretkey, str) + return result.secretkey + + +def add_user_cache(cache: ChatUserCaches, session: Session) -> Session: + session.add(cache) + session.commit() + return session + + +def nick_and_email_login( + nick_name: str, email: str, password_hash: str, session: Session +) -> tuple[int, int, bool, bool]: + """ + return + userid, profileid, emailverified, banned + """ + assert isinstance(nick_name, str) + assert isinstance(email, str) + assert isinstance(password_hash, str) + + result = ( + session.query( + Users.userid, Profiles.profileid, Users.emailverified, Users.banned + ) + .join(Profiles, (Users.userid == Profiles.userid)) + .where( + Users.email == email, + Profiles.nick == nick_name, + Users.password == password_hash, + ) + .first() + ) + if TYPE_CHECKING: + result = cast(tuple[int, int, bool, bool], result) + if result is None: + # fmt: off + raise ChatException(f"Can not find user with nickname:{nick_name} in database.") + # fmt on + + return result + + +def uniquenick_login( + uniquenick: str, namespace_id: int, session: Session +) -> tuple[int, int, bool, bool]: + """ + return + userid, profileid, emailverified, banned + """ + assert isinstance(uniquenick, str) + assert isinstance(namespace_id, int) + + result = ( + session.query( + Users.userid, Profiles.profileid, Users.emailverified, Users.banned + ) + .join(Profiles, (Users.userid == Profiles.userid)) + .join(Profiles, (Profiles.profileid == SubProfiles.profileid)) + .where( + SubProfiles.namespaceid == namespace_id, + SubProfiles.uniquenick == uniquenick, + ) + .first() + ) + if result is None: + # fmt: off + raise ChatException(f"Can not find user with uniquenick:{uniquenick} in database.") + # fmt on + if TYPE_CHECKING: + result = cast(tuple[int, int, bool, bool], result) + return result + + +# region User + + +def is_cdkey_valid(cdkey: str, session: Session) -> bool: + if TYPE_CHECKING: + assert isinstance(SubProfiles.cdkeyenc, Column) + + result = session.query(SubProfiles).where(SubProfiles.cdkeyenc == cdkey).count() + if result == 0: + return False + + else: + return True + + +# region Channel + + +def is_channel_exist(channel_name: str, game_name: str, session: Session) -> bool: + channel_count = ( + session.query(ChatChannelCaches) + .where( + ChatChannelCaches.channel_name == channel_name, + ChatChannelCaches.game_name == game_name, + ) + .count() + ) + if channel_count == 1: + return True + else: + return False + + +def add_channel(channel: ChatChannelCaches, session: Session): + session.add(channel) + session.commit() + + +def get_channel_by_name_and_game( + channel_name: str, game_name: str, session: Session +) -> ChatChannelCaches | None: + channel = ( + session.query(ChatChannelCaches) + .where( + ChatChannelCaches.channel_name == channel_name, + ChatChannelCaches.game_name == game_name, + ) + .first() + ) + return channel + + +def get_channel_by_name( + channel_name: str, session: Session +) -> ChatChannelCaches | None: + channel = ( + session.query(ChatChannelCaches) + .where(ChatChannelCaches.channel_name == channel_name) + .first() + ) + return channel + + +def get_channel_user_list_by_ip_port( + ip: str, port: int, session: Session +) -> list[ChatChannelUserCaches]: + assert isinstance(ip, str) + assert isinstance(port, int) + result = ( + session.query(ChatChannelUserCaches) + .where( + ChatChannelUserCaches.remote_ip == ip, + ChatChannelUserCaches.remote_port == port, + ) + .all() + ) + return result + + +# def get_channel_cache_list_by_ip_port( +# ip: str, port: int, session: Session +# ) -> list[ChatChannelCaches]: +# assert isinstance(ip, str) +# assert isinstance(port, int) +# result = ( +# session.query(ChatChannelCaches) +# .join(ChatChannelUserCaches) +# .where( +# ChatChannelUserCaches.remote_ip == ip, +# ChatChannelUserCaches.remote_port == port, +# ) +# .all() +# ) +# return result + + +def get_channel_by_name_and_ip_port( + channel_name: str, ip: str, port: int, session: Session +) -> ChatChannelCaches | None: + assert isinstance(channel_name, str) + assert isinstance(ip, str) + assert isinstance(port, int) + + result = ( + session.query(ChatChannelCaches) + .join(ChatChannelUserCaches) + .where( + ChatChannelUserCaches.channel_name == channel_name, + ChatChannelUserCaches.remote_ip == ip, + ChatChannelUserCaches.remote_port == port, + ) + .first() + ) + return result + + +def check_channel_user_trash_data( + channel: ChatChannelCaches, user: ChatUserCaches, session: Session +): + expire_time = datetime.now() - timedelta(minutes=2) + assert isinstance(channel.channel_name, str) + assert isinstance(user.nick_name, str) + exist_user = get_channel_user_cache_by_nick_name( + channel.channel_name, user.nick_name, session + ) + if exist_user is not None: + if exist_user.update_time <= expire_time: # type: ignore + session.delete(exist_user) + session.commit() + else: + raise NoSuchNickException( + "There are two same channel user cache in database" + ) + + # session.commit() + + +def get_channel_user_cache_by_nick_name( + channel_name: str, nick_name: str, session: Session +) -> ChatChannelUserCaches | None: + assert isinstance(channel_name, str) + assert isinstance(nick_name, str) + + result = ( + session.query(ChatChannelUserCaches) + .where( + ChatChannelUserCaches.channel_name == channel_name, + ChatChannelUserCaches.nick_name == nick_name, + ) + .first() + ) + return result + + +def get_channel_user_cache_by_name_and_ip_port( + channel_name: str, ip: str, port: int, session: Session +) -> ChatChannelUserCaches | None: + result = ( + session.query(ChatChannelUserCaches) + .where( + ChatChannelUserCaches.channel_name == channel_name, + ChatChannelUserCaches.remote_ip == ip, + ChatChannelUserCaches.remote_port == port, + ) + .first() + ) + return result + + +def get_channel_user_caches_by_name( + channel_name: str, session: Session +) -> list[ChatChannelUserCaches]: + assert isinstance(channel_name, str) + + result: list[ChatChannelUserCaches] = ( + session.query(ChatChannelUserCaches) + .where(ChatChannelUserCaches.channel_name == channel_name) + .all() + ) # type:ignore + return result + + +def db_commit(session: Session): + session.commit() + + +def get_user_cache_by_nick_name( + nick_name: str, session: Session +) -> ChatUserCaches | None: + result = ( + session.query(ChatUserCaches) + .where(ChatUserCaches.nick_name == nick_name) + .first() + ) + return result + + +def get_user_cache_by_ws( + websocket_address: str, session: Session +) -> ChatUserCaches | None: + user = ( + session.query(ChatUserCaches) + .where(ChatUserCaches.websocket_address == websocket_address) + .first() + ) + return user + + +def get_user_cache_by_ip_port( + ip: str, port: int, session: Session +) -> ChatUserCaches | None: + result = ( + session.query(ChatUserCaches) + .where( + ChatUserCaches.remote_ip == ip, + ChatUserCaches.remote_port == port, + ) + .first() + ) + assert isinstance(result, ChatUserCaches | None) + return result + + +def get_whois_result(nick: str, session: Session) -> WhoIsResult: + """ + nick is unique in chat + """ + + info = session.query(ChatUserCaches).first() + + if info is None: + raise NoSuchNickException(f"User not find by nick name:{nick}.") + channels = ( + session.query(ChatChannelUserCaches.channel_name) + .join( + ChatUserCaches, + ChatChannelUserCaches.nick_name == ChatUserCaches.nick_name, + ) + .where(ChatChannelUserCaches.nick_name == info.nick_name) + .all() + ) + + if info.nick_name is None: + raise ChatException("nick name is missing") + if info.user_name is None: + raise ChatException("user name is missing") + + assert isinstance(info.nick_name,str) + assert isinstance(info.user_name,str) + assert isinstance(info.remote_ip,str) + assert isinstance(channels,list) + re = WhoIsResult( + nick_name=info.nick_name, + user_name=info.user_name, + public_ip_address=info.remote_ip, + joined_channels=list(channels[0]) + ) + + return re + + +def get_websocket_addr_by_channel_name( + channel_name: str, session: Session +) -> list[str]: + """ + find the client websocket address in database which updated within 1 min + """ + users = ( + session.query(ChatUserCaches.websocket_address) + .join( + ChatChannelUserCaches, + ChatUserCaches.nick_name == ChatChannelUserCaches.nick_name, + ) + .where( + ChatChannelUserCaches.channel_name == channel_name, + ChatChannelUserCaches.update_time >= datetime.now() - timedelta(minutes=1), + ) + .all() + ) # type: ignore + users = [user[0] for user in users] + assert isinstance(users, list) + return users + + +def remove_channel_user_caches_by_ip_port(ip: str, port: int, session: Session): + assert isinstance(ip, str) + assert isinstance(port, int) + + session.query(ChatChannelUserCaches).where( + ChatChannelUserCaches.remote_ip == ip, + ChatChannelUserCaches.remote_port == port, + ).delete() + + +def remove_user_cache_by_ip_port(ip: str, port: int, session: Session): + assert isinstance(ip, str) + assert isinstance(port, int) + session.query(ChatUserCaches).where( + ChatUserCaches.remote_ip == ip, + ChatUserCaches.remote_port == port, + ).delete() + + +def remove_user_cache(cache: ChatUserCaches, session: Session): + session.delete(cache) + session.commit() + + +def remove_channel(cache: ChatChannelCaches, session: Session) -> None: + assert isinstance(cache, ChatChannelCaches) + + session.delete(cache) + session.commit() + + +def remove_user(cache: ChatChannelUserCaches, session: Session): + assert isinstance(cache, ChatChannelUserCaches) + + session.delete(cache) + session.commit() + + +def is_user_exist(ip: str, port: int, session: Session) -> bool: + user_count = ( + session.query(ChatChannelUserCaches) + .where( + ChatChannelUserCaches.remote_ip == ip, + ChatChannelUserCaches.remote_port == port, + ) + .count() + ) + if user_count == 1: + return True + else: + return False + + +def update_client(cache: ChatChannelUserCaches, session: Session): + assert isinstance(cache, ChatChannelUserCaches) + + session.commit() + + +def add_invited(channel_name: str, client_ip: str, client_port: int, session: Session): + pass + + +def find_channel_by_substring(channel_name: str, session: Session) -> list[dict]: + assert isinstance(channel_name, str) + + names, topics = ( + session.query(ChatChannelCaches.channel_name, ChatChannelCaches.topic) + .where(ChatChannelCaches.channel_name.like(f"%{channel_name}%")) + .all() + ) + users = ( + session.query(ChatChannelUserCaches) + .where(ChatChannelUserCaches.channel_name.like(f"%{channel_name}%")) + .all() + ) + data: list[dict] = [] + assert isinstance(names, list) + assert isinstance(topics, list) + assert isinstance(users, list) + for name, topic, count in zip(names, topics, users): + d = {"channel_name": name, "total_channel_user": count, "channel_topic": topic} + data.append(d) + return data + + +def find_user_by_substring(user_name: str, session: Session) -> list[dict]: + assert isinstance(user_name, str) + + names, topics, users = ( + session.query( + ChatChannelCaches.channel_name, + ChatChannelCaches.topic, + func.count(ChatChannelUserCaches.channel_name), + ) + .join( + ChatUserCaches, + ChatUserCaches.nick_name == ChatChannelUserCaches.nick_name, + ) + .join( + ChatChannelCaches, + ChatChannelCaches.channel_name == ChatChannelUserCaches.channel_name, + ) + .where(ChatUserCaches.user_name.like(f"%{user_name}%")) + .all() + ) + data: list[dict] = [] + + for name, topic, count in zip(names, topics, users): + d = {"channel_name": name, "total_channel_user": count, "channel_topic": topic} + data.append(d) + return data + + +def create_channel_user_caches(chan_user: ChatChannelUserCaches, session: Session): + session.add(chan_user) + session.commit() + + +def get_channel_user_caches(channel_name: str, session: Session) -> list[dict]: + result: list[ChatChannelUserCaches] = ( + session.query(ChatChannelUserCaches) + .join( + ChatChannelCaches, + ChatChannelCaches.channel_name == ChatChannelUserCaches.channel_name, + ) + .join( + ChatUserCaches, + ChatUserCaches.user_name == ChatChannelUserCaches.user_name, + ) + .where(ChatChannelUserCaches.channel_name == channel_name) + .all() + ) + data = [] + for r in result: + temp = {} + temp["channel_name"] = r.channel_name + temp["user_name"] = r.user_name + temp["public_ip_addr"] = r.remote_ip + temp["nick_name"] = r.nick_name + data.append(temp) + return data + + +def get_channel_user_cache_by_ip(ip: str, port: int, session: Session) -> list[dict]: + result: list[ChatChannelUserCaches] = ( + session.query(ChatChannelUserCaches) + .join( + ChatChannelCaches, + ChatChannelCaches.channel_name == ChatChannelUserCaches.channel_name, + ) + .join( + ChatUserCaches, + ChatUserCaches.user_name == ChatChannelUserCaches.user_name, + ) + .where( + ChatUserCaches.remote_ip == ip, + ChatUserCaches.remote_port == port, + ) + .all() + ) + data = [] + for r in result: + temp = {} + temp["channel_name"] = r.channel_name + temp["user_name"] = r.user_name + temp["public_ip_addr"] = r.remote_ip + temp["nick_name"] = r.nick_name + data.append(temp) + return data + + +def clean_expired_user_cache(session: Session): + session.query(ChatUserCaches).where( + ChatUserCaches.update_time < (datetime.now() - timedelta(minutes=5)) + ).delete() + session.commit() + + +def clean_expired_channel_cache(session: Session): + session.query(ChatChannelCaches).where( + ChatChannelCaches.update_time < (datetime.now() - timedelta(minutes=5)) + ).delete() + session.commit() + + +def clean_expired_channel_user_cache(session: Session): + session.query(ChatChannelUserCaches).where( + ChatUserCaches.update_time < (datetime.now() - timedelta(minutes=5)) + ).delete() + session.commit() + + +def _flush_chat_database(): + """ + be caution with this function + this function will remove all datatable for chat + """ + with Session(ENGINE) as session: + session.query(ChatChannelUserCaches).delete() + session.query(ChatUserCaches).delete() + session.query(ChatChannelCaches).delete() + session.commit() + + +if __name__ == "__main__": + pass + _flush_chat_database() + # + # result = ( + # session.query(ChatUserCaches) + # .where(ChatUserCaches.nick_name == "172.19.0.5:52986") + # .first() + # ) + # result.nick_name = "changed" + # session.commit() diff --git a/src/backends/protocols/gamespy/chat/handlers.py b/src/backends/protocols/gamespy/chat/handlers.py new file mode 100644 index 000000000..26ddb76c2 --- /dev/null +++ b/src/backends/protocols/gamespy/chat/handlers.py @@ -0,0 +1,881 @@ +from datetime import datetime +from typing import TYPE_CHECKING, cast +from backends.library.abstractions.contracts import OKResponse +import backends.library.abstractions.handler_base as hb + + +from backends.library.database.pg_orm import ( + ChatChannelCaches, + ChatUserCaches, + ChatChannelUserCaches, +) +from backends.protocols.gamespy.chat.brocker import BROCKER, MANAGER +from backends.protocols.gamespy.chat.helper import ChannelHelper +import backends.protocols.gamespy.chat.data as data +from backends.protocols.gamespy.chat.requests import ( + AtmRequest, + CdkeyRequest, + ChannelRequestBase, + CryptRequest, + GetCKeyRequest, + GetChannelKeyRequest, + GetKeyRequest, + GetUdpRelayRequest, + InviteRequest, + JoinRequest, + KickRequest, + ListRequest, + LoginPreAuthRequest, + ModeRequest, + NamesRequest, + NickRequest, + NoticeRequest, + PartRequest, + PrivateRequest, + PublishMessageRequest, + QuitRequest, + RequestBase, + SetCKeyRequest, + SetChannelKeyRequest, + SetKeyRequest, + TopicRequest, + UserRequest, + UtmRequest, + WhoIsRequest, + WhoRequest, +) +from backends.protocols.gamespy.chat.response import AtmResponse, CryptResponse, GetCkeyResponse, GetKeyResponse, JoinResponse, KickResponse, ModeResponse, NamesResponse, NicksResponse, PartResponse, PingResponse, PrivateResponse, SetCKeyResponse, SetChannelKeyResponse, TopicResponse, UtmResponse, WhoIsResponse +from frontends.gamespy.protocols.chat.aggregates.enums import ( + GetKeyRequestType, + ModeRequestType, + TopicRequestType, + WhoRequestType, +) +from frontends.gamespy.protocols.chat.aggregates.exceptions import ( + BadChannelKeyException, + ChatException, + LoginFailedException, + NickNameInUseException, + NoSuchChannelException, + NoSuchNickException, +) +from frontends.gamespy.protocols.chat.contracts.responses import NoticeResponse +from frontends.gamespy.protocols.chat.contracts.results import ( + AtmResult, + CryptResult, + GetCKeyResult, + GetChannelKeyResult, + GetKeyResult, + JoinResult, + KickResult, + ListResult, + ModeResult, + NamesResult, + NamesResultData, + NickResult, + NoticeResult, + PartResult, + PingResult, + PrivateResult, + SetCKeyResult, + SetChannelKeyResult, + TopicResult, + UtmResult, + WhoIsResult, + WhoResult, +) +from sqlalchemy.orm import Session + +# abstraction + + +class HandlerBase(hb.HandlerBase): + _request: RequestBase + _user: ChatUserCaches | None + _session: Session + + def __init__(self, request: RequestBase) -> None: + super().__init__(request) + self._user = None + + def _request_check(self) -> None: + self._get_user() + self._check_user() + self._session.commit() + + def _get_user(self): + self._user = data.get_user_cache_by_ip_port( + self._request.client_ip, self._request.client_port, self._session + ) + + def _check_user(self): + if self._user is None: + raise NoSuchNickException( + f"Can not find user with ip address: {self._request.client_ip}:{self._request.client_port}" + ) + self._user.update_time = datetime.now() # type: ignore + + +class ChannelHandlerBase(HandlerBase): + _request: ChannelRequestBase + _channel: ChatChannelCaches | None + _channel_user: ChatChannelUserCaches | None + + def __init__(self, request: RequestBase) -> None: + super().__init__(request) + self._channel = None + self._channel_user = None + + def _request_check(self) -> None: + self._get_user() + self._check_user() + + self._get_channel() + self._check_channel() + + self._get_channel_user() + self._check_channel_user() + self._session.commit() + + def _get_channel(self): + self._channel = data.get_channel_by_name( + self._request.channel_name, self._session + ) + + def _get_channel_user(self): + assert self._user is not None + # typechecking require this step + nick = self._user.nick_name + assert isinstance(nick, str) + self._channel_user = data.get_channel_user_cache_by_nick_name( + self._request.channel_name, + nick, + self._session, + ) + + def _check_channel(self): + if self._channel is None: + raise NoSuchChannelException( + f"Can not find channel with name: {self._request.channel_name}" + ) + self._channel.update_time = datetime.now() # type: ignore + + def _check_channel_user(self): + if self._channel_user is None: + raise NoSuchNickException( + f"Can not find channel user with channel name: {self._request.channel_name}, ip address: {self._request.client_ip}:{self._request.client_port}" + ) + self._channel_user.update_time = datetime.now() # type: ignore + + +class MessageHandlerBase(ChannelHandlerBase): + def __init__(self, request: RequestBase) -> None: + super().__init__(request) + + +# region General + +class PingHandler(HandlerBase): + response: PingResponse + + def _result_construct(self) -> None: + assert self._user is not None + assert isinstance(self._user.nick_name, str) + assert isinstance(self._user.user_name, str) + self._result = PingResult( + nick_name=self._user.nick_name, + user_name=self._user.user_name + ) + + +class CdKeyHandler(HandlerBase): + _request: CdkeyRequest + + def _data_operate(self) -> None: + is_valid = data.is_cdkey_valid(self._request.cdkey, self._session) + if not is_valid: + raise LoginFailedException("cdkey not matched") + + +class CryptHandler(HandlerBase): + _request: CryptRequest + response: CryptResponse + + def _request_check(self) -> None: + # we just clean the garbage data + data.clean_expired_channel_user_cache(self._session) + data.clean_expired_channel_cache(self._session) + data.clean_expired_user_cache(self._session) + self._get_user() + if self._user is not None: + raise ChatException("user cache is trash in database") + + def _data_operate(self) -> None: + assert self._user is None + if self._user is None: + self._user = ChatUserCaches( + server_id=self._request.server_id, + remote_ip=self._request.client_ip, + remote_port=self._request.client_port, + nick_name=f"{self._request.client_ip}:{self._request.client_port}", + websocket_address=self._request.websocket_address, + game_name=self._request.gamename, + ) + self._secret_key = data.get_secret_key_by_game_name( + self._request.gamename, self._session + ) + if self._secret_key is None: + raise ChatException("game secret key not found in database.") + self._session.add(self._user) + self._session.commit() + + def _result_construct(self) -> None: + assert isinstance(self._secret_key, str) + self._result = CryptResult(secret_key=self._secret_key) + + +class GetKeyHandler(HandlerBase): + _request: GetKeyRequest + response: GetKeyResponse + + def _data_operate(self) -> None: + caches = data.get_user_cache_by_nick_name( + self._request.nick_name, self._session + ) + + if caches is None: + raise NoSuchNickException("nick not found") + if TYPE_CHECKING: + kv = cast(dict, caches.key_value) + self._values = cast(list, kv.keys()) + + def _result_construct(self) -> None: + self._result = GetKeyResult( + nick_name=self._request.nick_name, + values=self._values, + cookie=self._request.cookie + ) + + +class GetUdpRelayHandler(HandlerBase): + _request: GetUdpRelayRequest + + def __init__(self, request: RequestBase) -> None: + super().__init__(request) + raise NotImplementedError() + + +class InviteHandler(HandlerBase): + _request: InviteRequest + + def _data_operate(self) -> None: + chann = data.get_channel_by_name_and_ip_port( + self._request.channel_name, + self._request.client_ip, + self._request.client_port, + self._session, + ) + if chann is None: + raise NoSuchChannelException( + "you have to be in this channel to invite your friends" + ) + + assert isinstance(chann.invited_nicks, list) + chann.invited_nicks.append(self._request.nick_name) + + +class ListHandler(HandlerBase): + _request: ListRequest + + def _request_check(self) -> None: + if self._request.is_searching_channel: + pass + elif self._request.is_searching_user: + pass + else: + raise ChatException("request is invalid") + + def _data_operate(self) -> None: + if self._request.is_searching_channel: + # get the channel names with the substring + self._data = data.find_channel_by_substring( + self._request.filter, self._session + ) + return + if self._request.is_searching_user: + # get the user names with the substring + self._data = data.find_user_by_substring( + self._request.filter, self._session + ) + + def _result_construct(self) -> None: + assert self._user + assert isinstance(self._user.nick_name, str) + assert isinstance(self._user.user_name, str) + + data = [] + for d in self._data: + dd = ListResult.ListInfo(**d) + data.append(dd) + self._result = ListResult( + invoker_nick_name=self._user.nick_name, + invoker_user_name=self._user.user_name, + channel_info_list=data, + ) + + +class LoginPreAuthHandler(HandlerBase): + _request: LoginPreAuthRequest + + def _data_operate(self) -> None: + raise NotImplementedError("should this access to PCM's api?") + + +class LoginHandler(HandlerBase): + def _data_operate(self) -> None: + raise NotImplementedError("should this access to PCM's api?") + + +class NickHandler(HandlerBase): + _request: NickRequest + response: NicksResponse + + def _request_check(self) -> None: + self._get_user() + + def _data_operate(self) -> None: + # some game do not use CRYPT + # todo check game with no encryption send nick or user request first + if self._user is None: + # assign nick_name to current user + self._user = ChatUserCaches( + server_id=self._request.server_id, + remote_ip=self._request.client_ip, + remote_port=self._request.client_port, + nick_name=f"{self._request.client_ip}:{self._request.client_port}", + websocket_address=self._request.websocket_address, + game_name="", + ) + else: + assert isinstance(self._user.update_time, datetime) + if (datetime.now() - self._user.update_time).seconds > 120: + # old profile delete it + self._session.delete(self._user) + # data.remove_user_cache(cache) + self._user.nick_name = self._request.nick_name # type: ignore + return + if ( + self._user.remote_ip != self._request.client_ip # type: ignore + and self._user.remote_port != self._request.client_port # type: ignore + ): # type: ignore + raise NickNameInUseException( + old_nick=self._request.nick_name, + new_nick="", + message="nick name in use", + ) + else: + # update user cache + self._user.nick_name = self._request.nick_name # type: ignore + self._session.commit() + + def _result_construct(self) -> None: + self._result = NickResult(nick_name=self._request.nick_name) + + +class QuitHandler(HandlerBase): + _request: QuitRequest + + def _data_operate(self) -> None: + data.remove_user_cache_by_ip_port( + self._request.client_ip, self._request.client_port, self._session + ) + data.remove_channel_user_caches_by_ip_port( + self._request.client_ip, self._request.client_port, self._session + ) + self._session.commit() + + +class RegisterNickHandler(HandlerBase): + def _data_operate(self) -> None: + raise NotImplementedError( + "we do not know which unique nick should be updated") + + +class SetKeyHandler(HandlerBase): + _request: SetKeyRequest + response: OKResponse + + def _data_operate(self) -> None: + user = data.get_user_cache_by_ip_port( + self._request.client_ip, self._request.client_port, self._session + ) + if user is None: + raise NoSuchNickException( + "The ip and port is not find in database") + + user.key_value = self._request.key_values # type:ignore + self._session.commit() + + +class UserHandler(HandlerBase): + _request: UserRequest + + # def _request_check(self) -> None: + # data.clean_expired_user_cache(self._session) + # super()._request_check() + + def _data_operate(self) -> None: + self._user.user_name = self._request.user_name # type: ignore + self._session.commit() + + +class WhoHandler(HandlerBase): + _request: WhoRequest + + def _data_operate(self) -> None: + if self._request.request_type == WhoRequestType.GET_CHANNEL_USER_INFO: + self._get_channel_user_info() + else: + self._get_user_info() + + def _get_channel_user_info(self) -> None: + self._data = data.get_channel_user_caches( + self._request.channel_name, self._session + ) + + def _get_user_info(self) -> None: + self._data = data.get_channel_user_cache_by_ip( + self._request.client_ip, self._request.client_port, self._session + ) + + def _result_construct(self) -> None: + infos = [] + for d in self._data: + info = WhoResult.WhoInfo(**d) + infos.append(info) + self._result = WhoResult(infos=infos, + request_type=self._request.request_type, + channel_name=self._request.channel_name, nick_name=self._request.nick_name) + + +class WhoIsHandler(HandlerBase): + _request: WhoIsRequest + response: WhoIsResponse + + def _data_operate(self) -> None: + self._data: WhoIsResult = data.get_whois_result( + self._request.nick_name, self._session) + + def _result_construct(self) -> None: + self._result = self._data + + +# region Channel + + +class JoinHandler(ChannelHandlerBase): + _request: JoinRequest + response: JoinResponse + + def _request_check(self) -> None: + self._get_user() + self._check_user() + + self._get_channel() + + def _data_operate(self) -> None: + assert self._user is not None + + if self._channel is None: + self._channel = ChannelHelper.create( + server_id=self._request.server_id, + channel_name=self._request.channel_name, + password=self._request.password, + game_name=self._user.game_name, # type: ignore + room_name="", + topic="", + key_values={}, + creator=self._user.nick_name, # type: ignore + group_id=0, + max_num_user=100, + session=self._session, + ) + + self._channel_user = ChannelHelper.join( + self._channel, self._user, self._session + ) + self._channel_users_info = ChannelHelper.get_channel_all_nicks( + self._channel, self._session + ) + + def _result_construct(self) -> None: + assert self._channel_user + assert isinstance(self._channel_user.nick_name, str) + assert isinstance(self._channel_user.user_name, str) + + self._result = JoinResult( + joiner_nick_name=self._channel_user.nick_name, + joiner_user_name=self._channel_user.user_name, + channel_name=self._request.channel_name + ) + + +class GetChannelKeyHandler(ChannelHandlerBase): + _request: GetChannelKeyRequest + _values: list + + def _result_construct(self) -> None: + assert self._channel + assert isinstance(self._channel.key_values, dict) + assert self._user + assert isinstance(self._user.nick_name, str) + assert isinstance(self._user.user_name, str) + + self._result = GetChannelKeyResult( + channel_name=self._request.channel_name, + key_values=dict(self._channel.key_values), + nick_name=self._user.nick_name, + user_name=self._user.user_name, + cookie=self._request.cookie + ) + + +class GetCKeyHandler(ChannelHandlerBase): + _request: GetCKeyRequest + response: GetCkeyResponse + + def _data_operate(self) -> None: + match self._request.request_type: + case GetKeyRequestType.GET_CHANNEL_ALL_USER_KEY_VALUE: + self.get_channel_all_user_key_value() + case GetKeyRequestType.GET_CHANNEL_SPECIFIC_USER_KEY_VALUE: + self.get_channel_specific_user_key_value() + + def get_channel_all_user_key_value(self): + self._data = data.get_channel_user_caches_by_name( + self._request.channel_name, self._session + ) + + def get_channel_specific_user_key_value(self): + d = data.get_channel_user_cache_by_nick_name( + self._request.channel_name, self._request.nick_name, self._session + ) + if d is not None: + self._data = [d] + + def _result_construct(self) -> None: + if self._data is None: + return + infos = [] + for d in self._data: + assert isinstance(d, ChatChannelUserCaches) + assert isinstance(d.nick_name, str) + assert isinstance(d.key_values, dict) + info = GetCKeyResult.GetCKeyInfos( + nick_name=d.nick_name, + key_values=d.key_values + ) + infos.append(info) + + self._result = GetCKeyResult( + infos=infos, + channel_name=self._request.channel_name, + cookie=self._request.cookie, + keys=self._request.keys + ) + + +class KickHandler(ChannelHandlerBase): + _kickee: ChatChannelUserCaches | None + _request: KickRequest + response: KickResponse + + def __init__(self, request: RequestBase) -> None: + super().__init__(request) + self._kickee = None + + def _request_check(self) -> None: + super()._request_check() + assert isinstance(self._channel, ChatChannelCaches) + assert isinstance(self._channel.channel_name, str) + self._kickee = data.get_channel_user_cache_by_nick_name( + self._channel.channel_name, self._request.kickee_nick_name, self._session + ) + if self._kickee is None: + raise BadChannelKeyException( + f"kickee is not a user of channel:{self._channel.channel_name}" + ) + + def _data_operate(self) -> None: + assert self._channel + assert self._channel_user + assert self._kickee + ChannelHelper.kick( + self._session, + self._channel, + self._channel_user, + self._kickee, + ) + + def _result_construct(self) -> None: + assert self._channel_user + assert isinstance(self._channel_user.nick_name, str) + assert isinstance(self._channel_user.user_name, str) + self._result = KickResult( + channel_name=self._request.channel_name, + kicker_user_name=self._channel_user.user_name, + kicker_nick_name=self._channel_user.nick_name, + kickee_nick_name=self._request.kickee_nick_name, + reason=self._request.reason + ) + + +class ModeHandler(ChannelHandlerBase): + _request: ModeRequest + response: ModeResponse + + def _data_operate(self) -> None: + assert self._channel + assert self._channel_user + if self._request.request_type == ModeRequestType.SET_CHANNEL_MODES: + # set modes of channel + ChannelHelper.change_modes( + self._channel, self._channel_user, self._request, self._session + ) + + def _result_construct(self) -> None: + # we send the response when type is GET_CHANNEL_MODES + if self._request.request_type == ModeRequestType.GET_CHANNEL_MODES: + self._result = ModeResult( + channel_name=self._channel.channel_name, # type: ignore + channel_modes=self._channel.modes, # type: ignore + joiner_nick_name=self._user.nick_name, # type: ignore + ) + + +class NamesHandler(ChannelHandlerBase): + _request: NamesRequest + response: NamesResponse + + def _request_check(self) -> None: + self._get_user() + self._check_user() + + self._get_channel() + self._check_channel() + + def _data_operate(self) -> None: + assert self._channel + self._channel_users_info = ChannelHelper.get_channel_all_nicks( + self._channel, self._session + ) + + def _result_construct(self) -> None: + assert self._user + assert isinstance(self._user.nick_name, str) + nicks = [] + for nick in self._channel_users_info: + nick.channel_name # yield nick + data = NamesResultData(**nick.__dict__) + nicks.append(data) + + self._result = NamesResult( + channel_nicks=nicks, + channel_name=self._request.channel_name, + requester_nick_name=self._user.nick_name, + ) + + +class PartHandler(ChannelHandlerBase): + _request: PartRequest + response: PartResponse + + def _data_operate(self) -> None: + assert self._channel + assert self._channel_user + ChannelHelper.quit(self._channel, self._channel_user, self._session) + + def _result_construct(self) -> None: + assert self._channel_user + assert self._channel + if TYPE_CHECKING: + assert isinstance(self._channel_user.is_channel_creator, bool) + assert isinstance(self._channel_user.is_channel_operator, bool) + assert isinstance(self._channel.channel_name, str) + assert isinstance(self._channel_user.nick_name, str) + assert isinstance(self._channel_user.user_name, str) + + self._result = PartResult( + leaver_nick_name=self._channel_user.nick_name, + leaver_user_name=self._channel_user.user_name, + is_channel_creator=self._channel_user.is_channel_creator, + channel_name=self._channel.channel_name, + reason=self._request.reason + ) + + +class SetChannelKeyHandler(ChannelHandlerBase): + _request: SetChannelKeyRequest + response: SetChannelKeyResponse + + def _request_check(self) -> None: + super()._request_check() + assert self._channel is not None + assert self._channel_user is not None + assert isinstance(self._channel_user.is_channel_operator, bool) + if self._channel_user.is_channel_operator: + ChannelHelper.update_channel_key_values( + self._request.key_values, self._channel, self._session) + + def _result_construct(self) -> None: + assert self._channel_user + assert isinstance(self._channel_user.nick_name, str) + assert isinstance(self._channel_user.user_name, str) + + self._result = SetChannelKeyResult( + setter_nick_name=self._channel_user.nick_name, + setter_user_name=self._channel_user.user_name, + channel_name=self._request.channel_name, + key_value=self._request.key_values + ) + + +class SetCKeyHandler(ChannelHandlerBase): + """ + todo check if set channel_user or user keyvalue or set for other channeluser keyvalue + """ + + _request: SetCKeyRequest + response: SetCKeyResponse + + def _data_operate(self) -> None: + assert self._channel_user is not None + self._channel_user.key_values = self._request.key_values # type:ignore + self._session.commit() + + def _result_construct(self) -> None: + assert self._channel_user + assert isinstance(self._channel_user.nick_name, str) + assert isinstance(self._channel_user.user_name, str) + self._result = SetCKeyResult( + setter_nick_name=self._channel_user.nick_name, + setter_user_name=self._channel_user.user_name, + channel_name=self._request.channel_name, + key_value=self._request.key_values, + cookie=self._request.cookie + ) + + +class TopicHandler(ChannelHandlerBase): + _request: TopicRequest + response: TopicResponse + + def _data_operate(self) -> None: + assert self._channel_user + assert isinstance(self._channel_user.is_channel_operator, bool) + if self._request.request_type is TopicRequestType.GET_CHANNEL_TOPIC: + self._data: str = self._channel.topic # type:ignore + else: + if not self._channel_user.is_channel_operator: + raise NoSuchChannelException( + "inorder to set channel topic, you have to be channel operator" + ) + self._data: str = self._request.channel_topic + self._channel.topic = self._request.channel_topic # type:ignore + self._session.commit() + + def _result_construct(self) -> None: + self._result = TopicResult( + channel_name=self._request.channel_name, channel_topic=self._data + ) + + +# region Message + + +class AtmHandler(MessageHandlerBase): + _request: AtmRequest + response: AtmResponse + + def _result_construct(self) -> None: + assert self._user is not None + assert isinstance(self._user.nick_name, str) + assert isinstance(self._user.user_name, str) + + self._result = AtmResult( + sender_nick_name=self._user.nick_name, + sender_user_name=self._user.user_name, + target_name=self._request.target_name, + message=self._request.message + ) + + +class UtmHandler(MessageHandlerBase): + _request: UtmRequest + response: UtmResponse + + def _result_construct(self) -> None: + assert self._user is not None + assert isinstance(self._user.nick_name, str) + assert isinstance(self._user.user_name, str) + + self._result = UtmResult( + sender_nick_name=self._user.nick_name, sender_user_name=self._user.user_name, + target_name=self._request.target_name, + message=self._request.message + ) + + +class NoticeHandler(MessageHandlerBase): + _request: NoticeRequest + response: NoticeResponse + + def _result_construct(self) -> None: + assert self._user is not None + assert isinstance(self._user.nick_name, str) + assert isinstance(self._user.user_name, str) + + self._result = NoticeResult( + sender_nick_name=self._user.nick_name, sender_user_name=self._user.user_name, + target_name=self._request.target_name, + message=self._request.message + ) + + +class PrivateHandler(MessageHandlerBase): + _request: PrivateRequest + response: PrivateResponse + + def _result_construct(self) -> None: + assert self._user is not None + assert isinstance(self._user.nick_name, str) + assert isinstance(self._user.user_name, str) + + self._result = PrivateResult( + sender_nick_name=self._user.nick_name, sender_user_name=self._user.user_name, + target_name=self._request.target_name, + message=self._request.message + ) + + +class PublishMessageHandler(hb.HandlerBase): + _request: PublishMessageRequest + response: OKResponse + + def _data_operate(self) -> None: + # todo add checking on request validation, like broadcast key + PublishMessageHandler.broad_cast_loacl(self._request) + PublishMessageHandler.broadcast_global(self._request) + + @staticmethod + def broad_cast_loacl(request: PublishMessageRequest): + ws = MANAGER.get_websocket(request.client_ip) + if ws is not None: + # if websocket is not none means the frontend that gamespy client connect to is connecting to this backend + # then we just broad cast on this channel + MANAGER.broadcast_channel_message( + request.channel_name, request.model_dump_json(), ws) + + @staticmethod + def broadcast_global(request: PublishMessageRequest): + BROCKER.publish_message(request.model_dump_json()) diff --git a/src/backends/protocols/gamespy/chat/helper.py b/src/backends/protocols/gamespy/chat/helper.py new file mode 100644 index 000000000..c3f8e2a2f --- /dev/null +++ b/src/backends/protocols/gamespy/chat/helper.py @@ -0,0 +1,323 @@ +from datetime import datetime +from typing import cast +from uuid import UUID + +from backends.library.database.pg_orm import ( + ENGINE, + ChatChannelCaches, + ChatChannelUserCaches, + ChatUserCaches, +) +import backends.protocols.gamespy.chat.data as data +from backends.protocols.gamespy.chat.requests import ModeRequest +from frontends.gamespy.protocols.chat.aggregates.enums import ModeName, ModeOperation +from frontends.gamespy.protocols.chat.aggregates.exceptions import ( + BadChannelKeyException, + BannedFromChanException, + InviteOnlyChanException, + NoSuchChannelException, +) + +from sqlalchemy.orm import Session + + +class ChannelUserHelper: + @staticmethod + def get_mode_string(user: ChatChannelUserCaches): + assert isinstance(user.is_channel_operator, bool) + assert isinstance(user.is_voiceable, bool) + buffer = "" + if user.is_channel_operator: + buffer += "@" + if user.is_voiceable: + buffer += "+" + return buffer + + @staticmethod + def connect(ip: str, port: str): + pass + + @staticmethod + def disconnect(websocket_address: str): + with Session(ENGINE) as session: + user = data.get_user_cache_by_ws(websocket_address, session) + if user is None: + return + session.delete(user) + channel_users = data.get_channel_user_list_by_ip_port( + user.remote_ip, # type: ignore + user.remote_port, # type: ignore + session, + ) + for user in channel_users: + session.delete(user) + session.commit() + + +class ChannelHelper: + @staticmethod + def join( + channel: ChatChannelCaches, user: ChatUserCaches, session: Session + ) -> ChatChannelUserCaches: + assert isinstance(channel, ChatChannelCaches) + assert isinstance(channel.channel_name, str) + assert isinstance(channel.modes, list) + assert isinstance(user.nick_name, str) + assert isinstance(channel.banned_nicks, list) + # 1 check if is a invited channel + # 1.1 check if user is in a invited list + channel_modes = [ModeName(m) for m in channel.modes] + if ModeName.INVITED_ONLY in channel_modes: + if user.nick_name not in channel.invited_nicks: + raise InviteOnlyChanException( + f"You can only join channel: {channel.channel_name} when you are in invite list" + ) + + # 2 check if user is in ban list, if it is user can not join + if user.nick_name in channel.banned_nicks: + raise BannedFromChanException( + "can not join channel, because you are in ban list" + ) + + data.check_channel_user_trash_data(channel, user, session) + + if channel.creator == user.nick_name: # type:ignore + is_creator = True + is_operator = True + else: + is_creator = False + is_operator = False + + chan_user = ChatChannelUserCaches( + server_id=user.server_id, + nick_name=user.nick_name, + user_name=user.user_name, + channel_name=channel.channel_name, + is_voiceable=True, + is_channel_operator=is_operator, + is_channel_creator=is_creator, + remote_ip=user.remote_ip, + remote_port=user.remote_port, + ) + session.add(chan_user) + + session.commit() + return chan_user + + @staticmethod + def quit( + channel: ChatChannelCaches, quiter: ChatChannelUserCaches, session: Session + ) -> None: + assert isinstance(quiter, ChatChannelUserCaches) + assert isinstance(channel, ChatChannelCaches) + assert isinstance(quiter.channel_name, str) + assert isinstance(channel.channel_name, str) + + if quiter.channel_name != channel.channel_name: # type:ignore + print("user is not in channel, so can not quit") + return + session.delete(quiter) + session.commit() + + @staticmethod + def kick( + session: Session, + channel: ChatChannelCaches, + kicker: ChatChannelUserCaches, + kickee: ChatChannelUserCaches, + ) -> None: + assert isinstance(channel, ChatChannelCaches) + assert isinstance(kicker, ChatChannelUserCaches) + assert isinstance(kickee, ChatChannelUserCaches) + assert isinstance(kicker.channel_name, str) + assert isinstance(channel.channel_name, str) + assert isinstance(kickee.channel_name, str) + if kicker.channel_name != channel.channel_name: # type:ignore + raise BadChannelKeyException( + f"kicker is not in channel: {channel.channel_name}" + ) + if kickee.channel_name != channel.channel_name: # type:ignore + raise BadChannelKeyException( + f"kickee is not in channel: {channel.channel_name}" + ) + if not kicker.is_channel_operator: # type:ignore + raise BadChannelKeyException( + "kick failed, kicker is not channel operator") + session.delete(kickee) + session.commit() + + @staticmethod + def invite( + channel: ChatChannelCaches, + inviter: ChatChannelUserCaches, + invitee: ChatUserCaches, + ) -> None: + if str(inviter.channel_name) != str(channel.channel_name): + raise InviteOnlyChanException( + f"The inviter:{inviter.nick_name} is not a user in channel:{channel.channel_name}." + ) + + assert isinstance(channel.invited_nicks, list) + channel.invited_nicks.append(invitee.nick_name) + with Session(ENGINE) as session: + session.commit() + + @staticmethod + def create( + server_id: UUID, + channel_name: str, + password: str | None, + game_name: str, + room_name: str, + topic: str, + group_id: int, + max_num_user: int, + key_values: dict, + session: Session, + modes: list = [], + creator: str | None = None, + ) -> ChatChannelCaches: + # check whether if channel exist, if not user is creator + is_exist = data.is_channel_exist(channel_name, game_name, session) + if is_exist: + raise NoSuchChannelException( + f"Channel: {channel_name} is already exist, can not create a new one" + ) + cache = ChatChannelCaches( + server_id=server_id, + channel_name=channel_name, + password=password, + game_name=game_name, + room_name=room_name, + topic=topic, + group_id=group_id, + max_num_user=max_num_user, + key_values=key_values, + creator=creator, + modes=modes, + ) + session.add(cache) + session.commit() + + return cache + + @staticmethod + def change_modes( + channel: ChatChannelCaches, + changer: ChatChannelUserCaches, + request: ModeRequest, + session: Session, + ): + assert isinstance(channel, ChatChannelCaches) + assert isinstance(changer, ChatChannelUserCaches) + channel_modes = cast(list, channel.modes) + for flag, operation in request.mode_operations.items(): + match flag: + case ModeName.USER_QUIET_FLAG: + if operation == ModeOperation.SET: + if changer.is_channel_operator: # type:ignore + if flag.value not in channel_modes: + channel_modes.append(flag.value) + else: + if changer.is_channel_operator: # type:ignore + if flag.value in channel_modes: + channel_modes.remove(flag.value) + case ModeName.CHANNEL_PASSWORD: + if operation == ModeOperation.SET: + assert isinstance(request.password, str) + if changer.is_channel_operator: # type:ignore + channel.password = request.password # type:ignore + else: + if changer.is_channel_operator: # type:ignore + channel.password = None # type:ignore + case ModeName.CHANNEL_USER_LIMITS: + if operation == ModeOperation.SET: + channel.max_num_user = request.limit_number # type: ignore + else: + channel.max_num_user = 200 # type: ignore + case ModeName.BAN_ON_USER: + assert isinstance(channel.banned_nicks, list) + if operation == ModeOperation.SET: + # type: ignore + if request.nick_name not in list(channel.banned_nicks): + channel.banned_nicks.append(request.nick_name) + else: + if request.nick_name in list(channel.banned_nicks): + channel.banned_nicks.remove(request.nick_name) + case ModeName.CHANNEL_OPERATOR: + if operation == ModeOperation.SET: + if request.nick_name is None: + raise BadChannelKeyException( + "ADD_CHANNEL_OPERATOR require nick name" + ) + u = data.get_channel_user_cache_by_nick_name( + request.channel_name, request.nick_name, session + ) + if u is None: + raise BadChannelKeyException( + f"no user found with nick name:{request.nick_name}" + ) + u.is_channel_operator = True # type: ignore + else: + if request.nick_name is None: + raise BadChannelKeyException( + "REMOVE_CHANNEL_OPERATOR require nick name" + ) + u = data.get_channel_user_cache_by_nick_name( + request.channel_name, request.nick_name, session + ) + u.is_channel_operator = False # type: ignore + case ModeName.USER_VOICE_PERMISSION: + if operation == ModeOperation.SET: + if request.nick_name is None: + raise BadChannelKeyException( + "ENABLE_USER_VOICE_PERMISSION require nick name" + ) + u = data.get_channel_user_cache_by_nick_name( + request.channel_name, request.nick_name, session + ) + u.is_voiceable = True # type: ignore + else: + if request.nick_name is None: + raise BadChannelKeyException( + "DISABLE_USER_VOICE_PERMISSION require nick name" + ) + u = data.get_channel_user_cache_by_nick_name( + request.channel_name, request.nick_name, session + ) + u.is_voiceable = False # type: ignore + session.commit() + + @staticmethod + def get_all_user_nick_string(channel: ChatChannelCaches, session: Session) -> str: + assert isinstance(channel, ChatChannelCaches) + assert isinstance(channel.channel_name, str) + users = data.get_channel_user_caches_by_name( + channel.channel_name, session) + nicks = "" + for user in users: + assert isinstance(user.is_channel_creator, bool) + assert isinstance(user.nick_name, str) + if user.is_channel_creator: + nicks += f"@{user.nick_name}" + else: + nicks += user.nick_name + # use space as seperator + if user != users[-1]: + nicks += " " + return nicks + + @staticmethod + def get_channel_all_nicks( + channel: ChatChannelCaches, session: Session + ) -> list[ChatChannelUserCaches]: + assert channel is not None + assert isinstance(channel.channel_name, str) + users = data.get_channel_user_caches_by_name( + channel.channel_name, session) + return users + + @staticmethod + def update_channel_key_values(kv: dict, channel: ChatChannelCaches, session: Session): + channel.key_values = kv # type:ignore + session.commit() diff --git a/src/backends/protocols/gamespy/chat/requests.py b/src/backends/protocols/gamespy/chat/requests.py new file mode 100644 index 000000000..2e090447e --- /dev/null +++ b/src/backends/protocols/gamespy/chat/requests.py @@ -0,0 +1,220 @@ +import backends.library.abstractions.contracts as lib +from frontends.gamespy.protocols.chat.aggregates.enums import ( + GetKeyRequestType, + LoginRequestType, + MessageType, + ModeName, + ModeOperation, + ModeRequestType, + TopicRequestType, + WhoRequestType, +) + + +class RequestBase(lib.RequestBase): + raw_request: str + command_name: str + websocket_address: str + + +# region General + + +class CdkeyRequest(RequestBase): + cdkey: str + + +class CryptRequest(RequestBase): + version_id: str + gamename: str + + +class GetUdpRelayRequest(RequestBase): + pass + + +class InviteRequest(RequestBase): + channel_name: str + nick_name: str + + +class ListLimitRequest(RequestBase): + max_number_of_channels: int + filter: str + + +class ListRequest(RequestBase): + is_searching_channel: bool + is_searching_user: bool + filter: str + + +class LoginPreAuthRequest(RequestBase): + auth_token: str + partner_challenge: str + + +class LoginRequest(RequestBase): + request_type: LoginRequestType + namespace_id: int + nick_name: str + email: str + unique_nick: str + password_hash: str + + +class NickRequest(RequestBase): + nick_name: str + + +class PingRequest(RequestBase): + pass + + +class PongRequest(RequestBase): + echo_message: str + + +class QuitRequest(RequestBase): + reason: str + + +class RegisterNickRequest(RequestBase): + namespace_id: int + unique_nick: str + cdkey: str + + +class SetKeyRequest(RequestBase): + key_values: dict[str, str] + + +class UserIPRequest(RequestBase): + remote_ip: str + + +class UserRequest(RequestBase): + user_name: str + local_ip_address: str + server_name: str + name: str + + +class WhoIsRequest(RequestBase): + nick_name: str + + +class WhoRequest(RequestBase): + request_type: WhoRequestType + channel_name: str + nick_name: str + + +class GetKeyRequest(RequestBase): + is_get_all_user: bool + nick_name: str + cookie: str + unknown_cmd_param: str + keys: list[str] + + +# region Channel + + +class ChannelRequestBase(RequestBase): + channel_name: str + broad_cast_raw: str | None = None + + +class GetChannelKeyRequest(ChannelRequestBase): + cookie: str + keys: list + + +class GetCKeyRequest(ChannelRequestBase): + nick_name: str + cookie: str + keys: list + request_type: GetKeyRequestType + + +class JoinRequest(ChannelRequestBase): + password: str | None = None + + +class KickRequest(ChannelRequestBase): + kickee_nick_name: str + reason: str + + +class ModeRequest(ChannelRequestBase): + request_type: ModeRequestType + mode_operations: dict[ModeName, ModeOperation] + limit_number: int | None = None + mode_flag: str | None = None + password: str | None = None + nick_name: str | None = None + user_name: str | None = None + + +class NamesRequest(ChannelRequestBase): + pass + + +class PartRequest(ChannelRequestBase): + reason: str + + +class SetChannelKeyRequest(ChannelRequestBase): + key_value_string: str + key_values: dict[str, str] + is_broadcast: bool + + +class SetCKeyRequest(ChannelRequestBase): + nick_name: str + cookie: str + is_broadcast: bool + key_value_string: str + key_values: dict[str, str] + + +class SetGroupRequest(ChannelRequestBase): + group_name: str + + +class TopicRequest(ChannelRequestBase): + channel_topic: str + request_type: TopicRequestType + + +class MessageRequestBase(ChannelRequestBase): + type: MessageType + target_name: str + message: str + + +# region Message + + +class AtmRequest(MessageRequestBase): + pass + + +class NoticeRequest(MessageRequestBase): + pass + + +class PrivateRequest(MessageRequestBase): + pass + + +class UtmRequest(MessageRequestBase): + pass + + +class PublishMessageRequest(lib.RequestBase): + channel_name: str + sender_ip_address: str + sender_port: int + message: str diff --git a/src/backends/protocols/gamespy/chat/response.py b/src/backends/protocols/gamespy/chat/response.py new file mode 100644 index 000000000..4b504a8b0 --- /dev/null +++ b/src/backends/protocols/gamespy/chat/response.py @@ -0,0 +1,87 @@ +from backends.library.abstractions.contracts import DataResponse +from frontends.gamespy.protocols.chat.contracts.results import AtmResult, CryptResult, GetCKeyResult, GetChannelKeyResult, GetKeyResult, JoinResult, KickResult, ListResult, ModeResult, NamesResult, NickResult, NoticeResult, PartResult, PingResult, PrivateResult, SetCKeyResult, SetChannelKeyResult, TopicResult, UtmResult, WhoIsResult, WhoResult + + +class PingResponse(DataResponse): + result: PingResult + + +class CryptResponse(DataResponse): + result: CryptResult + + +class GetKeyResponse(DataResponse): + result: GetKeyResult + + +class ListResponse(DataResponse): + result: ListResult + + +class NicksResponse(DataResponse): + result: NickResult + + +class WhoResponse(DataResponse): + result: WhoResult + + +class WhoIsResponse(DataResponse): + result: WhoIsResult + + +class JoinResponse(DataResponse): + result: JoinResult + + +class GetChannelKeyResponse(DataResponse): + result: GetChannelKeyResult + + +class GetCkeyResponse(DataResponse): + result: GetCKeyResult + + +class KickResponse(DataResponse): + result: KickResult + + +class ModeResponse(DataResponse): + result: ModeResult + + +class NamesResponse(DataResponse): + result: NamesResult + + +class PartResponse(DataResponse): + result: PartResult + + +class SetChannelKeyResponse(DataResponse): + result: SetChannelKeyResult + + +class SetCKeyResponse(DataResponse): + result: SetCKeyResult + + +class TopicResponse(DataResponse): + result: TopicResult + + +class AtmResponse(DataResponse): + result: AtmResult + + +class UtmResponse(DataResponse): + result: UtmResult + + +class NoticeResponse(DataResponse): + result: NoticeResult + + +class PrivateResponse(DataResponse): + result: PrivateResult + diff --git a/src/backends/protocols/gamespy/game_status/data.py b/src/backends/protocols/gamespy/game_status/data.py new file mode 100644 index 000000000..50e141b83 --- /dev/null +++ b/src/backends/protocols/gamespy/game_status/data.py @@ -0,0 +1,78 @@ +from datetime import datetime +from typing import TYPE_CHECKING, cast + +from sqlalchemy import Column +from backends.library.database.pg_orm import ENGINE, PStorage, Profiles, SubProfiles, Users +from frontends.gamespy.protocols.game_status.aggregations.enums import PersistStorageType +from frontends.gamespy.protocols.game_status.aggregations.exceptions import GSException +from sqlalchemy.orm import Session + + +def get_player_data(profile_id: int, storage_type: PersistStorageType, data_index: int, session: Session) -> PStorage | None: + result = (session.query(PStorage) + .where(PStorage.ptype == storage_type.value, + PStorage.dindex == data_index, + PStorage.profileid == profile_id).first()) + return result + + +def create_new_game_data(): + raise NotImplementedError() + + +def create_player_data(profile_id: int, ptype, dindex, data: str, session: Session) -> None: + pd = PStorage( + profileid=profile_id, + ptype=ptype, + dindex=dindex, + data=data + ) + session.add(pd) + session.commit() + + +def update_player_data(pd: PStorage, data: str, session: Session) -> None: + pd.data = data # type: ignore + pd.update_time = datetime.now() # type: ignore + session.commit() + + +def get_profile_id_by_token(token: str, session: Session) -> int: + assert isinstance(token, str) + result = session.query(SubProfiles.profileid).where( + SubProfiles.authtoken == token).first() + if result is None: + raise GSException("No records found in database") + assert isinstance(result, int) + return result + + +def get_profile_id_by_profile_id(profile_id: int, session: Session) -> int: + assert isinstance(profile_id, int) + result = session.query(SubProfiles.profileid).where( + SubProfiles.profileid == profile_id).count() + if result != 1: + raise GSException(f"There is no profile_id {profile_id} existed") + assert isinstance(result, int) + return result + + +def get_profile_id_by_cdkey(cdkey: str, nick_name: str, session: Session) -> int: + if TYPE_CHECKING: + assert isinstance(Profiles.profileid, Column) + assert isinstance(Profiles.userid, Column) + assert isinstance(Users.userid, Column) + assert isinstance(Users.email, Column) + assert isinstance(Profiles.nick, Column) + assert isinstance(SubProfiles.profileid, Column) + assert isinstance(SubProfiles.cdkeyenc, Column) + + result = (session.query(Profiles.profileid) + .join(SubProfiles) + .where(SubProfiles.cdkeyenc == cdkey, + Profiles.nick == nick_name) + .first()) + if result is None: + raise GSException("No record found in database") + pid: int = result[0] + return pid diff --git a/src/backends/protocols/gamespy/game_status/handlers.py b/src/backends/protocols/gamespy/game_status/handlers.py new file mode 100644 index 000000000..eefff8ec2 --- /dev/null +++ b/src/backends/protocols/gamespy/game_status/handlers.py @@ -0,0 +1,181 @@ +from datetime import datetime +from backends.library.abstractions.contracts import OKResponse +from backends.library.abstractions.handler_base import HandlerBase +import backends.protocols.gamespy.game_status.data as data +from backends.protocols.gamespy.game_status.requests import ( + AuthGameRequest, + AuthPlayerRequest, + GetPlayerDataRequest, + GetProfileIdRequest, + NewGameRequest, + SetPlayerDataRequest, +) +from backends.protocols.gamespy.game_status.response import AuthGameResponse, AuthPlayerResponse, GetPlayerDataResponse, GetProfileIdResponse, SetPlayerDataResponse +from frontends.gamespy.protocols.game_status.aggregations.enums import AuthMethod +from frontends.gamespy.protocols.game_status.aggregations.exceptions import GSException +from frontends.gamespy.protocols.game_status.contracts.results import ( + AuthGameResult, + AuthPlayerResult, + GetPlayerDataResult, + GetProfileIdResult, + SetPlayerDataResult, + +) +import base64 + + +class AuthGameHandler(HandlerBase): + _request: AuthGameRequest + response: AuthGameResponse + + def _data_operate(self) -> None: + # generate session key + # todo: check whether need to store on database + self.session_key = "11111" + + def _result_construct(self) -> None: + self._result = AuthGameResult( + session_key=self.session_key, + local_id=self._request.local_id, + game_name=self._request.game_name) + + +class AuthPlayerHandler(HandlerBase): + _request: AuthPlayerRequest + response: AuthPlayerResponse + + def _data_operate(self): + match self._request.auth_type: + case AuthMethod.PARTNER_ID_AUTH: + if self._request.auth_token is None: + raise GSException("auth tocken is missing") + self.data = data.get_profile_id_by_token( + token=self._request.auth_token, + session=self._session) + case AuthMethod.PROFILE_ID_AUTH: + if self._request.profile_id is None: + raise GSException("profileid is missing") + self.data = data.get_profile_id_by_profile_id( + profile_id=self._request.profile_id, + session=self._session + ) + case AuthMethod.CDKEY_AUTH: + if self._request.cdkey_hash is None: + raise GSException("cdkey hash is required") + if self._request.nick is None: + raise GSException("nick is missing") + self.data = data.get_profile_id_by_cdkey( + cdkey=self._request.cdkey_hash, + nick_name=self._request.nick, + session=self._session + ) + case _: + raise GSException("Invalid auth type") + + def _result_construct(self): + self._result = AuthPlayerResult( + profile_id=self.data, local_id=self._request.local_id) + + +class GetPlayerDataHandler(HandlerBase): + _request: GetPlayerDataRequest + response: GetPlayerDataResponse + + def _data_operate(self): + self.pd = data.get_player_data( + self._request.profile_id, + self._request.storage_type, + self._request.data_index, + self._session + ) + if self.pd is None: + raise GSException("No records found in database") + + def _result_construct(self): + assert self.pd is not None + assert isinstance(self.pd.data, str) + assert isinstance(self.pd.update_time, datetime) + + if str(self.pd.data).endswith("=="): + data_formated = base64.b64decode(self.pd.data).decode() + else: + data_formated = self.pd.data + + self._result = GetPlayerDataResult( + local_id=self._request.local_id, + profile_id=self._request.profile_id, + data=data_formated, + modified=self.pd.update_time) + + +class GetProfileIdHandler(HandlerBase): + _request: GetProfileIdRequest + response: GetProfileIdResponse + + def _data_operate(self): + self.data = data.get_profile_id_by_cdkey( + cdkey=self._request.key_hash, + nick_name=self._request.nick, + session=self._session + ) + + def _result_construct(self): + self._result = GetProfileIdResult( + profile_id=self.data, + local_id=self._request.local_id) + + +class NewGameHandler(HandlerBase): + """ + find game based on the session key, and create a space for the game data + """ + _request: NewGameRequest + response: OKResponse + + def _data_operate(self): + self.data = data.create_new_game_data() + + +class SetPlayerDataHandler(HandlerBase): + _request: SetPlayerDataRequest + _result: SetPlayerDataResult + response: SetPlayerDataResponse + + def _data_operate(self): + if not self._request.is_key_value: + data_formated = base64.b64encode( + self._request.data.encode()).decode() + else: + data_formated = self._request.data + + pd = data.get_player_data(self._request.profile_id, + self._request.storage_type, + self._request.data_index, + self._session) + if pd is not None: + data.update_player_data(pd, + data_formated, + self._session) + else: + data.create_player_data( + self._request.profile_id, + self._request.storage_type, + self._request.data_index, + self._request.data, + self._session + ) + + def _result_construct(self) -> None: + self._result = SetPlayerDataResult( + local_id=self._request.local_id, + profile_id=self._request.profile_id, + modified=datetime.now() + ) + + +class UpdateGameHandler(HandlerBase): + _request: SetPlayerDataRequest + response: OKResponse + + def _data_operate(self): + raise NotImplementedError() diff --git a/src/backends/protocols/gamespy/game_status/requests.py b/src/backends/protocols/gamespy/game_status/requests.py new file mode 100644 index 000000000..febd40582 --- /dev/null +++ b/src/backends/protocols/gamespy/game_status/requests.py @@ -0,0 +1,67 @@ +from pydantic import Field, model_validator +import backends.library.abstractions.contracts as lib +from frontends.gamespy.protocols.game_status.aggregations.enums import ( + AuthMethod, + PersistStorageType, +) +from frontends.gamespy.protocols.game_status.aggregations.exceptions import GSException + + +class RequestBase(lib.RequestBase): + raw_request: str + local_id: int + _request_dict: dict[str, str] + + +class AuthGameRequest(RequestBase): + game_name: str + + +class AuthPlayerRequest(RequestBase): + auth_type: AuthMethod + profile_id: int | None = None + auth_token: str | None = None + cdkey_hash: str | None = None + response: str | None = None + nick: str | None = None + + +class GetPlayerDataRequest(RequestBase): + profile_id: int + storage_type: PersistStorageType + data_index: int + is_get_all_data: bool = False + keys: list[str] + + +class GetProfileIdRequest(RequestBase): + nick: str + key_hash: str + + +class NewGameRequest(RequestBase): + is_client_local_storage_available: bool + challenge: str | None = None + connection_id: int = Field( + description="The session key that backend send to client." + ) + session_key: str = Field(description="The game session key") + + +class SetPlayerDataRequest(RequestBase): + profile_id: int + storage_type: PersistStorageType + data_index: int + length: int + report: str | None = None + data: str + is_key_value: bool + + +class UpdateGameRequest(RequestBase): + connection_id: int + is_done: bool + is_client_local_storage_available: bool + game_data: str + game_data_dict: dict[str, str] + session_key: str diff --git a/src/backends/protocols/gamespy/game_status/response.py b/src/backends/protocols/gamespy/game_status/response.py new file mode 100644 index 000000000..459d7749e --- /dev/null +++ b/src/backends/protocols/gamespy/game_status/response.py @@ -0,0 +1,22 @@ +from backends.library.abstractions.contracts import DataResponse +from frontends.gamespy.protocols.game_status.contracts.results import AuthGameResult, AuthPlayerResult, GetPlayerDataResult, GetProfileIdResult, SetPlayerDataResult + + +class AuthGameResponse(DataResponse): + result: AuthGameResult + + +class AuthPlayerResponse(DataResponse): + result: AuthPlayerResult + + +class GetPlayerDataResponse(DataResponse): + result: GetPlayerDataResult + + +class GetProfileIdResponse(DataResponse): + result: GetProfileIdResult + + +class SetPlayerDataResponse(DataResponse): + result: SetPlayerDataResult diff --git a/src/backends/protocols/gamespy/game_traffic_relay/data.py b/src/backends/protocols/gamespy/game_traffic_relay/data.py new file mode 100644 index 000000000..76aedad97 --- /dev/null +++ b/src/backends/protocols/gamespy/game_traffic_relay/data.py @@ -0,0 +1,69 @@ +from datetime import datetime, timedelta + +from uuid import UUID +from backends.library.database.pg_orm import RelayServerCaches +from sqlalchemy.orm import Session + + +def search_relay_server( + server_id: UUID, server_ip: str, session: Session +) -> RelayServerCaches | None: + result = ( + session.query(RelayServerCaches) + .where( + RelayServerCaches.server_id == server_id, + RelayServerCaches.public_ip == server_ip, + ) + .first() + ) + return result + + +def get_available_relay_serves(session: Session) -> list[RelayServerCaches]: + """ + Return + ------ + list of ip:port + """ + + result: list[RelayServerCaches] = session.query(RelayServerCaches).all() + return result + + +def update_relay_server(info: RelayServerCaches, session: Session): + info.update_time = datetime.now() # type: ignore + + session.commit() + + +def create_relay_server(info: RelayServerCaches, session: Session): + session.add(info) + session.commit() + + +def check_expired_server(session: Session): + expire_time = datetime.now()-timedelta(seconds=30) + session.query( + RelayServerCaches + ).where( + RelayServerCaches.update_time < expire_time + ).delete() + session.commit() + + +def delete_relay_server(server_id: UUID, ip_address: str, port: int, session: Session): + assert isinstance(server_id, UUID) + assert isinstance(ip_address, str) + assert isinstance(port, int) + + info = ( + session.query(RelayServerCaches) + .where( + RelayServerCaches.server_id == server_id, + RelayServerCaches.public_ip == ip_address, + RelayServerCaches.public_port == port, + ) + .first() + ) + session.delete(info) + session.commit() diff --git a/src/backends/protocols/gamespy/game_traffic_relay/handlers.py b/src/backends/protocols/gamespy/game_traffic_relay/handlers.py new file mode 100644 index 000000000..4a10890cd --- /dev/null +++ b/src/backends/protocols/gamespy/game_traffic_relay/handlers.py @@ -0,0 +1,34 @@ +from datetime import datetime, timedelta +import logging +import socket +from backends.library.abstractions.contracts import OKResponse +from backends.library.abstractions.handler_base import HandlerBase +from backends.library.database.pg_orm import RelayServerCaches +from backends.protocols.gamespy.game_traffic_relay.requests import ( + GtrHeartBeatRequest, +) + +import backends.protocols.gamespy.game_traffic_relay.data as data +from frontends.gamespy.library.exceptions.general import UniSpyException + + +class GtrHeartBeatHandler(HandlerBase): + _request: GtrHeartBeatRequest + response: OKResponse + + def _data_operate(self) -> None: + data.check_expired_server(self._session) + info = data.search_relay_server( + self._request.server_id, self._request.public_ip_address, self._session + ) + if info is None: + info = RelayServerCaches( + server_id=self._request.server_id, + public_ip=self._request.public_ip_address, + public_port=self._request.public_port, + client_count=self._request.client_count, + ) + data.create_relay_server(info, self._session) + else: + # refresh update time + data.update_relay_server(info, self._session) diff --git a/src/backends/protocols/gamespy/game_traffic_relay/requests.py b/src/backends/protocols/gamespy/game_traffic_relay/requests.py new file mode 100644 index 000000000..a0e857760 --- /dev/null +++ b/src/backends/protocols/gamespy/game_traffic_relay/requests.py @@ -0,0 +1,19 @@ +from uuid import UUID +from pydantic import BaseModel + +from backends.library.abstractions.contracts import RequestBase + +""" +There are 2 UpdateGTRServiceRequest class +The other one is in frontends/gamespy/protocols/game_traffic_relay/contracts/general.py +""" + + +class GtrHeartBeatRequest(RequestBase): + server_id: UUID + public_ip_address: str + public_port: int + client_count: int + raw_request: None = None + client_ip: None = None + client_port: None = None diff --git a/src/backends/protocols/gamespy/natneg/data.py b/src/backends/protocols/gamespy/natneg/data.py new file mode 100644 index 000000000..7b7f5b5cc --- /dev/null +++ b/src/backends/protocols/gamespy/natneg/data.py @@ -0,0 +1,171 @@ +from datetime import datetime, timedelta + +from backends.library.database.pg_orm import ( + InitPacketCaches, + NatResultCaches, + RelayServerCaches, +) +from frontends.gamespy.protocols.natneg.aggregations.enums import ( + NatClientIndex, + NatPortType, +) + +from sqlalchemy.orm import Session + + +def add_init_packet(info: InitPacketCaches, session: Session) -> None: + assert isinstance(info, InitPacketCaches) + + session.add(info) + session.commit() + + +def clean_expired_init_cache(session: Session) -> None: + session.query(InitPacketCaches).where( + InitPacketCaches.update_time < datetime.now() - timedelta(minutes=5) + ).delete() + session.commit() + + +def count_init_info(cookie: int, version: int, session: Session) -> int: + time = datetime.now() - timedelta(seconds=30) + + result = ( + session.query(InitPacketCaches) + .where( + InitPacketCaches.cookie == cookie, + InitPacketCaches.version == version, + InitPacketCaches.update_time <= time, + ) + .count() + ) + return result + + +def get_init_cache( + cookie: int, client_index: NatClientIndex, port_type: NatPortType, session: Session +) -> InitPacketCaches | None: + result = ( + session.query(InitPacketCaches) + .where( + InitPacketCaches.cookie == cookie, + InitPacketCaches.client_index == client_index, + InitPacketCaches.port_type == port_type, + ) + .first() + ) + return result + + +def get_init_caches( + cookie: int, client_index: NatClientIndex, session: Session +) -> list[InitPacketCaches]: + # query the latest init info with in 30 seconds + time = datetime.now() - timedelta(seconds=30) + + result = ( + session.query(InitPacketCaches) + .where( + InitPacketCaches.cookie == cookie, + InitPacketCaches.client_index == client_index, + InitPacketCaches.update_time >= time, + ) + .all() + ) + return result + + +def update_init_info(info: InitPacketCaches, session: Session) -> None: + assert isinstance(info, InitPacketCaches) + + session.commit() + + +def remove_init_info(info: InitPacketCaches, session: Session) -> None: + assert isinstance(info, InitPacketCaches) + + session.delete(info) + session.commit() + + +def store_nat_result_info(info: NatResultCaches, session: Session) -> None: + assert isinstance(info, NatResultCaches) + session.add(info) + session.commit() + + +def update_nat_result_info(info: NatResultCaches, session: Session) -> None: + """ + remove the exist record and store the newest record + """ + assert isinstance(info, NatResultCaches) + + session.query(NatResultCaches).where( + NatResultCaches.cookie == info.cookie, + NatResultCaches.public_ip == info.public_ip, + NatResultCaches.private_ip == info.private_ip + ).delete() + store_nat_result_info(info, session) + + +def remove_nat_result_info(info: NatResultCaches, session: Session) -> None: + assert isinstance(info, NatResultCaches) + + session.delete(info) + session.commit() + + +def get_nat_result_info(info: NatResultCaches, session: Session) -> list[NatResultCaches]: + assert isinstance(info.cookie, int) + assert isinstance(info.public_ip, str) + result = get_nat_result_info_by_cookie_ip( + info.cookie, info.public_ip, session + ) + return result + + +def get_nat_result_info_by_ip( + public_ip: str, session: Session +) -> list[NatResultCaches]: + result = ( + session.query(NatResultCaches) + .where( + NatResultCaches.public_ip == public_ip, + ) + .all() + ) + return result + + +def get_nat_result_info_by_cookie_ip( + cookie: int, public_ip: str, session: Session +) -> list[NatResultCaches]: + result = ( + session.query(NatResultCaches) + .where( + NatResultCaches.cookie == cookie, + NatResultCaches.public_ip == public_ip, + ) + .all() + ) + return result + + +def get_game_traffic_relay_servers( + session: Session, number: int | None = None +) -> list[RelayServerCaches]: + if number is None: + result = ( + session.query(RelayServerCaches) + .order_by(RelayServerCaches.client_count.desc()) + .all() + ) + else: + assert isinstance(number, int) + result = ( + session.query(RelayServerCaches) + .order_by(RelayServerCaches.client_count.desc()) + .limit(number) + .all() + ) + return result diff --git a/src/backends/protocols/gamespy/natneg/handlers.py b/src/backends/protocols/gamespy/natneg/handlers.py new file mode 100644 index 000000000..46ef13b2b --- /dev/null +++ b/src/backends/protocols/gamespy/natneg/handlers.py @@ -0,0 +1,184 @@ +from datetime import datetime, timezone +from time import sleep +from backends.library.abstractions.contracts import OKResponse +from backends.library.abstractions.handler_base import HandlerBase +from backends.library.database.pg_orm import InitPacketCaches, NatResultCaches +import backends.protocols.gamespy.natneg.data as data +from backends.protocols.gamespy.natneg.helpers import NatProtocolHelper, NatStrategy +from backends.protocols.gamespy.natneg.requests import ConnectRequest, InitRequest, ReportRequest +from backends.protocols.gamespy.natneg.responses import ConnectResponse +from frontends.gamespy.protocols.natneg.aggregations.enums import ( + ConnectPacketStatus, + NatClientIndex, +) +from frontends.gamespy.protocols.natneg.aggregations.exceptions import NatNegException +from frontends.gamespy.protocols.natneg.contracts.results import ConnectResult + + +class InitHandler(HandlerBase): + _request: InitRequest + response: OKResponse + + def __init__(self, request: InitRequest) -> None: + assert isinstance(request, InitRequest) + super().__init__(request) + + def _data_operate(self) -> None: + data.clean_expired_init_cache(self._session) + info = data.get_init_cache( + self._request.cookie, + self._request.client_index, + self._request.port_type, + self._session, + ) + if info is None: + info = InitPacketCaches( + cookie=self._request.cookie, + server_id=self._request.server_id, + version=self._request.version, + port_type=self._request.port_type, + client_index=self._request.client_index, + game_name=self._request.game_name, + use_game_port=self._request.use_game_port, + public_ip=self._request.client_ip, + public_port=self._request.client_port, + private_ip=self._request.private_ip, + private_port=self._request.private_port, + update_time=datetime.now(timezone.utc), + ) + data.add_init_packet(info, self._session) + else: + info.update_time = datetime.now(timezone.utc) # type: ignore + data.update_init_info(info, self._session) + + +class ConnectHandler(HandlerBase): + _request: ConnectRequest + _strategy: NatStrategy | None + _is_valid: bool + response: ConnectResponse + + def __init__(self, request: ConnectRequest) -> None: + super().__init__(request) + assert isinstance(request, ConnectRequest) + self._strategy = None + + def _data_operate(self) -> None: + # first sleep 5 time to + sleep(2) + self._get_client_pair() + + def _get_client_pair(self) -> None: + # analysis NAT of both parties and find the proper ips + init_infos_1 = data.get_init_caches( + self._request.cookie, self._request.client_index, self._session + ) + # choose the other index of the currect client + if self._request.client_index == NatClientIndex.GAME_CLIENT: + client_index_2 = NatClientIndex.GAME_SERVER + else: + client_index_2 = NatClientIndex.GAME_CLIENT + init_infos_2 = data.get_init_caches( + self._request.cookie, client_index_2, self._session + ) + if len(init_infos_1) == 0 or len(init_infos_2) == 0: + self._is_valid = False + self.logger.info( + f"client1 init count:{len(init_infos_1)}, client2 init count:{len(init_infos_2)}") + return + else: + self._is_valid = True + + assert isinstance(init_infos_1[0].public_ip, str) + assert isinstance(init_infos_2[0].public_ip, str) + nat_fail_infos = data.get_nat_result_info_by_ip( + init_infos_1[0].public_ip, self._session + ) + self._strategy = NatStrategy.USE_GAME_TRAFFIC_RALEY + if len(nat_fail_infos) != 0: + self._strategy = NatStrategy.USE_GAME_TRAFFIC_RALEY + else: + self._helper1 = NatProtocolHelper(init_infos_1) + self._helper2 = NatProtocolHelper(init_infos_2) + self._strategy = NatProtocolHelper.choose_nat_strategy( + self._helper1, self._helper2 + ) + + def _result_construct(self) -> None: + if not self._is_valid: + self._result = ConnectResult( + is_both_client_ready=False, + ip=None, + port=None, + status=None, + version=self._request.version, + cookie=self._request.cookie, + ) + return + + if self._strategy == NatStrategy.USE_PRIVATE_IP: + self._result = ConnectResult( + is_both_client_ready=True, + ip=self._helper2.private_ip, + port=self._helper2.private_port, + status=ConnectPacketStatus.NO_ERROR, + version=self._request.version, + cookie=self._request.cookie, + ) + elif self._strategy == NatStrategy.USE_PUBLIC_IP: + self._result = ConnectResult( + is_both_client_ready=True, + ip=self._helper2.public_ip, + port=self._helper2.public_port, + status=ConnectPacketStatus.NO_ERROR, + version=self._request.version, + cookie=self._request.cookie, + ) + + elif self._strategy == NatStrategy.USE_GAME_TRAFFIC_RALEY: + # get a small number of players server from database + relay_servers = data.get_game_traffic_relay_servers( + self._session, 5) + # select strategy to choose one gtr server + if len(relay_servers) == 0: + raise NatNegException( + "No relay server found, please check the database") + rs = relay_servers[0] + assert isinstance(rs.public_ip, str) + assert isinstance(rs.public_port, int) + self._result = ConnectResult( + is_both_client_ready=True, + ip=rs.public_ip, + port=rs.public_port, + status=ConnectPacketStatus.NO_ERROR, + version=self._request.version, + cookie=self._request.cookie, + ) + + +class ReportHandler(HandlerBase): + _request: ReportRequest + response: OKResponse + + def _data_operate(self) -> None: + init_cache = data.get_init_cache( + self._request.cookie, + self._request.client_index, + self._request.port_type, + self._session + ) + if init_cache is None: + raise NatNegException( + f"No init package found for report pacakge cookie: {self._request.cookie} client_index: {self._request.client_index}") + report_cache = NatResultCaches( + cookie=self._request.cookie, + public_ip=init_cache.public_ip, + private_ip=init_cache.private_ip, + is_success=self._request.is_nat_success, + port_mapping_scheme=self._request.mapping_scheme, + nat_type=self._request.nat_type, + port_type=self._request.port_type, + client_index=self._request.client_index, + game_name=self._request.game_name, + ) + data.update_nat_result_info(report_cache, self._session) diff --git a/src/backends/protocols/gamespy/natneg/helpers.py b/src/backends/protocols/gamespy/natneg/helpers.py new file mode 100644 index 000000000..37cd9e391 --- /dev/null +++ b/src/backends/protocols/gamespy/natneg/helpers.py @@ -0,0 +1,281 @@ +import enum +from backends.library.database.pg_orm import InitPacketCaches +from frontends.gamespy.protocols.natneg.aggregations.enums import ( + NatClientIndex, + NatPortMappingScheme, + NatPortType, + NatType, +) +from frontends.gamespy.protocols.natneg.aggregations.exceptions import NatNegException + + +class NatStrategy(enum.IntEnum): + USE_PUBLIC_IP = 0 + USE_PRIVATE_IP = 1 + USE_GAME_TRAFFIC_RALEY = 2 + + +class NatNegVersion(enum.IntEnum): + VERSION2 = 2 + VERSION3 = 3 + VERSION4 = 4 + + +class NatProtocolHelper: + address_infos: dict[NatPortType, InitPacketCaches] + nat_type: NatType + port_mapping: NatPortMappingScheme + guessed_next_port: int + cookie: int + version: int + client_index: NatClientIndex + public_ip: str + public_port: int + private_ip: str + private_port: int + + def __init__(self, init_caches: list[InitPacketCaches]) -> None: + if len(init_caches) < 3: + raise NatNegException( + "init cache length not enough for NAT determination") + self.nat_type = NatType.NO_NAT + self.port_mapping = NatPortMappingScheme.CONSISTENT_PORT + self.guessed_next_port = 0 + self.address_infos = {} + for cache in init_caches: + assert isinstance(cache.port_type, NatPortType) + self.address_infos[cache.port_type] = cache + + last_address_info = list(self.address_infos.values())[-1] + assert isinstance(last_address_info.cookie, int) + assert isinstance(last_address_info.version, int) + assert isinstance(last_address_info.client_index, NatClientIndex) + assert isinstance(last_address_info.public_ip, str) + assert isinstance(last_address_info.public_port, int) + assert isinstance(last_address_info.private_ip, str) + assert isinstance(last_address_info.private_port, int) + + self.cookie = last_address_info.cookie + self.version = last_address_info.version + self.client_index = last_address_info.client_index + self.public_ip = last_address_info.public_ip + self.public_port = last_address_info.public_port + self.private_ip = last_address_info.private_ip + self.private_port = last_address_info.private_port + + if self.version not in NatNegVersion: + raise NatNegException("Unknown natneg version") + version = NatNegVersion(self.version) + if version == NatNegVersion.VERSION2: + raise NatNegException("Version 1 not implemented") + elif version == NatNegVersion.VERSION3: + self._validate_version3() + NatProtocolHelper._determine_nat_type_version3(self) + elif version == NatNegVersion.VERSION4: + self._validate_version4() + NatProtocolHelper._determine_nat_type_version4(self) + + def _validate_version3(self): + if not ( + NatPortType.NN1 in self.address_infos + and NatPortType.NN2 in self.address_infos + ): + raise NatNegException("Incomplete init packets") + assert isinstance(self.address_infos[NatPortType.NN1].cookie, int) + assert isinstance(self.address_infos[NatPortType.NN2].cookie, int) + + if ( + self.address_infos[NatPortType.NN1].cookie + != self.address_infos[NatPortType.NN2].cookie + ): # type: ignore + raise NatNegException("Broken cookie") + if ( + self.address_infos[NatPortType.NN1].version + != self.address_infos[NatPortType.NN2].version + ): # type: ignore + raise NatNegException("Broken version") + if ( + self.address_infos[NatPortType.NN1].client_index + != self.address_infos[NatPortType.NN2].client_index + ): # type: ignore + raise NatNegException("Broken client index") + + if NatPortType.GP in self.address_infos: + if ( + self.address_infos[NatPortType.GP].cookie + != self.address_infos[NatPortType.NN1].cookie # type:ignore + or self.address_infos[NatPortType.GP].version + != self.address_infos[NatPortType.NN1].version # type:ignore + or self.address_infos[NatPortType.GP].client_index + # type:ignore + != self.address_infos[NatPortType.NN1].client_index + or self.address_infos[NatPortType.GP].use_game_port + # type:ignore + != self.address_infos[NatPortType.NN1].use_game_port + ): + raise NatNegException("GP packet info is not correct") + + def _validate_version4(self): + # TODO: some games will not send GP packet to NAT negotiation server; currently, the reason is unknown and requires more games for analysis. + # This will happen in GameClient + + if not ( + NatPortType.NN1 in self.address_infos + and NatPortType.NN2 in self.address_infos + and NatPortType.NN3 in self.address_infos + ): + raise NatNegException("Incomplete init packets") + + if ( + self.address_infos[NatPortType.NN1].cookie + != self.address_infos[NatPortType.NN2].cookie # type:ignore + or self.address_infos[NatPortType.NN1].cookie + != self.address_infos[NatPortType.NN3].cookie # type:ignore + ): # type: ignore + raise NatNegException("Broken cookie") + + if ( + self.address_infos[NatPortType.NN1].version + != self.address_infos[NatPortType.NN2].version # type:ignore + or self.address_infos[NatPortType.NN1].version + != self.address_infos[NatPortType.NN3].version # type:ignore + ): # type: ignore + raise NatNegException("Broken version") + + if ( + self.address_infos[NatPortType.NN1].client_index + != self.address_infos[NatPortType.NN2].client_index # type:ignore + or self.address_infos[NatPortType.NN1].client_index + != self.address_infos[NatPortType.NN3].client_index # type:ignore + ): # type: ignore + raise NatNegException("Broken client index") + + if ( + self.address_infos[NatPortType.NN1].use_game_port + != self.address_infos[NatPortType.NN2].use_game_port # type:ignore + or self.address_infos[NatPortType.NN1].use_game_port + != self.address_infos[NatPortType.NN3].use_game_port # type:ignore + ): # type: ignore + raise NatNegException("Broken use game port") + + if ( + self.address_infos[NatPortType.NN2].private_ip + != self.address_infos[NatPortType.NN3].private_ip + ): # type: ignore + raise NatNegException("Client is sending wrong init packet.") + + if NatPortType.GP in self.address_infos: + if ( + self.address_infos[NatPortType.GP].cookie + != self.address_infos[NatPortType.NN1].cookie # type:ignore + or self.address_infos[NatPortType.GP].version + != self.address_infos[NatPortType.NN1].version # type:ignore + or self.address_infos[NatPortType.GP].client_index + # type:ignore + != self.address_infos[NatPortType.NN1].client_index + or self.address_infos[NatPortType.GP].use_game_port + # type:ignore + != self.address_infos[NatPortType.NN1].use_game_port + ): # type: ignore + raise NatNegException("GP packet info is not correct") + + @staticmethod + def _determine_nat_type_version3(info: "NatProtocolHelper"): + if len(info.address_infos) < 3: + raise NatNegException( + "We need 3 init records to determine the nat type.") + + nn1 = info.address_infos[NatPortType.NN1] + nn2 = info.address_infos[NatPortType.NN2] + # no nat + if nn1.public_ip == nn1.private_ip and ( # type:ignore + nn2.public_ip == nn2.private_ip and nn2.public_port == nn1.public_port # type:ignore + ): # type: ignore + info.nat_type = NatType.NO_NAT + # detect cone + elif nn1.public_ip == nn2.public_ip and nn1.public_port == nn2.public_port: # type: ignore + info.nat_type = NatType.FULL_CONE + elif nn1.public_ip == nn2.public_ip and nn1.public_port != nn2.public_port: # type: ignore + info.nat_type = NatType.SYMMETRIC + info.port_mapping = NatPortMappingScheme.INCREMENTAL + # todo: get all interval of the port increment value + port_interval = nn2.public_port - nn1.public_port + info.guessed_next_port = nn2.public_port + port_interval # type: ignore + else: + info.nat_type = NatType.UNKNOWN + + @staticmethod + def _determine_nat_type_version4(info: "NatProtocolHelper"): + if len(info.address_infos) < 3: + raise NatNegException( + "We need 3 init records to determine the nat type.") + + nn1 = info.address_infos[NatPortType.NN1] + nn2 = info.address_infos[NatPortType.NN2] + nn3 = info.address_infos[NatPortType.NN3] + + # no nat + if ( + nn1.public_ip == nn1.private_ip # type:ignore + and ( + nn2.public_ip == nn2.private_ip and nn2.public_port == nn2.private_port # type:ignore + ) + and ( + nn3.public_ip == nn3.private_ip and nn3.public_port == nn3.private_port # type:ignore + ) + ): # type: ignore + info.nat_type = NatType.NO_NAT + # detect cone + elif ( + nn1.public_ip == nn2.public_ip and nn1.public_port == nn2.public_port # type:ignore + ) and (nn2.public_ip == nn3.public_ip and nn2.public_port == nn3.public_port): # type: ignore + info.nat_type = NatType.FULL_CONE + elif ( + nn1.public_ip == nn2.public_ip and nn1.public_port != nn2.public_port # type:ignore + ) or (nn2.public_ip == nn3.public_ip and nn2.public_port != nn3.public_port): # type: ignore + info.nat_type = NatType.SYMMETRIC + info.port_mapping = NatPortMappingScheme.INCREMENTAL + + # Calculate port increments + port_increment_1: int = nn2.public_port - nn1.public_port # type: ignore + port_increment_2: int = nn3.public_port - nn2.public_port # type: ignore + assert isinstance(port_increment_1, int) + assert isinstance(port_increment_2, int) + if port_increment_1 == port_increment_2: + info.guessed_next_port = port_increment_1 + else: + increase_interval = port_increment_2 - port_increment_1 + info.guessed_next_port = port_increment_2 + increase_interval + else: + info.nat_type = NatType.UNKNOWN + + @staticmethod + def choose_nat_strategy( + helper1: "NatProtocolHelper", helper2: "NatProtocolHelper" + ) -> NatStrategy: + is_both_have_same_public_ip = helper1.public_ip == helper2.public_ip + # Check if the first 3 bytes of the private IP addresses are the same + is_both_in_same_private_ip_range = ( + helper1.private_ip.split( + ".")[:3] == helper2.private_ip.split(".")[:3] + ) + + # we use p2p strategy when nat punch is available + p2p_nat_types = [ + NatType.NO_NAT, + NatType.FIRE_WALL_ONLY, + NatType.FULL_CONE, + NatType.ADDRESS_RESTRICTED_CONE, + NatType.PORT_RESTRICTED_CONE, + ] + + if helper1.nat_type in p2p_nat_types and helper2.nat_type in p2p_nat_types: + if is_both_have_same_public_ip: + if is_both_in_same_private_ip_range: + return NatStrategy.USE_PRIVATE_IP + else: + return NatStrategy.USE_GAME_TRAFFIC_RALEY + else: + return NatStrategy.USE_PUBLIC_IP + else: + return NatStrategy.USE_GAME_TRAFFIC_RALEY diff --git a/src/backends/protocols/gamespy/natneg/requests.py b/src/backends/protocols/gamespy/natneg/requests.py new file mode 100644 index 000000000..9bed1fb24 --- /dev/null +++ b/src/backends/protocols/gamespy/natneg/requests.py @@ -0,0 +1,66 @@ +from frontends.gamespy.protocols.natneg.aggregations.enums import ( + NatClientIndex, + NatPortMappingScheme, + NatPortType, + NatType, + PreInitState, + RequestType, +) +from typing import Union + +import backends.library.abstractions.contracts as lib +from frontends.gamespy.protocols.natneg.contracts.results import ConnectResult + +# region Requests +class RequestBase(lib.RequestBase): + raw_request: str + version: int + cookie: int + port_type: NatPortType + command_name: RequestType + + +class CommonRequestBase(RequestBase): + client_index: NatClientIndex + use_game_port: bool + + +class AddressCheckRequest(CommonRequestBase): + pass + + +class ConnectAckRequest(RequestBase): + client_index: NatClientIndex + + +class ConnectRequest(CommonRequestBase): + """ + Server will send this request to client to let them connect to each other + """ + + +class ErtAckRequest(CommonRequestBase): + pass + + +class InitRequest(CommonRequestBase): + game_name: str | None = None + private_ip: str + private_port: int + + +class NatifyRequest(CommonRequestBase): + pass + + +class PreInitRequest(RequestBase): + state: Union[PreInitState, int] + target_cookie: list + + +class ReportRequest(CommonRequestBase): + is_nat_success: bool + game_name: str + nat_type: NatType + mapping_scheme: NatPortMappingScheme + diff --git a/src/backends/protocols/gamespy/natneg/responses.py b/src/backends/protocols/gamespy/natneg/responses.py new file mode 100644 index 000000000..df4e215bd --- /dev/null +++ b/src/backends/protocols/gamespy/natneg/responses.py @@ -0,0 +1,7 @@ +# region Response +from backends.library.abstractions.contracts import DataResponse +from frontends.gamespy.protocols.natneg.contracts.results import ConnectResult + + +class ConnectResponse(DataResponse): + result: ConnectResult diff --git a/src/backends/protocols/gamespy/presence_connection_manager/data.py b/src/backends/protocols/gamespy/presence_connection_manager/data.py new file mode 100644 index 000000000..c649d72f7 --- /dev/null +++ b/src/backends/protocols/gamespy/presence_connection_manager/data.py @@ -0,0 +1,628 @@ +# type:ignore +from datetime import datetime +from typing import TYPE_CHECKING, cast + +from sqlalchemy import Column +from backends.library.database.pg_orm import ( + Blocked, + FriendAddRequest, + Friends, + Profiles, + SubProfiles, + Users, +) +from frontends.gamespy.protocols.presence_connection_manager.aggregates.enums import ( + GPStatusCode, + LoginStatus, +) + +from frontends.gamespy.protocols.presence_connection_manager.contracts.results import ( + GetProfileData, + LoginData, +) +from frontends.gamespy.protocols.presence_search_player.aggregates.exceptions import ( + GPAddBuddyException, + GPDatabaseException, + GPStatusException, + GPException, +) +import backends.protocols.gamespy.presence_search_player.data as psp + +# region General +from sqlalchemy.orm import Session + + +def is_email_exist(email: str, session: Session): + return psp.is_email_exist(email, session) + + +def update_online_time(ip: str, port: int, session: Session): + if TYPE_CHECKING: + assert isinstance(Users.lastip, Column) + + result = session.query(Users).where(Users.lastip == ip).first() + if result is None: + return False + result.lastonline = datetime.now() + session.commit() + + +def delete_friend_by_profile_id(profile_id: int, session: Session): + friend = session.query(Friends).where( + Friends.friendid == profile_id).first() + if friend is None: + raise GPDatabaseException( + f"friend deletion have errors on profile id:{profile_id}" + ) + else: + session.delete(friend) + session.commit() + + +def get_blocked_profile_id_list( + profile_id: int, namespace_id: int, session: Session +) -> list[int]: + result = ( + session.query(Blocked.targetid) + .where(Blocked.profileid == profile_id, Blocked.namespaceid == namespace_id) + .all() + ) + if TYPE_CHECKING: + result = cast(list[int], result) + return result + + +def get_friend_profile_id_list( + profile_id: int, namespace_id: int, session: Session +) -> list[int]: + result = ( + session.query(Friends.targetid) + .where(Friends.profileid == profile_id, Friends.namespaceid == namespace_id) + .all() + ) + if TYPE_CHECKING: + result = cast(list[int], result) + return result + + +# region Profile + + +def get_profile_infos( + profile_id: int, session_key: str, session: Session +) -> GetProfileData: + """ + Retrieve profile information based on profile_id and namespace_id. + + Args: + profile_id (int): The ID of the profile to retrieve information for. + namespace_id (int): The ID of the namespace to filter the sub-profiles. + + Returns: + tuple: A tuple containing the profile information, sub-profile information, and user information. + """ + if TYPE_CHECKING: + assert isinstance(Profiles.profileid, Column) + assert isinstance(Profiles.userid, Column) + assert isinstance(SubProfiles.namespaceid, Column) + assert isinstance(SubProfiles.session_key, Column) + + namespace_id = ( + session.query(SubProfiles.namespaceid) + .where(SubProfiles.session_key == session_key) + .first() + ) + if namespace_id is None: + raise GPException("namespace not found") + + result = ( + session.query(Users, Profiles, SubProfiles) + .join(SubProfiles, Profiles.profileid == SubProfiles.profileid) + .join(Users, Profiles.userid == Users.userid) + .where( + Profiles.profileid == profile_id, + SubProfiles.namespaceid == namespace_id, + ) + .first() + ) + if result is None: + raise GPException("no profile found") + + if TYPE_CHECKING: + result = cast(tuple, result) + + user: Users = result[0] + profile: Profiles = result[1] + subprofile: SubProfiles = result[3] + if TYPE_CHECKING: + assert isinstance(profile.nick, str) + assert isinstance(profile.profileid, int) + assert isinstance(subprofile.uniquenick, str) + assert isinstance(user.email, str) + assert isinstance(Profiles.extra_info, dict) + + data = GetProfileData( + nick=profile.nick, + profile_id=profile.profileid, + unique_nick=subprofile.uniquenick, + email=user.email, + extra_infos=Profiles.extra_info, + ) + + return data + + +def get_user_info_list( + email: str, nick_name: str, session: Session +) -> list[tuple[int, int, int]]: + """ + Retrieve the user information list based on the provided email and nickname. + + Args: + email (str): The email address of the user to search for. + nick_name (str): The nickname of the user to search for. + + Returns: + List[Tuple[int, int, int]]: A list of tuples containing the userid, profileid, and subprofileid + of users that match the provided email and nickname in the database. + """ + if TYPE_CHECKING: + assert isinstance(Profiles.profileid, Column) + assert isinstance(Profiles.userid, Column) + assert isinstance(Users.userid, Column) + assert isinstance(Users.email, Column) + assert isinstance(Profiles.nick, Column) + + result = ( + session.query(Users.userid, Profiles.profileid, + SubProfiles.subprofileid) + .join(Users, Profiles.userid == Users.userid) + .join(SubProfiles, Profiles.profileid == SubProfiles.profileid) + .where(Users.email == email, Profiles.nick == nick_name) + .all() + ) + if TYPE_CHECKING: + result = cast(list[tuple[int, int, int]], result) + return result + + +def get_user_info( + unique_nick: str, namespace_id: int, session: Session +) -> tuple[int, int, int]: + # if TYPE_CHECKING: + # assert isinstance(Profiles.profileid, Column) + # assert isinstance(Profiles.userid, Column) + # assert isinstance(Users.userid, Column) + # assert isinstance(Users.email, Column) + # assert isinstance(Profiles.nick, Column) + # assert isinstance(SubProfiles.uniquenick, Column) + # assert isinstance(SubProfiles.namespaceid, Column) + + result = ( + session.query(Users.userid, Profiles.profileid, + SubProfiles.subprofileid) + .join(Users, Profiles.userid == Users.userid) + .join(SubProfiles, Profiles.profileid == SubProfiles.profileid) + .where( + SubProfiles.uniquenick == unique_nick, + SubProfiles.namespaceid == namespace_id, + ) + .first() + ) + if TYPE_CHECKING: + result = cast(tuple[int, int, int], result) + return result + + +_login_infos = [Users.userid, + Profiles.profileid, + SubProfiles.subprofileid, + Profiles.nick, + Users.email, + SubProfiles.uniquenick, + Users.password, + Users.emailverified, + Users.banned, + SubProfiles.namespaceid] + + +def get_user_infos_by_uniquenick_namespace_id( + unique_nick: str, namespace_id: int, session: Session +) -> LoginData | None: + if TYPE_CHECKING: + assert isinstance(Profiles.profileid, Column) + assert isinstance(Profiles.userid, Column) + assert isinstance(Users.userid, Column) + assert isinstance(Users.email, Column) + assert isinstance(Profiles.nick, Column) + assert isinstance(SubProfiles.uniquenick, Column) + assert isinstance(SubProfiles.namespaceid, Column) + assert isinstance(Users.password, Column) + assert isinstance(Users.emailverified, Column) + assert isinstance(Users.banned, Column) + + result = ( + session.query( + *_login_infos + ) + .join(Users, Profiles.userid == Users.userid) + .join(SubProfiles, Profiles.profileid == SubProfiles.profileid) + .where( + SubProfiles.uniquenick == unique_nick, + SubProfiles.namespaceid == namespace_id, + ) + .first() + ) + data = { + "user_id": result[0], + "profile_id": result[1], + "sub_profile_id": result[2], + "nick": result[3], + "email": result[4], + "unique_nick": result[5], + "password_hash": result[6], + "email_verified_flag": result[7], + "banned_flag": result[8], + "namespace_id": result[9], + } + if result is not None: + return LoginData(**data) # type: ignore + else: + return None + return result + + +def get_user_infos_by_nick_email( + nick: str, email: str, session: Session +) -> LoginData | None: + if TYPE_CHECKING: + assert isinstance(Profiles.profileid, Column) + assert isinstance(Profiles.userid, Column) + assert isinstance(Users.userid, Column) + assert isinstance(Users.email, Column) + assert isinstance(Users.password, Column) + assert isinstance(Users.emailverified, Column) + assert isinstance(Users.banned, Column) + assert isinstance(Profiles.nick, Column) + assert isinstance(SubProfiles.uniquenick, Column) + assert isinstance(SubProfiles.namespaceid, Column) + + result = ( + session.query( + *_login_infos + ) + .join(Users, Profiles.userid == Users.userid) + .join(SubProfiles, Profiles.profileid == SubProfiles.profileid) + .where(Users.email == email, Profiles.nick == nick) + .first() + ) + data = { + "user_id": result[0], + "profile_id": result[1], + "sub_profile_id": result[2], + "nick": result[3], + "email": result[4], + "unique_nick": result[5], + "password_hash": result[6], + "email_verified_flag": result[7], + "banned_flag": result[8], + "namespace_id": result[9], + } + if result is not None: + return LoginData(**data) # type: ignore + else: + return None + + +def update_online_status(user_id: int, status: LoginStatus, session: Session): + if TYPE_CHECKING: + assert isinstance(Users.userid, Column) + raise NotImplementedError("implement sesskey") + result = session.query(Users).where(Users.userid == user_id).first() + + +def get_user_infos_by_authtoken(auth_token: str, session: Session) -> LoginData | None: + if TYPE_CHECKING: + assert isinstance(Profiles.profileid, Column) + assert isinstance(Profiles.userid, Column) + assert isinstance(Users.userid, Column) + assert isinstance(Users.email, Column) + assert isinstance(Users.password, Column) + assert isinstance(Users.emailverified, Column) + assert isinstance(Users.banned, Column) + assert isinstance(Profiles.nick, Column) + assert isinstance(SubProfiles.uniquenick, Column) + assert isinstance(SubProfiles.namespaceid, Column) + assert isinstance(SubProfiles.authtoken, Column) + + result = ( + session.query( + *_login_infos + ) + .join(Users, Profiles.userid == Users.userid) + .join(SubProfiles, Profiles.profileid == SubProfiles.profileid) + .where(SubProfiles.authtoken == auth_token) + .first() + ) + + if result is not None: + keys = [ + "user_id", + "profile_id", + "sub_profile_id", + "nick", + "email", + "unique_nick", + "password_hash", + "email_verified_flag", + "banned_flag", + "namespace_id", + ] + data = {key: result[i] for i, key in enumerate(keys)} + return LoginData(**data) # type: ignore + else: + return None + + +def get_block_list(profile_id: int, namespace_id: int, session: Session) -> list[int]: + result = ( + session.query(Blocked.targetid) + .where( + Blocked.namespaceid == namespace_id, + Blocked.profileid == profile_id, + ) + .all() + ) + if TYPE_CHECKING: + result = cast(list[int], result) + return result + + +# region Buddy + + +def get_buddy_list(profile_id: int, namespace_id: int, session: Session) -> list[int]: + result = ( + session.query(Friends.targetid) + .where( + Blocked.namespaceid == namespace_id, + Blocked.profileid == profile_id, + ) + .all() + ) + # assert isinstance(result, list) + if TYPE_CHECKING: + result = cast(list[int], result) + return result + + +def update_block( + profile_id: int, target_id: int, session_key: str, session: Session +) -> None: + if TYPE_CHECKING: + assert isinstance(SubProfiles.session_key, Column) + + namespace_id = ( + session.query(SubProfiles).where( + SubProfiles.session_key == session_key).first() + ) + result = ( + session.query(Blocked) + .where( + Blocked.targetid == target_id, + Blocked.namespaceid == namespace_id, + Blocked.profileid == profile_id, + ) + .count() + ) + if result == 0: + b = Blocked(targetid=target_id, namespaceid=namespace_id, + profileid=profile_id) + session.add(b) + session.commit() + + +def update_friend_info( + target_id: int, profile_id: int, namespace_id: int, session: Session +): + result = ( + session.query(Friends) + .where( + Friends.targetid == target_id, + Friends.namespaceid == namespace_id, + Friends.profileid == profile_id, + ) + .count() + ) + f = Friends(targetid=target_id, namespaceid=namespace_id, + profileid=profile_id) + + if result == 0: + session.add(f) + session.commit() + + +def add_nick_name(profile_id: int, old_nick: str, new_nick: str, session: Session): + assert isinstance(profile_id, int) + assert isinstance(old_nick, str) + assert isinstance(new_nick, str) + if TYPE_CHECKING: + assert isinstance(Profiles.profileid, Column) + assert isinstance(Profiles.userid, Column) + assert isinstance(Users.userid, Column) + assert isinstance(Users.email, Column) + assert isinstance(Profiles.nick, Column) + + result = ( + session.query(Profiles) + .where(Profiles.profileid == profile_id, Profiles.nick == old_nick) + .first() + ) + + if result is None: + raise GPDatabaseException("No user infomation found in database.") + + result.nick = new_nick # type:ignore + session.commit() + + +# def update_profile_info(profile: Profiles): +# session.add(profile) +# session.commit() + + +def update_unique_nick(subprofile_id: int, unique_nick: str, session: Session): + result = ( + session.query(SubProfiles) + .where(SubProfiles.subprofileid == subprofile_id) + .first() + ) + result.uniquenick = unique_nick # type:ignore + session.commit() + + +def update_subprofile_info(subprofile: SubProfiles, session: Session): + session.add(subprofile) + session.commit() + + +def add_friend_request( + profileid: int, targetid: int, namespace_id: int, reason: str, session: Session +) -> None: + data = ( + session.query(FriendAddRequest) + .where( + FriendAddRequest.profileid == profileid, + FriendAddRequest.targetid == targetid, + FriendAddRequest.namespaceid == namespace_id, + ) + .first() + ) + if data is not None: + raise GPAddBuddyException("Request is existed, add friend ignored") + request = FriendAddRequest( + profileid=profileid, + targetid=targetid, + namespaceid=namespace_id, + reason=reason, + ) + session.add(request) + session.commit() + + +def get_status(session_key: str, session: Session) -> dict: + if TYPE_CHECKING: + assert isinstance(SubProfiles.session_key, Column) + + result = ( + session.query(Profiles) + .join(SubProfiles) + .where(SubProfiles.session_key == session_key) + .first() + ) + if result is None: + raise GPStatusException( + "No profile found with the provided session key") + + if TYPE_CHECKING: + assert isinstance(result.statstring, str) + assert isinstance(result.status, GPStatusCode) + if "location" not in result.extra_info: + result.extra_info["location"] = "" + data = { + "status_string": result.statstring, + "location_string": result.extra_info["locstring"], + "current_status": result.status, + } + return data + + +def update_status( + session_key: str, + current_status: GPStatusCode, + location_string: str, + status_string: str, + session: Session +): + if TYPE_CHECKING: + assert isinstance(SubProfiles.session_key, Column) + + result = ( + session.query(Profiles) + .join(SubProfiles) + .where(SubProfiles.session_key == session_key) + .first() + ) + if result is None: + raise GPStatusException( + "No profile found with the provided session key") + + result.statstring = status_string + result.status = current_status + assert isinstance(result.extra_info, dict) + result.extra_info['locstring'] = location_string + + session.commit() + + +def update_new_nick(session_key: str, old_nick: str, new_nick: str, session: Session): + result = ( + session.query(Profiles) + .join(SubProfiles) + .where(SubProfiles.session_key == session_key) + .first() + ) + if result.nick == old_nick and result.nick != new_nick: + result.nick = new_nick + session.commit() + + +def update_cdkey(session_key: str, cdkey: str, session: Session): + subprofile = ( + session.query(SubProfiles).where( + SubProfiles.session_key == session_key).first() + ) + if subprofile is None: + raise GPDatabaseException( + f"no subprofile found with session key:{session_key}") + + subprofile.cdkeyenc = cdkey + + session.commit() + + +def update_uniquenick(session_key: str, uniquenick: str, session: Session): + subprofile = ( + session.query(SubProfiles).where( + SubProfiles.session_key == session_key).first() + ) + if subprofile is None: + raise GPDatabaseException( + f"no subprofile found with session key:{session_key}") + + subprofile.uniquenick = uniquenick + session.commit() + + +def update_profiles(session_key: str, extra_info: dict, session: Session): + profile = ( + session.query(Profiles) + .join(SubProfiles) + .where(SubProfiles.session_key == session_key) + .first() + ) + if profile is None: + raise GPDatabaseException( + f"no profile found with session key:{session_key}") + for key, value in extra_info.items(): + profile.extra_info[key] = value + + session.commit() + + +def update_user(session_key): + raise NotImplementedError() + + +if __name__ == "__main__": + result = get_block_list(1, 1) diff --git a/src/backends/protocols/gamespy/presence_connection_manager/handlers.py b/src/backends/protocols/gamespy/presence_connection_manager/handlers.py new file mode 100644 index 000000000..d3c28519c --- /dev/null +++ b/src/backends/protocols/gamespy/presence_connection_manager/handlers.py @@ -0,0 +1,321 @@ +from backends.library.abstractions.contracts import OKResponse, RequestBase +from backends.library.abstractions.handler_base import HandlerBase +import backends.protocols.gamespy.presence_connection_manager.data as data +from backends.protocols.gamespy.presence_connection_manager.requests import ( + AddBlockRequest, + AddBuddyRequest, + BlockListRequest, + BuddyListRequest, + DelBuddyRequest, + GetProfileRequest, + InviteToRequest, + KeepAliveRequest, + LoginRequest, + LogoutRequest, + NewProfileRequest, + NewUserRequest, + RegisterCDKeyRequest, + RegisterNickRequest, + StatusInfoRequest, + StatusRequest, + UpdateProfileRequest, + UpdateUserInfoRequest, +) +from backends.protocols.gamespy.presence_connection_manager.responses import BlockListResponse, BuddyListResponse, GetProfileResponse, LoginResponse +from frontends.gamespy.protocols.presence_connection_manager.aggregates.enums import ( + LoginType, +) +from frontends.gamespy.protocols.presence_connection_manager.contracts.results import ( + BlockListResult, + BuddyListResult, + GetProfileResult, + LoginResult, +) +from frontends.gamespy.protocols.presence_search_player.aggregates.exceptions import ( + GPLoginBadEmailException, + GPLoginException, +) +# region General + + +class KeepAliveHandler(HandlerBase): + _request: KeepAliveRequest + response: OKResponse + + def _data_operate(self) -> None: + data.update_online_time( + self._request.client_ip, self._request.client_port, self._session + ) + + +class LoginHandler(HandlerBase): + _request: LoginRequest + response: LoginResponse + + def _data_operate(self) -> None: + if self._request.type == LoginType.NICK_EMAIL: + self._nick_email_login() + elif self._request.type == LoginType.UNIQUENICK_NAMESPACE_ID: + self._unique_nick_login() + elif self._request.type == LoginType.AUTH_TOKEN: + self._auth_token_login() + else: + raise ValueError("Request type not valid") + + def _nick_email_login(self) -> None: + assert self._request.email is not None + assert self._request.nick is not None + is_exsit = data.is_email_exist(self._request.email, self._session) + if not is_exsit: + raise GPLoginBadEmailException( + f"email: {self._request.email} is invalid.") + self._data = data.get_user_infos_by_nick_email( + self._request.nick, self._request.email, self._session + ) + + def _unique_nick_login(self) -> None: + assert self._request.unique_nick is not None + assert self._request.namespace_id is not None + self._data = data.get_user_infos_by_uniquenick_namespace_id( + self._request.unique_nick, self._request.namespace_id, self._session + ) + + def _auth_token_login(self) -> None: + assert self._request.auth_token is not None + self._data = data.get_user_infos_by_authtoken( + self._request.auth_token, self._session + ) + + def _result_construct(self) -> None: + if self._data is None: + raise GPLoginException("User do not exist.") + self._result = LoginResult(operation_id=self._request.operation_id, + data=self._data, + user_data=self._request.user_data, + type=self._request.type, + partner_id=self._request.partner_id, + user_challenge=self._request.user_challenge) + + +class LogoutHandler(HandlerBase): + _request: LogoutRequest + response: OKResponse + + def _data_operate(self) -> None: + # data.update_online_status(user_id=, status=LoginStatus.DISCONNECTED) + raise NotImplementedError() + + +class NewUserHandler(HandlerBase): + response: OKResponse + + def __init__(self, request: NewUserRequest) -> None: + raise NotImplementedError("Use presence search player newuser router") + super().__init__(request) + # region Profile + + # region Buddy + + +class BuddyListHandler(HandlerBase): + _request: BuddyListRequest + response: BuddyListResponse + + def _data_operate(self) -> None: + self.data = data.get_buddy_list( + self._request.profile_id, self._request.namespace_id, self._session + ) + + def _result_construct(self) -> None: + self._result = BuddyListResult( + profile_ids=self.data, operation_id=self._request.operation_id) + + +class BlockListHandler(HandlerBase): + _request: BlockListRequest + response: BlockListResponse + + def _data_operate(self) -> None: + self.data = data.get_block_list( + self._request.profile_id, self._request.namespace_id, self._session + ) + + def _result_construct(self) -> None: + self._result = BlockListResult( + profile_ids=self.data, operation_id=self._request.operation_id) + + +class BuddyStatusInfoHandler(HandlerBase): + """ + This is what the message should look like. Its broken up for easy viewing. + + "\\bsi\\\\state\\\\profile\\\\bip\\\\bport\\\\hostip\\\\hprivip\\" + "\\qport\\\\hport\\\\sessflags\\\\rstatus\\\\gameType\\" + "\\gameVnt\\\\gameMn\\\\product\\\\qmodeflags\\" + """ + + def __init__(self, request: RequestBase) -> None: + super().__init__(request) + raise NotImplementedError() + + +class DelBuddyHandler(HandlerBase): + _request: DelBuddyRequest + response: OKResponse + + def _data_operate(self) -> None: + self.data = data.delete_friend_by_profile_id( + self._request.target_id, self._session + ) + + +class AddBuddyHandler(HandlerBase): + _request: AddBuddyRequest + response: OKResponse + + def _data_operate(self) -> None: + data.add_friend_request( + self._request.profile_id, + self._request.target_id, + self._request.namespace_id, + self._request.reason, + self._session, + ) + + +class AddBlockHandler(HandlerBase): + _request: AddBlockRequest + response: OKResponse + + def _data_operate(self) -> None: + data.update_block( + self._request.profile_id, + self._request.taget_id, + self._request.session_key, + self._session, + ) + + +class InviteToHandler(HandlerBase): + _request: InviteToRequest + + def _data_operate(self) -> None: + # user is offline + # if (client is null) + # { + # return; + # } + # else + # { + + # } + # TODO + # parse user to buddy message system + raise NotImplementedError("whether need chat server to interact?") + + +class StatusHandler(HandlerBase): + _request: StatusRequest + response: OKResponse + + def _data_operate(self) -> None: + data.update_status( + self._request.session_key, + self._request.current_status, + self._request.location_string, + self._request.status_string, + self._session, + ) + + +class StatusInfoHandler(HandlerBase): + _request: StatusInfoRequest + response: OKResponse + + def _data_operate(self) -> None: + raise NotImplementedError() + + +# region Profile + + +class GetProfileHandler(HandlerBase): + _request: GetProfileRequest + response: GetProfileResponse + + def _data_operate(self) -> None: + self.data = data.get_profile_infos( + profile_id=self._request.profile_id, + session_key=self._request.session_key, + session=self._session, + ) + + def _result_construct(self) -> None: + self._result = GetProfileResult( + user_profile=self.data, operation_id=self._request.operation_id) + + +class NewProfileHandler(HandlerBase): + """ + update a exist profile + """ + + _request: NewProfileRequest + response: OKResponse + + def _data_operate(self) -> None: + data.update_new_nick( + self._request.session_key, + self._request.old_nick, + self._request.new_nick, + self._session, + ) + + +class RegisterCDKeyHandler(HandlerBase): + _request: RegisterCDKeyRequest + response: OKResponse + + def _data_operate(self): + data.update_cdkey( + self._request.session_key, self._request.cdkey_enc, self._session + ) + + +class RegisterNickHandler(HandlerBase): + """ + some game will not register uniquenick when create a new account, it will update its uniquenick later + """ + + _request: RegisterNickRequest + response: OKResponse + + def _data_operate(self): + data.update_uniquenick( + self._request.session_key, self._request.unique_nick, self._session + ) + + +class RemoveBlockHandler(HandlerBase): + def _data_operate(self): + raise NotImplementedError() + + +class UpdateProfileHandler(HandlerBase): + _request: UpdateProfileRequest + response: OKResponse + + def _data_operate(self): + data.update_profiles( + self._request.session_key, self._request.extra_infos, self._session + ) + + +class UpdateUserInfoHandler(HandlerBase): + _request: UpdateUserInfoRequest + response: OKResponse + + def _data_operate(self): + data.update_profiles( + self._request.session_key, self._request.extra_infos, self._session + ) diff --git a/src/backends/protocols/gamespy/presence_connection_manager/requests.py b/src/backends/protocols/gamespy/presence_connection_manager/requests.py new file mode 100644 index 000000000..1294802ff --- /dev/null +++ b/src/backends/protocols/gamespy/presence_connection_manager/requests.py @@ -0,0 +1,191 @@ +from typing import Any, Optional, Union + +from pydantic import ValidationError + +from frontends.gamespy.protocols.presence_connection_manager.aggregates.enums import ( + GPStatusCode, + LoginType, + SdkRevisionType, +) + +from backends.library.abstractions.contracts import RequestBase + + +class ErrorOnParse(RequestBase): + raw_request: str + + +# region buddy + + +class AddBlockRequest(RequestBase): + taget_id: int + profile_id: int + session_key: str + + +class BuddyListRequest(RequestBase): + profile_id: int + namespace_id: int + raw_request: str | None = None + operation_id: int + + +class BlockListRequest(RequestBase): + profile_id: int + namespace_id: int + operation_id: int + + +class AddBuddyRequest(RequestBase): + profile_id: int + target_id: int + namespace_id: int + reason: str + + +class DelBuddyRequest(RequestBase): + profile_id: int + target_id: int + namespace_id: int + + +class InviteToRequest(RequestBase): + product_id: int + profile_id: int + session_key: str + """the invite target profile id""" + + +class StatusInfoRequest(RequestBase): + is_get: bool + profile_id: int + namespace_id: int + status_state: str + buddy_ip: str + host_ip: str + host_private_ip: str + query_report_port: int + host_port: int + session_flags: str + rich_status: str + game_type: str + game_variant: str + game_map_name: str + quiet_mode_flags: str + + +class StatusRequest(RequestBase): + session_key: str + status_string: str + location_string: str + current_status: GPStatusCode + + +# region general + + +class KeepAliveRequest(RequestBase): + client_ip: str + client_port: int + pass + + +class NewUserRequest(RequestBase): + product_id: int + game_port: int + cd_key: str + has_game_name: bool + has_product_id: bool + has_cdkey: bool + has_partner_id: bool + has_game_port: bool + nick: str + email: str + password: str + partner_id: int + game_name: str + uniquenick: str + + +class LoginRequest(RequestBase): + user_challenge: str + response: str + user_data: str + unique_nick: str | None = None + namespace_id: int | None = None + auth_token: str | None = None + nick: str | None = None + email: str | None = None + product_id: int + type: LoginType + sdk_revision_type: list[SdkRevisionType] + game_port: int + partner_id: int + game_name: str | None = None + quiet_mode_flags: int + firewall: bool + operation_id: int + + def model_post_init(self, __context: Any) -> None: + super().model_post_init(__context) + if self.type == LoginType.AUTH_TOKEN: + if self.auth_token is None: + raise ValidationError("authtoken is missing.") + elif self.type == LoginType.UNIQUENICK_NAMESPACE_ID: + if self.unique_nick is None: + raise ValidationError("unique nick is missing.") + if self.namespace_id is None: + raise ValidationError("namespace is missing.") + elif self.type == LoginType.NICK_EMAIL: + if self.nick is None: + raise ValidationError("nick name is missing.") + if self.email is None: + raise ValidationError("email is missing.") + else: + raise ValidationError(f"request type {self.type} not found.") + + +class LogoutRequest(RequestBase): + pass + + +# region profile + + +class GetProfileRequest(RequestBase): + profile_id: int + session_key: str + operation_id: int + + +class NewProfileRequest(RequestBase): + is_replace_nick_name: bool + session_key: str + new_nick: str + old_nick: str + + +class RegisterCDKeyRequest(RequestBase): + session_key: str + cdkey_enc: str + + +class RegisterNickRequest(RequestBase): + unique_nick: str + session_key: str + partner_id: int + + +class UpdateProfileRequest(RequestBase): + session_key: str + extra_infos: dict + + +class UpdateUserInfoRequest(RequestBase): + session_key: str + extra_infos: dict + + +if __name__ == "__main__": + pass diff --git a/src/backends/protocols/gamespy/presence_connection_manager/responses.py b/src/backends/protocols/gamespy/presence_connection_manager/responses.py new file mode 100644 index 000000000..d47ed6e11 --- /dev/null +++ b/src/backends/protocols/gamespy/presence_connection_manager/responses.py @@ -0,0 +1,18 @@ +from backends.library.abstractions.contracts import DataResponse +from frontends.gamespy.protocols.presence_connection_manager.contracts.results import BlockListResult, BuddyListResult, GetProfileResult, LoginResult + + +class LoginResponse(DataResponse): + result: LoginResult + + +class BuddyListResponse(DataResponse): + result: BuddyListResult + + +class BlockListResponse(DataResponse): + result: BlockListResult + + +class GetProfileResponse(DataResponse): + result: GetProfileResult diff --git a/src/backends/protocols/gamespy/presence_search_player/data.py b/src/backends/protocols/gamespy/presence_search_player/data.py new file mode 100644 index 000000000..d47f46c94 --- /dev/null +++ b/src/backends/protocols/gamespy/presence_search_player/data.py @@ -0,0 +1,421 @@ +from typing import TYPE_CHECKING, cast +from sqlalchemy import Column +from backends.library.database.pg_orm import ( + Friends, + Profiles, + SubProfiles, + Users, +) +from sqlalchemy.orm import Session + + +def db_commit(session: Session) -> None: + session.commit() + + +def verify_email(email: str, session: Session): + assert isinstance(email, str) + + if session.query(Users).where(Users.email == email).count() == 1: + return True + else: + return False + + +def verify_email_and_password(email: str, password: str, session: Session): + assert isinstance(email, str) + assert isinstance(password, str) + + result = ( + session.query(Users) + .where(Users.email == email, Users.password == password) + .count() + ) + if result == 1: + return True + return False + + +def get_profile_id( + email: str, password: str, nick_name: str, partner_id: int, session: Session +) -> int | None: + result = ( + session.query(Profiles.profileid) + .join(Users, Profiles.userid == Users.userid) + .join(SubProfiles, Profiles.profileid == SubProfiles.profileid) + .where( + Users.email == email, + Users.password == password, + Profiles.nick == nick_name, + SubProfiles.partnerid == partner_id, + ) + .first() + ) + if result is not None: + result = result[0] + assert isinstance(result, int) + return result + + +def add_user(user: Users, session: Session): + session.add(user) + session.commit() + + +def add_profile(profile: Profiles, session: Session): + session.add(profile) + session.commit() + + +def add_sub_profile(subprofile: SubProfiles, session: Session): + session.add(subprofile) + session.commit() + + +def update_user(user: Users, session: Session): + session.merge(user) + session.commit() + + +def update_profile(profile: Profiles, session: Session): + session.merge(profile) + session.commit() + + +def update_subprofile(subprofile: SubProfiles, session: Session): + session.merge(subprofile) + session.commit() + + +def get_user(email: str, session: Session) -> Users | None: + assert isinstance(email, str) + + result = session.query(Users).where(Users.email == email).first() + return result + + +def get_profile(user_id: int, nick_name: str, session: Session) -> Profiles | None: + assert isinstance(user_id, int) + assert isinstance(nick_name, str) + + result = ( + session.query(Profiles) + .where(Profiles.userid == user_id, Profiles.nick == nick_name) + .first() + ) + return result + + +def get_sub_profile( + profile_id: int, namespace_id: int, product_id: int, session: Session +) -> SubProfiles | None: + assert isinstance(profile_id, int) + assert isinstance(namespace_id, int) + assert isinstance(product_id, int) + + result = ( + session.query(SubProfiles) + .where( + SubProfiles.profileid == profile_id, + SubProfiles.namespaceid == namespace_id, + SubProfiles.namespaceid == product_id, + ) + .first() + ) + return result + + +def get_nick_and_unique_nick_list( + email: str, password: str, namespace_id: int, session: Session +) -> list[tuple[str, str]]: + """ + return [(nick, uniquenick)] + """ + + result = ( + session.query(Profiles.nick, SubProfiles.uniquenick) + .join(Users, Profiles.userid == Users.userid) + .join(SubProfiles, Profiles.profileid == SubProfiles.profileid) + .where( + Users.email == email, + Users.password == password, + SubProfiles.namespaceid == namespace_id, + ) + .all() + ) + assert isinstance(result, list) + data = [] + for r in result: + # convert to tuple + data.append(tuple(r)) + return data + + +def get_friend_info_list( + profile_id: int, namespace_id: int, game_name: str, session: Session +) -> list: + """ + return [(profileid, nick, uniquenick, lastname, firstname, userid, email)] + """ + + result = ( + session.query( + Profiles.profileid, + Profiles.nick, + SubProfiles.uniquenick, + Users.userid, + Users.email, + ) + .join(Users, Profiles.userid == Users.userid) + .join(SubProfiles, Profiles.profileid == SubProfiles.profileid) + .join(Friends, Profiles.profileid == Friends.friendid) + # todo check whether friends table join is correct + .where( + Friends.profileid == profile_id, + SubProfiles.namespaceid == namespace_id, + SubProfiles.gamename == game_name, + ) + .all() + ) + return result + + +def get_matched_profile_info_list( + profile_ids: list[int], namespace_id: int, session: Session +) -> list[tuple[int, str]]: + """ + return [(profileid,uniquenick)] + + """ + if TYPE_CHECKING: + assert isinstance(SubProfiles.profileid, Column) + assert isinstance(SubProfiles.uniquenick, Column) + assert isinstance(SubProfiles.namespaceid, Column) + + result = ( + session.query(SubProfiles.profileid, SubProfiles.uniquenick) + .where( + SubProfiles.profileid.in_(profile_ids), + SubProfiles.namespaceid == namespace_id, + ) + .all() + ) + data = [] + for r in result: + data.append(tuple(r)) + return data + + +def get_matched_info_by_nick(nick_name: str, session: Session) -> list[dict]: + result = ( + session.query( + Users.email, + Profiles.profileid, + Profiles.nick, + SubProfiles.uniquenick, + SubProfiles.namespaceid, + Profiles.extra_info, + ) + .join(Users, Profiles.userid == Users.userid) + .join(SubProfiles, Profiles.profileid == SubProfiles.profileid) + .where(Profiles.nick == nick_name) + .all() + ) + temp: list[dict] = [] + for email, profile_id, nick, uniquenick, namespace_id, extra_info in result: + if TYPE_CHECKING: + extra_info = cast(dict, extra_info) + firstname = extra_info.get("firstname", "") + lastname = extra_info.get("lastname", "") + t = { + "profile_id": profile_id, + "nick": nick, + "uniquenick": uniquenick, + "email": email, + "namespace_id": namespace_id, + "firstname": firstname, + "lastname": lastname, + } + temp.append(t) + + return temp + + +def get_matched_info_by_email(email: str, session: Session) -> list[dict]: + result = ( + session.query( + Users.email, + Profiles.profileid, + Profiles.nick, + SubProfiles.uniquenick, + SubProfiles.namespaceid, + Profiles.extra_info, + ) + .join(Users, Profiles.userid == Users.userid) + .join(SubProfiles, Profiles.profileid == SubProfiles.profileid) + .where(Users.email == email) + .all() + ) + temp: list[dict] = [] + for email, profile_id, nick, uniquenick, namespace_id, extra_info in result: + if TYPE_CHECKING: + extra_info = cast(dict, extra_info) + firstname = extra_info.get("firstname", "") + lastname = extra_info.get("lastname", "") + t = { + "profile_id": profile_id, + "nick": nick, + "uniquenick": uniquenick, + "email": email, + "namespace_id": namespace_id, + "firstname": firstname, + "lastname": lastname, + } + temp.append(t) + return temp + + +def get_matched_info_by_nick_and_email( + nick_name: str, email: str, session: Session +) -> list[dict]: + result = ( + session.query( + Users.email, + Profiles.profileid, + Profiles.nick, + SubProfiles.uniquenick, + SubProfiles.namespaceid, + Profiles.extra_info, + ) + .join(Users, Profiles.userid == Users.userid) + .join(SubProfiles, Profiles.profileid == SubProfiles.profileid) + .where(Users.email == email, Profiles.nick == nick_name) + .all() + ) + data: list[dict] = [] + for email, profile_id, nick, uniquenick, namespace_id, extra_info in result: + if TYPE_CHECKING: + extra_info = cast(dict, extra_info) + firstname = extra_info.get("firstname", "") + lastname = extra_info.get("lastname", "") + t = { + "profile_id": profile_id, + "nick": nick, + "uniquenick": uniquenick, + "email": email, + "namespace_id": namespace_id, + "firstname": firstname, + "lastname": lastname, + } + data.append(t) + return data + + +def get_matched_info_by_uniquenick_and_namespaceid( + unique_nick: str, namespace_id: int, session: Session +) -> list[dict]: + result = ( + session.query( + Users.email, + Profiles.profileid, + Profiles.nick, + SubProfiles.uniquenick, + SubProfiles.namespaceid, + Profiles.extra_info, + ) + .join(Users, Profiles.userid == Users.userid) + .join(SubProfiles, Profiles.profileid == SubProfiles.profileid) + .where( + SubProfiles.uniquenick == unique_nick, + SubProfiles.namespaceid == namespace_id, + ) + .all() + ) + data: list[dict] = [] + for email, profile_id, nick, uniquenick, namespace_id, extra_info in result: + if TYPE_CHECKING: + extra_info = cast(dict, extra_info) + firstname = extra_info.get("firstname", "") + lastname = extra_info.get("lastname", "") + t = { + "profile_id": profile_id, + "nick": nick, + "uniquenick": uniquenick, + "email": email, + "namespace_id": namespace_id, + "firstname": firstname, + "lastname": lastname, + } + data.append(t) + + return data + + +def get_matched_info_by_uniquenick_and_namespaceids( + unique_nick: str, namespace_ids: list[int], session: Session +) -> list[dict]: + result = ( + session.query( + Profiles.profileid, + Profiles.nick, + SubProfiles.uniquenick, + SubProfiles.namespaceid, + ) + .join(Users, Profiles.userid == Users.userid) + .join(SubProfiles, Profiles.profileid == SubProfiles.profileid) + .where( + SubProfiles.uniquenick == unique_nick, + SubProfiles.namespaceid.in_(namespace_ids), + ) + .all() + ) + data: list[dict] = [] + for email, profile_id, nick, uniquenick, namespace_id, extra_info in result: + if TYPE_CHECKING: + extra_info = cast(dict, extra_info) + firstname = extra_info.get("firstname", "") + lastname = extra_info.get("lastname", "") + t = { + "profile_id": profile_id, + "nick": nick, + "uniquenick": uniquenick, + "email": email, + "namespace_id": namespace_id, + "firstname": firstname, + "lastname": lastname, + } + data.append(t) + + return data + + +def is_uniquenick_exist( + unique_nick: str, namespace_id: int, game_name: str, session: Session +) -> bool: + result = ( + session.query(Profiles) + .join(SubProfiles, Profiles.profileid == SubProfiles.profileid) + .where( + SubProfiles.uniquenick == unique_nick, + SubProfiles.gamename == game_name, + SubProfiles.namespaceid == namespace_id, + ) + .count() + ) + + if result == 0: + return False + else: + return True + + +def is_email_exist(email: str, session: Session) -> bool: + if TYPE_CHECKING: + Users.userid = cast(Column, Users.userid) + Users.email = cast(Column, Users.email) + + result = session.query(Users.userid).where(Users.email == email).count() + # According to game partnerid is not nessesary + if result == 0: + return False + return True diff --git a/src/backends/protocols/gamespy/presence_search_player/handlers.py b/src/backends/protocols/gamespy/presence_search_player/handlers.py new file mode 100644 index 000000000..ed0a5a3c2 --- /dev/null +++ b/src/backends/protocols/gamespy/presence_search_player/handlers.py @@ -0,0 +1,303 @@ +from backends.library.abstractions.handler_base import HandlerBase +from backends.library.database.pg_orm import Users, Profiles, SubProfiles +import backends.protocols.gamespy.presence_search_player.data as data +from backends.protocols.gamespy.presence_search_player.requests import ( + CheckRequest, + NewUserRequest, + NicksRequest, + OthersListRequest, + OthersRequest, + SearchRequest, + SearchUniqueRequest, + UniqueSearchRequest, + ValidRequest, +) +from backends.protocols.gamespy.presence_search_player.responses import CheckResponse, NewUserResponse, NicksResponse, OthersListResponse, OthersResponse, SearchResponse, SearchUniqueResponse, UniqueSearchResponse, ValidResponse +from frontends.gamespy.protocols.presence_search_player.aggregates.enums import ( + SearchType, +) +from frontends.gamespy.protocols.presence_search_player.aggregates.exceptions import ( + CheckException, + GPException, +) +from frontends.gamespy.protocols.presence_search_player.contracts.results import ( + CheckResult, + NewUserResult, + NickResultData, + NicksResult, + OthersListData, + OthersListResult, + OthersResult, + OthersResultData, + SearchResult, + SearchResultData, + SearchUniqueResult, + UniqueSearchResult, + ValidResult, +) + + +class CheckHandler(HandlerBase): + """ + todo: whether need check the partner id, which means whether we need to check subprofiles + """ + + _request: CheckRequest + _result: CheckResult + response: CheckResponse + + def _data_operate(self) -> None: + if not data.verify_email(self._request.email, self._session): + raise CheckException("The email is not existed") + if not data.verify_email_and_password( + self._request.email, self._request.password, self._session + ): + raise CheckException("The password is incorrect") + self._profile_id = data.get_profile_id( + self._request.email, + self._request.password, + self._request.nick, + self._request.partner_id, + self._session, + ) + if self._profile_id is None: + raise CheckException( + f"No pid found with email{self._request.email}") + + def _result_construct(self) -> None: + assert self._profile_id is not None + self._result = CheckResult(profile_id=self._profile_id) + + +class NewUserHandler(HandlerBase): + _request: NewUserRequest + _result: NewUserResult + response: NewUserResponse + + def _data_operate(self) -> None: + # check if user exist + self.user = data.get_user(self._request.email, self._session) + if self.user is None: + self._create_user() + + assert self.user + assert isinstance(self.user.userid, int) + + self.profile = data.get_profile( + self.user.userid, self._request.nick, self._session + ) + if self.profile is None: + self._create_profile() + assert self.profile is not None + assert isinstance(self.profile.profileid, int) + self.subprofile = data.get_sub_profile( + profile_id=self.profile.profileid, + namespace_id=self._request.namespace_id, + product_id=self._request.product_id, + session=self._session, + ) + if self.subprofile is None: + self._create_subprofile() + + def _result_construct(self) -> None: + assert self.user is not None + assert isinstance(self.user.userid, int) + assert self.profile is not None + assert isinstance(self.profile.profileid, int) + self._result = NewUserResult( + user_id=self.user.userid, profile_id=self.profile.profileid + ) + + def _create_user(self) -> None: + user_dict = {} + for key, value in self._request.__dict__.items(): + if key in Users.__dict__: + user_dict[key] = value + self.user = Users(**user_dict) + self._session.add(self.user) + self._session.commit() + + def _create_profile(self) -> None: + profile_dict = {} + for key, value in self._request.__dict__.items(): + if key in Profiles.__dict__: + profile_dict[key] = value + + assert self.user is not None + assert isinstance(self.user.userid, int) + profile_dict["userid"] = self.user.userid + self.profile = Profiles(**profile_dict) + self._session.add(self.profile) + self._session.commit() + + def _create_subprofile(self) -> None: + subprofile_dict = {} + for key, value in self._request.__dict__.items(): + if key in SubProfiles.__dict__: + subprofile_dict[key] = value + assert self.profile is not None + subprofile_dict["profileid"] = self.profile.profileid + self.subprofile = SubProfiles(**subprofile_dict) + self._session.add(self.subprofile) + self._session.commit() + + +class NicksHandler(HandlerBase): + _request: NicksRequest + _result: NicksResult + response: NicksResponse + + def _data_operate(self) -> None: + self.temp_list = data.get_nick_and_unique_nick_list( + self._request.email, + self._request.password, + self._request.namespace_id, + self._session, + ) + self.result_data = [] + for nick, unique in self.temp_list: + self.result_data.append( + NickResultData(nick=nick, uniquenick=unique)) + + def _result_construct(self) -> None: + self._result = NicksResult(data=self.result_data) + + +class OthersHandler(HandlerBase): + _request: OthersRequest + _result: OthersResult + response: OthersResponse + + def _data_operate(self) -> None: + self._data: list = data.get_friend_info_list( + self._request.profile_id, + self._request.namespace_id, + self._request.game_name, + self._session, + ) + + def _result_construct(self) -> None: + temp_list = [] + for item in self._data: + temp_list.append( + OthersResultData( + profile_id=item[0], + nick=item[1], + uniquenick=item[2], + lastname=item[3], + firstname=item[4], + user_id=item[5], + email=item[6], + ) + ) + self._result = OthersResult(data=temp_list) + + +class OthersListHandler(HandlerBase): + _request: OthersListRequest + result: OthersListResult + response: OthersListResponse + + def _data_operate(self) -> None: + self._data: list = data.get_matched_profile_info_list( + self._request.profile_ids, self._request.namespace_id, self._session + ) + + def _result_construct(self) -> None: + temp = [] + for profile_id, uniquenick in self._data: + temp.append(OthersListData( + profile_id=profile_id, unique_nick=uniquenick)) + self._result = OthersListResult(data=temp) + + +# class PlayerMatchHandler(HandlerBase): +# _request: playermatchrequest + + +class SearchHandler(HandlerBase): + _request: SearchRequest + _result: SearchResult + response: SearchResponse + + def _data_operate(self) -> None: + if self._request.request_type == SearchType.NICK_SEARCH: + assert self._request.nick + self._data = data.get_matched_info_by_nick( + self._request.nick, self._session + ) + elif self._request.request_type == SearchType.NICK_EMAIL_SEARCH: + assert self._request.email + assert self._request.nick + self._data = data.get_matched_info_by_nick_and_email( + self._request.nick, self._request.email, self._session + ) + elif self._request.request_type == SearchType.UNIQUENICK_NAMESPACEID_SEARCH: + assert self._request.uniquenick + self._data = data.get_matched_info_by_uniquenick_and_namespaceid( + self._request.uniquenick, self._request.namespace_id, self._session + ) + elif self._request.request_type == SearchType.EMAIL_SEARCH: + assert self._request.email + self._data = data.get_matched_info_by_email( + self._request.email, self._session + ) + else: + raise GPException("search type invalid") + + def _result_construct(self) -> None: + data = [] + for d in self._data: + dd = SearchResultData(**d) + data.append(dd) + self._result = SearchResult(data=data) + + +class SearchUniqueHandler(HandlerBase): + _request: SearchUniqueRequest + _result: SearchUniqueResult + response: SearchUniqueResponse + + def _data_operate(self) -> None: + self._data = data.get_matched_info_by_uniquenick_and_namespaceids( + self._request.uniquenick, self._request.namespace_ids, self._session + ) + + def _result_construct(self) -> None: + data = [] + for d in self._data: + dd = SearchResultData(**d) + data.append(dd) + self._result = SearchUniqueResult(data=data) + + +class UniqueSearchHandler(HandlerBase): + _request: UniqueSearchRequest + _result: UniqueSearchResult + response: UniqueSearchResponse + + def _data_operate(self) -> None: + self._is_exist = data.is_uniquenick_exist( + self._request.preferred_nick, + self._request.namespace_id, + self._request.game_name, + self._session, + ) + + def _result_construct(self) -> None: + self._result = UniqueSearchResult( + is_uniquenick_exist=self._is_exist, + preferred_nick=self._request.preferred_nick) + + +class ValidHandler(HandlerBase): + _request: ValidRequest + _result: ValidResult + response: ValidResponse + + def _data_operate(self) -> None: + self._is_exist = data.is_email_exist( + self._request.email, self._session) + + def _result_construct(self) -> None: + self._result = ValidResult(is_account_valid=self._is_exist) diff --git a/src/backends/protocols/gamespy/presence_search_player/requests.py b/src/backends/protocols/gamespy/presence_search_player/requests.py new file mode 100644 index 000000000..dc9c3bf92 --- /dev/null +++ b/src/backends/protocols/gamespy/presence_search_player/requests.py @@ -0,0 +1,80 @@ + +from backends.library.abstractions.contracts import RequestBase as RB +from frontends.gamespy.protocols.presence_search_player.aggregates.enums import SearchType + + +class RequestBase(RB): + operation_id: int + +# general + +# we just need to recreate the requests and just put the property inside it. The result we can use the results inside servers. + + +class CheckRequest(RequestBase): + nick: str + password: str + email: str + partner_id: int + + +class NewUserRequest(RequestBase): + nick: str + email: str + password: str + uniquenick: str + namespace_id: int + product_id: int + game_port: int | None = None + cd_key: str | None = None + partner_id: int | None = None + game_name: str | None = None + + +class NicksRequest(RequestBase): + password: str + email: str + namespace_id: int + is_require_uniquenicks: bool + + +class OthersListRequest(RequestBase): + profile_ids: list[int] + namespace_id: int + + +class OthersRequest(RequestBase): + profile_id: int + game_name: str + namespace_id: int + + +class SearchRequest(RequestBase): + skip_num: int + request_type: SearchType + game_name: str + profile_id: int | None = None + partner_id: int + email: str | None = None + nick: str | None = None + uniquenick: str | None = None + session_key: str | None = None + firstname: str | None = None + lastname: str | None = None + icquin: str | None = None + namespace_id: int + + +class SearchUniqueRequest(RequestBase): + uniquenick: str + namespace_ids: list[int] + + +class UniqueSearchRequest(RequestBase): + preferred_nick: str + game_name: str + namespace_id: int + + +class ValidRequest(RequestBase): + email: str diff --git a/src/backends/protocols/gamespy/presence_search_player/responses.py b/src/backends/protocols/gamespy/presence_search_player/responses.py new file mode 100644 index 000000000..25b58e8f5 --- /dev/null +++ b/src/backends/protocols/gamespy/presence_search_player/responses.py @@ -0,0 +1,37 @@ +from backends.library.abstractions.contracts import DataResponse +from frontends.gamespy.protocols.presence_search_player.contracts.results import CheckResult, NewUserResult, NicksResult, OthersListResult, OthersResult, SearchResult, SearchUniqueResult, UniqueSearchResult, ValidResult + + +class CheckResponse(DataResponse): + result: CheckResult + + +class NewUserResponse(DataResponse): + result: NewUserResult + + +class NicksResponse(DataResponse): + result: NicksResult + + +class OthersResponse(DataResponse): + result: OthersResult + + +class OthersListResponse(DataResponse): + result: OthersListResult + + +class SearchResponse(DataResponse): + result: SearchResult + + +class SearchUniqueResponse(DataResponse): + result: SearchUniqueResult + + +class ValidResponse(DataResponse): + result: ValidResult + +class UniqueSearchResponse(DataResponse): + result:UniqueSearchResult \ No newline at end of file diff --git a/src/backends/protocols/gamespy/query_report/broker.py b/src/backends/protocols/gamespy/query_report/broker.py new file mode 100644 index 000000000..49dfd60ee --- /dev/null +++ b/src/backends/protocols/gamespy/query_report/broker.py @@ -0,0 +1,35 @@ +from contextlib import asynccontextmanager +import logging + +from fastapi import APIRouter +from backends.protocols.gamespy.query_report.handlers import ClientMessageHandler +from backends.protocols.gamespy.query_report.requests import ClientMessageRequest +from backends.library.networks.redis_brocker import RedisBrocker +from frontends.gamespy.library.configs import CONFIG + +from backends.library.networks.ws_manager import WebsocketManager as WsManager + +logger = logging.getLogger("backend") + + +class WebsocketManager(WsManager): + pass + + +def handle_client_message(message: str): + try: + request = ClientMessageRequest.model_validate(message) + handler = ClientMessageHandler(request) + handler.handle() + except Exception as e: + logger.error(str(e)) + + +MANAGER = WebsocketManager() +BROCKER = RedisBrocker("master", CONFIG.redis.url, handle_client_message) + + +@asynccontextmanager +async def launch_brocker(_: APIRouter): + BROCKER.subscribe() + yield diff --git a/src/backends/protocols/gamespy/query_report/data.py b/src/backends/protocols/gamespy/query_report/data.py new file mode 100644 index 000000000..969d563a2 --- /dev/null +++ b/src/backends/protocols/gamespy/query_report/data.py @@ -0,0 +1,263 @@ +from typing import TYPE_CHECKING, cast +from uuid import UUID +from backends.library.database.pg_orm import ( + ENGINE, + ChatChannelCaches, + ChatChannelUserCaches, + GroupList, + Games, + GameServerCaches, +) +from frontends.gamespy.protocols.chat.aggregates.peer_room import PeerRoom +from frontends.gamespy.protocols.query_report.aggregates.enums import GameServerStatus +from frontends.gamespy.protocols.query_report.aggregates.exceptions import QRException +from frontends.gamespy.protocols.query_report.aggregates.game_server_info import ( + GameServerInfo, +) +from frontends.gamespy.protocols.query_report.aggregates.peer_room_info import ( + PeerRoomInfo, +) +from sqlalchemy.orm import Session + +from datetime import datetime, timedelta + +from frontends.gamespy.protocols.server_browser.v2.aggregations.exceptions import SBException + + +def __expire_time(): + return datetime.now() - timedelta(5) + + +def get_peer_staging_channels( + game_name: str, group_id: int, session: Session +) -> list[GameServerInfo]: + """ + todo check where use this function + """ + assert isinstance(game_name, str) + assert isinstance(group_id, int) + staging_name = f"{PeerRoom.StagingRoomPrefix}!{game_name}!*" + result = ( + session.query(ChatChannelCaches) + .where(ChatChannelCaches.channel_name == staging_name) + .all() + ) + data = [] + for s in result: + t = {k: v for k, v in s.__dict__.items() if k != "_sa_instance_state"} + data.append(GameServerInfo(**t)) + return data + + +def get_peer_group_channel( + game_name: str, session: Session +) -> list[PeerRoomInfo]: + # Query the database for channels matching the constructed group names + group_data = ( + session.query(GroupList) + .select_from(Games) + .join(GroupList, (Games.gameid == GroupList.gameid)) + .where(Games.gamename == game_name) + .all() + ) + group_info: list[PeerRoomInfo] = [] + for gd in group_data: + # get the group room info from GroupList + + # Construct the group names based on the provided group_ids + group_room_channel_name = f"{PeerRoom.GroupRoomPrefix}!{gd.groupid}" + channel_name_prefix_regex = f"{group_room_channel_name}!%" + # Query the database for channels matching the constructed group names + result = ( + session.query(ChatChannelCaches) + .where(ChatChannelCaches.channel_name == group_room_channel_name + ).first()) + assert isinstance(gd.groupid, int) + assert isinstance(gd.roomname, str) + + if result is None: + info = PeerRoomInfo(groupid=gd.groupid, + game_name=game_name, + hostname=gd.roomname) + else: + assert isinstance(result.channel_name, str) + + assert isinstance(result.max_num_user, int) + # todo get the peer room extra info + waiting_player_count = session.query(ChatChannelUserCaches).where( + ChatChannelUserCaches.channel_name == result.channel_name).count() + playing_player_count = session.query(ChatChannelUserCaches).where( + ChatChannelUserCaches.channel_name.like(channel_name_prefix_regex)).count() + password = result.password if result.password is not None else "" + assert isinstance(password, str) + info = PeerRoomInfo(groupid=gd.groupid, + game_name=game_name, + hostname=result.channel_name, + password=password, + maxplayers=result.max_num_user, + numplayers=waiting_player_count+playing_player_count, + numwaiting=waiting_player_count, + numplaying=playing_player_count + ) + + group_info.append(info) + return group_info + + +def get_game_server_cache_by_ip_port(ip: str, port: int, session: Session) -> GameServerCaches | None: + result = ( + session.query(GameServerCaches) + .where(GameServerCaches.host_ip_address == ip, + GameServerCaches.query_report_port == port, + GameServerCaches.update_time >= __expire_time()) + .first() + ) + return result + + +def get_game_server_cache_with_instant_key( + instant_key: str, session: Session +) -> GameServerCaches | None: + assert isinstance(instant_key, str) + result = ( + session.query(GameServerCaches) + .where(GameServerCaches.instant_key == instant_key, + GameServerCaches.update_time >= __expire_time()) + .first() + ) + return result + + +def get_server_info_with_game_name( + game_name: str, session: Session +) -> GameServerCaches | None: + assert isinstance(game_name, str) + result = ( + session.query(GameServerCaches) + .where(GameServerCaches.game_name == game_name) + .first() + ) + return result + + +def get_secret_key(game_name: str, session: Session) -> str: + result = session.query(Games.secretkey).where( + Games.gamename == game_name).first() + if result is None: + raise SBException(f"{game_name} secret key not found in database") + return result[0] + + +def get_server_info_list_with_game_name( + game_name: str, session: Session +) -> list[GameServerInfo]: + result = ( + session.query(GameServerCaches) + .where(GameServerCaches.game_name == game_name, + GameServerCaches.update_time >= __expire_time(), + GameServerCaches.avaliable == True) + .all() + ) + data = [] + for info in result: + assert isinstance(info.server_id, UUID) + assert isinstance(info.host_ip_address, str) + assert isinstance(info.instant_key, str) + assert isinstance(info.game_name, str) + assert isinstance(info.query_report_port, int) + assert isinstance(info.update_time, datetime) + assert isinstance(info.status, GameServerStatus) + assert isinstance(info.data, dict) + + data.append(GameServerInfo( + server_id=info.server_id, + host_ip_address=info.host_ip_address, + instant_key=info.instant_key, + game_name=info.game_name, + query_report_port=info.query_report_port, + update_time=info.update_time, + status=info.status, + data=info.data + )) + return data + + +def check_game_server_cache_conflict(ip: str, port: int, instant_key: str, session: Session): + cache = get_server_info_with_ip_and_port( + ip, port, session) + if cache is not None: + if cache.instant_key != instant_key: + session.delete(cache) + session.commit() + + +def get_server_info_with_ip_and_port(ip: str, port: int, session: Session) -> GameServerInfo | None: + assert isinstance(ip, str) + assert isinstance(port, int) + result = ( + session.query(GameServerCaches) + .where( + GameServerCaches.host_ip_address == ip, + GameServerCaches.query_report_port == port, + GameServerCaches.update_time >= __expire_time()) + .first() + ) + if result is None: + return None + data = GameServerInfo(**result.__dict__) + return data + + +def remove_server_info(info: GameServerCaches, session: Session) -> None: + session.delete(info) + session.commit() + + +# todo finish the GameServerCaches creation + + +def create_game_server_cache(info: GameServerCaches, session: Session) -> None: + session.add(info) + session.commit() + + +def update_game_server_cache( + cache: GameServerCaches, + instant_key: str | None, + server_id: UUID, + host_ip_address: str, + game_name: str, + query_report_port: int, + server_status: GameServerStatus, + data: dict[str, str], + session: Session, +) -> None: + cache.instant_key = instant_key # type: ignore + cache.server_id = server_id # type: ignore + cache.host_ip_address = host_ip_address # type: ignore + cache.game_name = game_name # type: ignore + cache.query_report_port = query_report_port # type: ignore + cache.update_time = datetime.now() # type: ignore + cache.status = server_status # type: ignore + cache.data = data # type: ignore + session.commit() + + +def refresh_game_server_cache(client_ip: str, client_port: int, session: Session): + cache = get_game_server_cache_by_ip_port(client_ip, client_port, session) + if cache is None: + raise QRException( + "no game server cache found, please check the database") + cache.update_time = datetime.now() # type: ignore + session.commit() + + +def clean_expired_game_server_cache(session: Session): + session.query(GameServerCaches).where( + GameServerCaches.update_time < __expire_time() + ).delete() + session.commit() + + +if __name__ == "__main__": + pass diff --git a/src/backends/protocols/gamespy/query_report/handlers.py b/src/backends/protocols/gamespy/query_report/handlers.py new file mode 100644 index 000000000..01ac65cbf --- /dev/null +++ b/src/backends/protocols/gamespy/query_report/handlers.py @@ -0,0 +1,148 @@ +from backends.library.abstractions.contracts import OKResponse +from backends.library.abstractions.handler_base import HandlerBase +from backends.library.database.pg_orm import ENGINE, GameServerCaches +from backends.protocols.gamespy.query_report.requests import ( + AvaliableRequest, + ClientMessageRequest, + HeartBeatRequest, + KeepAliveRequest, + LegacyHeartbeatRequest, +) +from frontends.gamespy.protocols.query_report.aggregates.enums import GameServerStatus +from frontends.gamespy.protocols.query_report.aggregates.exceptions import QRException +import backends.protocols.gamespy.query_report.data as data +from sqlalchemy.orm import Session + + +class AvaliableHandler(HandlerBase): + _request: AvaliableRequest + response: OKResponse + + +class ChallengeHandler(HandlerBase): + _request: HeartBeatRequest + response: OKResponse + + def _data_operate(self) -> None: + with Session(ENGINE) as session: + cache = ( + session.query(GameServerCaches) + .where(GameServerCaches.instant_key == self._request.instant_key) + .first() + ) + if cache is None: + raise QRException( + "No server found, please make sure there is a server." + ) + cache.avaliable = True # type: ignore + session.commit() + + +class HeartbeatHandler(HandlerBase): + """ + v2 protocol qr heartbeat + this heartbeat have instantkey which is using for natneg + """ + _request: HeartBeatRequest + response: OKResponse + + def _data_operate(self) -> None: + # clean the expired server cache + data.clean_expired_game_server_cache(self._session) + + cache = data.get_game_server_cache_by_ip_port( + self._request.client_ip, self._request.client_port, self._session + ) + + if cache is None: + # todo check whether these data can be null at first heartbeat + if len(self._request.data) == 0: + raise QRException( + "data in first heartbeat can not be null") + # team data can be none in peertest sdk + cache = GameServerCaches( + instant_key=self._request.instant_key, + server_id=self._request.server_id, + host_ip_address=self._request.client_ip, + game_name=self._request.game_name, + query_report_port=self._request.client_port, + status=self._request.status, + data=self._request.data, + avaliable=True, + ) + data.create_game_server_cache(cache, self._session) + else: + data.update_game_server_cache( + cache=cache, + instant_key=self._request.instant_key, + server_id=self._request.server_id, + host_ip_address=self._request.client_ip, + game_name=self._request.game_name, + query_report_port=self._request.client_port, + server_status=self._request.status, + data=self._request.data, + session=self._session, + ) + + +class LegacyHeartbeatHandler(HandlerBase): + """ + same as HeartbeatHandler + The v1 protocol heartbeat do not have instantkey + """ + _request: LegacyHeartbeatRequest + response: OKResponse + + def _data_operate(self) -> None: + # clean the expired server cache + data.clean_expired_game_server_cache(self._session) + + cache = data.get_game_server_cache_by_ip_port( + self._request.client_ip, self._request.client_port, self._session + ) + + if cache is None: + cache = GameServerCaches( + instant_key=None, + server_id=self._request.server_id, + host_ip_address=self._request.client_ip, + game_name=self._request.game_name, + query_report_port=self._request.client_port, + status=GameServerStatus.NORMAL, + data=self._request.data, + avaliable=True, + ) + data.create_game_server_cache(cache, self._session) + else: + data.update_game_server_cache( + cache=cache, + instant_key=None, + server_id=self._request.server_id, + host_ip_address=self._request.client_ip, + game_name=self._request.game_name, + query_report_port=self._request.client_port, + server_status=GameServerStatus.NORMAL, + data=self._request.data, + session=self._session, + ) + + +class KeepAliveHandler(HandlerBase): + _request: KeepAliveRequest + response: OKResponse + + def _data_operate(self) -> None: + assert isinstance(self._request.instant_key, str) + data.refresh_game_server_cache( + self._request.client_ip, self._request.client_port, self._session) + + +class ClientMessageHandler(HandlerBase): + _request: ClientMessageRequest + response: OKResponse + + def _response_construct(self) -> None: + # todo use websocket to send the message to qr client, but how to determine which qr router should be received + # currently we just use broadcast message to all qr frontends + from backends.protocols.gamespy.query_report.broker import MANAGER + MANAGER.broadcast(self._request.model_dump_json()) diff --git a/src/backends/protocols/gamespy/query_report/requests.py b/src/backends/protocols/gamespy/query_report/requests.py new file mode 100644 index 000000000..4a60b5791 --- /dev/null +++ b/src/backends/protocols/gamespy/query_report/requests.py @@ -0,0 +1,59 @@ + +from pydantic import UUID4 +import backends.library.abstractions.contracts as lib + +from frontends.gamespy.protocols.query_report.aggregates.enums import GameServerStatus +from frontends.gamespy.protocols.query_report.v2.aggregates.enums import RequestType as V2RequestType + +from frontends.gamespy.protocols.query_report.v1.aggregates.enums import RequestType as V1RequestType + + +class RequestBase(lib.RequestBase): + instant_key: str + command_name: V2RequestType + raw_request: str + + +class AvaliableRequest(RequestBase): + pass + + +class ChallengeRequest(RequestBase): + pass + + +class ClientMessageAckRequest(RequestBase): + pass + + +class ClientMessageRequest(RequestBase): + server_browser_sender_id: UUID4 + target_query_report_id: UUID4 + natneg_message: str + target_ip_address: str + target_port: int + command_name: None = None + + +class HeartBeatRequest(RequestBase): + data: dict[str, str] + status: GameServerStatus + group_id: int | None + game_name: str + + + + +class LegacyHeartbeatRequest(lib.RequestBase): + command_name: V1RequestType + raw_request: str + query_id: str + game_name: str + data: dict[str, str] + +class EchoRequest(RequestBase): + pass + + +class KeepAliveRequest(RequestBase): + pass diff --git a/src/backends/protocols/gamespy/query_report/responses.py b/src/backends/protocols/gamespy/query_report/responses.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backends/protocols/gamespy/server_browser/data.py b/src/backends/protocols/gamespy/server_browser/data.py new file mode 100644 index 000000000..765d6fca8 --- /dev/null +++ b/src/backends/protocols/gamespy/server_browser/data.py @@ -0,0 +1,7 @@ + + +# region V1 + + +# region V2 + diff --git a/src/backends/protocols/gamespy/server_browser/handlers.py b/src/backends/protocols/gamespy/server_browser/handlers.py new file mode 100644 index 000000000..e4f3cd72e --- /dev/null +++ b/src/backends/protocols/gamespy/server_browser/handlers.py @@ -0,0 +1,187 @@ +from typing import TYPE_CHECKING, cast +from uuid import UUID +from backends.library.abstractions.contracts import RequestBase +from backends.library.abstractions.handler_base import HandlerBase +from backends.protocols.gamespy.query_report.broker import BROCKER, MANAGER +import backends.protocols.gamespy.query_report.data as data +from backends.protocols.gamespy.query_report.requests import ClientMessageRequest +from backends.protocols.gamespy.server_browser.requests import ( + AdHocRequestBase, + SendMessageRequest, + ServerInfoRequest, + ServerListRequest, +) +from backends.protocols.gamespy.server_browser.responses import P2PGroupRoomListResponse, SendMessageResponse, ServerFullInfoListResponse, ServerInfoResponse +from frontends.gamespy.protocols.query_report.aggregates.game_server_info import ( + GameServerInfo, +) +from frontends.gamespy.protocols.query_report.aggregates.peer_room_info import ( + PeerRoomInfo, +) +from frontends.gamespy.protocols.query_report.v2.aggregates.enums import RequestType +from frontends.gamespy.protocols.server_browser.v2.aggregations.enums import ( + GameServerFlags, +) +from frontends.gamespy.protocols.server_browser.v2.aggregations.exceptions import SBException +from frontends.gamespy.protocols.server_browser.v2.contracts.results import ( + P2PGroupRoomListResult, + SendMessageResult, + UpdateServerInfoResult, + ServerMainListResult, + ServerFullInfoListResult, +) +from backends.protocols.gamespy.server_browser.responses import ServerInfoResponse, ServerMainListResponse + + +# region Server list +class P2PGroupRoomListHandler(HandlerBase): + _request: ServerListRequest + _caches: list[PeerRoomInfo] + response: P2PGroupRoomListResponse + + def __init__(self, request: ServerListRequest) -> None: + assert isinstance(request, ServerListRequest) + super().__init__(request) + + def _data_operate(self): + self._secret_key = data.get_secret_key( + self._request.game_name, self._session) + self._caches = data.get_peer_group_channel( + self._request.game_name, self._session) + + def _result_construct(self) -> None: + assert isinstance(self._caches, list) and all( + isinstance(item, PeerRoomInfo) for item in self._caches + ) + + self._result = P2PGroupRoomListResult( + client_remote_ip=self._request.client_ip, + flag=GameServerFlags.HAS_KEYS_FLAG, + game_secret_key=self._secret_key, + peer_room_info=self._caches, + keys=self._request.keys + ) + + +class ServerMainListHandler(HandlerBase): + _request: ServerListRequest + _caches: list[GameServerInfo] + _secret_key: str + response: ServerMainListResponse + + def _data_operate(self): + self._secret_key = data.get_secret_key( + self._request.game_name, self._session) + self._caches = data.get_server_info_list_with_game_name( + self._request.game_name, self._session + ) + # we just need server data + for cache in self._caches: + filtered_data = {} + for key in self._request.keys: + if key in cache.data: + filtered_data[key] = cache.data[key] + cache.data = filtered_data + + def _result_construct(self): + assert isinstance(self._caches, list) and all( + isinstance(item, GameServerInfo) for item in self._caches + ) + + if TYPE_CHECKING: + self._caches = cast(list[GameServerInfo], self._caches) + self._result = ServerMainListResult( + client_remote_ip=self._request.client_ip, + game_secret_key=self._secret_key, + servers_info=self._caches, + keys=self._request.keys + ) + + +class ServerFullInfoListHandler(HandlerBase): + _request: ServerListRequest + _caches: list[GameServerInfo] + response: ServerFullInfoListResponse + + def _data_operate(self): + self._secret_key = data.get_secret_key( + self._request.game_name, self._session) + self._caches = data.get_server_info_list_with_game_name( + self._request.game_name, self._session + ) + + def _result_construct(self): + assert isinstance(self._caches, list) and all( + isinstance(item, GameServerInfo) for item in self._caches + ) + if TYPE_CHECKING: + self._caches = cast(list[GameServerInfo], self._caches) + all_keys = list(self._caches[0].data.keys()) + self._result = ServerFullInfoListResult( + client_remote_ip=self._request.client_ip, + game_secret_key=self._secret_key, + servers_info=self._caches, + keys=all_keys + ) + +# region Adhoc + + +class AdHocHandler(HandlerBase): + _request: AdHocRequestBase + + def _data_operate(self): + raise NotImplementedError() + + +class SendMessageHandler(HandlerBase): + """ + client -> server browser -> backend -> sb-SendMessageHandler -> qr-ClientMessageHandler -> websocket -> query report -> client + """ + _request: SendMessageRequest + response: SendMessageResponse + + def _data_operate(self): + # construct client message and invoke frontends qr server client message + cache = data.get_game_server_cache_by_ip_port( + self._request.game_server_public_ip, self._request.game_server_public_port, self._session) + if cache is None: + raise SBException( + f"could not find game server: {self._request.game_server_public_ip}:{self._request.game_server_public_port}") + assert isinstance(cache.instant_key, str) + assert isinstance(cache.server_id, UUID) + request = ClientMessageRequest( + server_id=self._request.server_id, + server_browser_sender_id=self._request.server_id, + target_query_report_id=cache.server_id, + raw_request=self._request.raw_request, + client_ip=self._request.client_ip, + client_port=self._request.client_port, + target_ip_address=self._request.game_server_public_ip, + target_port=self._request.game_server_public_port, + natneg_message=self._request.client_message, + instant_key=cache.instant_key, + ) + BROCKER.publish_message(request.model_dump_json()) + + +class ServerInfoHandler(HandlerBase): + _request: ServerInfoRequest + response: ServerInfoResponse + + def __init__(self, request: ServerInfoRequest) -> None: + assert isinstance(request, ServerInfoRequest) + super().__init__(request) + + def _data_operate(self) -> None: + self._data = data.get_server_info_with_ip_and_port( + self._request.game_server_public_ip, + self._request.game_server_public_port, + self._session, + ) + + def _result_construct(self) -> None: + # TODO: check whether we need respond when gameserver not exist + if self._data is None: + return + self._result = UpdateServerInfoResult(game_server_info=self._data) diff --git a/src/backends/protocols/gamespy/server_browser/requests.py b/src/backends/protocols/gamespy/server_browser/requests.py new file mode 100644 index 000000000..f2e7489cd --- /dev/null +++ b/src/backends/protocols/gamespy/server_browser/requests.py @@ -0,0 +1,43 @@ + +import backends.library.abstractions.contracts as lib +from frontends.gamespy.protocols.server_browser.v2.aggregations.enums import ( + ServerListUpdateOption, +) + + +class RequestBase(lib.RequestBase): + raw_request: str + + +class ServerListUpdateOptionRequestBase(RequestBase): + request_version: int + protocol_version: int + encoding_version: int + game_version: int + dev_game_name: str + game_name: str + client_challenge: str + update_option: ServerListUpdateOption + keys: list[str] + filter: str | None = None + max_servers: int | None = None + source_ip: str | None = None + query_options: int | None = None + + +class ServerListRequest(ServerListUpdateOptionRequestBase): + pass + + +class AdHocRequestBase(RequestBase): + game_server_public_ip: str + game_server_public_port: int + + +class SendMessageRequest(AdHocRequestBase): + prefix_message: str + client_message: str + + +class ServerInfoRequest(AdHocRequestBase): + pass diff --git a/src/backends/protocols/gamespy/server_browser/responses.py b/src/backends/protocols/gamespy/server_browser/responses.py new file mode 100644 index 000000000..da9e4d58c --- /dev/null +++ b/src/backends/protocols/gamespy/server_browser/responses.py @@ -0,0 +1,29 @@ +from backends.library.abstractions.contracts import DataResponse +from frontends.gamespy.protocols.server_browser.v2.contracts.results import ServerFullInfoListResult +from frontends.gamespy.protocols.server_browser.v2.contracts.results import ( + P2PGroupRoomListResult, + SendMessageResult, + UpdateServerInfoResult, + ServerMainListResult, + ServerFullInfoListResult, +) + + +class ServerFullInfoListResponse(DataResponse): + result: ServerFullInfoListResult + + +class P2PGroupRoomListResponse(DataResponse): + result: P2PGroupRoomListResult + + +class SendMessageResponse(DataResponse): + result: SendMessageResult + + +class ServerInfoResponse(DataResponse): + result: UpdateServerInfoResult + + +class ServerMainListResponse(DataResponse): + result: ServerMainListResult diff --git a/src/backends/protocols/gamespy/web_services/data.py b/src/backends/protocols/gamespy/web_services/data.py new file mode 100644 index 000000000..0bc299089 --- /dev/null +++ b/src/backends/protocols/gamespy/web_services/data.py @@ -0,0 +1,220 @@ +# region altas + +# region auth + +from typing import TYPE_CHECKING, cast +from backends.library.database.pg_orm import ( + Profiles, + SubProfiles, + Users, + SakeStorage, +) +from frontends.gamespy.protocols.web_services.modules.auth.exceptions.general import ( + AuthException, +) +from frontends.gamespy.protocols.web_services.modules.sake.exceptions.general import ( + SakeException, +) +from sqlalchemy.orm import Session + + +def is_user_exist( + uniquenick: str, + cdkey: str, + partner_id: int, + namespace_id: int, + email: str, + password: str, + session: Session, +) -> None: + result = ( + session.query(Profiles) + .join(Users) + .join(SubProfiles) + .where( + SubProfiles.uniquenick == uniquenick, + SubProfiles.cdkeyenc == cdkey, + SubProfiles.partnerid == partner_id, + SubProfiles.namespaceid == namespace_id, + Users.email == email, + Users.password == password, + ) + .first() + ) + if result is None: + raise AuthException( + "No account exists with the provided email address.") + + +def get_info_by_cdkey_email( + uniquenick: str, namespace_id: int, cdkey: str, email: str, session: Session +) -> tuple[int, int, str, str, str]: + """ + return [user_id,profile_id,profile_nick,unique_nick,cdkey_hash] + """ + assert isinstance(uniquenick, str) + assert isinstance(namespace_id, int) + assert isinstance(cdkey, str) + assert isinstance(email, str) + + result = ( + session.query(Users, Profiles, SubProfiles) + .join(Users) + .join( + Profiles, + ) + .join(SubProfiles) + .where( + SubProfiles.uniquenick == uniquenick, + SubProfiles.namespaceid == namespace_id, + SubProfiles.cdkeyenc == cdkey, + Users.email == email, + ) + .first() + ) + + if result is None: + raise AuthException( + "No account exists with the provided uniquenick and namespace id." + ) + user: Users = result[0] + profile: Profiles = result[1] + subprofile: SubProfiles = result[2] + assert isinstance(user.userid, int) + assert isinstance(profile.profileid, int) + assert isinstance(profile.nick, str) + assert isinstance(subprofile.uniquenick, str) + assert isinstance(subprofile.cdkeyenc, str) + + return ( + user.userid, + profile.profileid, + profile.nick, + subprofile.uniquenick, + subprofile.cdkeyenc, + ) + + +def get_info_by_authtoken( + auth_token: str, session: Session +) -> tuple[int, int, str, str, str]: + """ + return [user_id,profile_id,profile_nick,unique_nick,cdkey_hash] + """ + + result = ( + session.query(Users.userid, + Profiles.profileid, + Profiles.nick, + SubProfiles.uniquenick, + SubProfiles.cdkeyenc) + .join(Profiles, Profiles.userid == Users.userid) + .join(SubProfiles, SubProfiles.profileid == Profiles.profileid) + .where(SubProfiles.authtoken == auth_token) + .first() + ) + if result is None: + raise AuthException("No account exists with the provided authtoken.") + + userid, profileid, nick, uniquenick, cdkeyenc = result + assert isinstance(userid, int) + assert isinstance(profileid, int) + assert isinstance(nick, str) + assert isinstance(uniquenick, str) + assert isinstance(cdkeyenc, str) + return ( + userid, profileid, nick, uniquenick, cdkeyenc + ) + + +def get_info_by_uniquenick( + uniquenick: str, namespace_id: int, session: Session +) -> tuple[int, int, str, str, str]: + """ + return [user_id,profile_id,profile_nick,unique_nick,cdkey_hash] + """ + + result = ( + session.query(Users, Profiles, SubProfiles) + .join(Users, Users.userid == Profiles.userid) + .join(SubProfiles, SubProfiles.profileid == Profiles.profileid) + .where( + SubProfiles.uniquenick == uniquenick, + SubProfiles.namespaceid == namespace_id, + ) + .first() + ) + + if result is None: + raise AuthException( + "No account exists with the provided uniquenick and namespace id." + ) + user: Users = result[0] + profile: Profiles = result[1] + subprofile: SubProfiles = result[2] + assert isinstance(user.userid, int) + assert isinstance(profile.profileid, int) + assert isinstance(profile.nick, str) + assert isinstance(subprofile.uniquenick, str) + assert isinstance(subprofile.cdkeyenc, str) + + return ( + user.userid, + profile.profileid, + profile.nick, + subprofile.uniquenick, + subprofile.cdkeyenc, + ) + + +# region d2g + +# region ingamead + +# region patching and tracking + +# region racing + +# region sake + + +def get_user_data(table_id: int, session: Session) -> dict: + result = ( + session.query(SakeStorage.data).where( + SakeStorage.tableid == table_id).first() + ) + + if TYPE_CHECKING: + result = cast(dict, result) + return result + + +def update_user_data(table_id: int, data: dict, session: Session) -> None: + result = session.query(SakeStorage).where( + SakeStorage.tableid == table_id).first() + if result is None: + raise SakeException("user data not found") + assert isinstance(result.data, dict) + for key, value in result.data.items(): + if key in data: + if data[key] is None or data[key] == "": + raise SakeException(f"the value of {key} should not be None.") + if value == data[key]: + continue + result.data[key] = data[key] + + +def create_records(table_id: int, data: dict, session: Session) -> None: + assert isinstance(table_id, int) + assert isinstance(data, dict) + + result = session.query(SakeStorage).where( + SakeStorage.tableid == table_id).count() + + if result != 0: + raise SakeException("Records already existed") + + sake = SakeStorage(table_id=table_id, data=data) + + session.add(sake) + session.commit() diff --git a/src/backends/protocols/gamespy/web_services/handlers.py b/src/backends/protocols/gamespy/web_services/handlers.py new file mode 100644 index 000000000..b0980c1a6 --- /dev/null +++ b/src/backends/protocols/gamespy/web_services/handlers.py @@ -0,0 +1,200 @@ +# region altas + +# region auth +from backends.library.abstractions.contracts import RequestBase +from backends.library.abstractions.handler_base import HandlerBase +from backends.protocols.gamespy.presence_search_player.handlers import NewUserHandler +from backends.protocols.gamespy.presence_search_player.requests import NewUserRequest +import backends.protocols.gamespy.web_services.data as data +from backends.protocols.gamespy.web_services.requests import ( + CreateRecordRequest, + CreateUserAccountRequest, + GetMyRecordsRequest, + GetPurchaseHistoryRequest, + GetStoreAvailabilityRequest, + LoginPS3CertRequest, + LoginProfileRequest, + LoginRemoteAuthRequest, + LoginUniqueNickRequest, + SearchForRecordsRequest, +) +from backends.protocols.gamespy.web_services.responses import CreateRecordResponse, CreateUserAccountResponse, GetMyRecordsResponse, LoginProfileResponse, LoginRemoteAuthRepsonse, LoginUniqueNickResponse, SearchForRecordsResponse +from frontends.gamespy.protocols.web_services.modules.auth.contracts.results import ( + CreateUserAccountResult, + LoginProfileResult, + LoginRemoteAuthResult, + LoginUniqueNickResult, +) +from frontends.gamespy.protocols.web_services.modules.direct2game.contracts.results import ( + GetPurchaseHistoryResult, + GetStoreAvailabilityResult, +) + + +class LoginProfileHandler(HandlerBase): + _request: LoginProfileRequest + response: LoginProfileResponse + + def _data_operate(self) -> None: + self.data = data.get_info_by_cdkey_email( + uniquenick=self._request.uniquenick, + namespace_id=self._request.namespace_id, + cdkey=self._request.cdkey, + email=self._request.email, + session=self._session, + ) + + def _result_construct(self) -> None: + self._result = LoginProfileResult( + user_id=self.data[0], + profile_id=self.data[1], + profile_nick=self.data[2], + unique_nick=self.data[3], + cdkey_hash=self.data[4], + version=self._request.version, + namespace_id=self._request.namespace_id, + partner_code=self._request.partner_code + ) + + +class LoginPS3CertHandler(HandlerBase): + _request: LoginPS3CertRequest + + def _data_operate(self) -> None: + raise NotImplementedError() + + +class LoginRemoteAuthHandler(HandlerBase): + _request: LoginRemoteAuthRequest + response: LoginRemoteAuthRepsonse + + def _data_operate(self) -> None: + self.data = data.get_info_by_authtoken( + auth_token=self._request.auth_token, session=self._session + ) + + def _result_construct(self) -> None: + self._result = LoginRemoteAuthResult( + user_id=self.data[0], + profile_id=self.data[1], + profile_nick=self.data[2], + unique_nick=self.data[3], + cdkey_hash=self.data[4], + version=self._request.version, + namespace_id=self._request.namespace_id, + partner_code=self._request.partner_code + ) + + +class LoginUniqueNickHandler(HandlerBase): + _request: LoginUniqueNickRequest + response: LoginUniqueNickResponse + + def _data_operate(self) -> None: + self.data = data.get_info_by_uniquenick( + uniquenick=self._request.uniquenick, + namespace_id=self._request.namespace_id, + session=self._session, + ) + + def _result_construct(self) -> None: + self._result = LoginUniqueNickResult( + user_id=self.data[0], + profile_id=self.data[1], + profile_nick=self.data[2], + unique_nick=self.data[3], + cdkey_hash=self.data[4], + version=self._request.version, + namespace_id=self._request.namespace_id, + partner_code=self._request.partner_code + ) + + +class CreateUserAccountHandler(HandlerBase): + _request: CreateUserAccountRequest + response: CreateUserAccountResponse + + def _data_operate(self) -> None: + dump = self._request.model_dump() + dump["operation_id"] = 0 + dump["product_id"] = 0 + req = NewUserRequest.model_validate(dump) + h = NewUserHandler(req) + h.handle() + self.data = h._result + + def _result_construct(self) -> None: + self._result = CreateUserAccountResult( + user_id=self.data.user_id, + profile_id=self.data.profile_id, + profile_nick=self._request.nick, + unique_nick=self._request.uniquenick, + cdkey_hash="", + version=3, + namespace_id=self._request.namespace_id, + partner_code=self._request.partner_code + ) + + +# region d2g + + +class GetPurchaceHistoryHandler(HandlerBase): + _request: GetPurchaseHistoryRequest + + def _result_construct(self) -> None: + self._result = GetPurchaseHistoryResult() + + +class GetStoreAvailabilityHandler(HandlerBase): + _request: GetStoreAvailabilityRequest + + def _result_construct(self) -> None: + self._result = GetStoreAvailabilityResult() + + +# region ingamead + + +class GetTargettedAdHandler(HandlerBase): + def __init__(self, request: RequestBase) -> None: + super().__init__(request) + raise NotImplementedError() + + +class ReportAdUsageRequest(HandlerBase): + def __init__(self, request: RequestBase) -> None: + super().__init__(request) + raise NotImplementedError() + + +# region patching and tracking + +# region racing + +# region sake + + +class CreateRecordHandler(HandlerBase): + _request: CreateRecordRequest + response: CreateRecordResponse + + def _data_operate(self) -> None: + raise NotImplementedError() + + +class GetMyRecordsHandler(HandlerBase): + _request: GetMyRecordsRequest + response: GetMyRecordsResponse + + def _data_operate(self): + self.data = data.get_user_data(self._request.table_id, self._session) + raise NotImplementedError() + + +class SearchForRecordsHandler(HandlerBase): + _request: SearchForRecordsRequest + response: SearchForRecordsResponse + + def _data_operate(self) -> None: + raise NotImplementedError() diff --git a/src/backends/protocols/gamespy/web_services/requests.py b/src/backends/protocols/gamespy/web_services/requests.py new file mode 100644 index 000000000..494b45644 --- /dev/null +++ b/src/backends/protocols/gamespy/web_services/requests.py @@ -0,0 +1,148 @@ + +from pydantic import BaseModel +import backends.library.abstractions.contracts as lib + + +class SakeRequestBase(lib.RequestBase): + game_id: int + secret_key: str + login_ticket: str + table_id: int + + +class CreateRecordData(BaseModel): + name: str + type: str + value: str + + +class CreateRecordRequest(SakeRequestBase): + values: list[CreateRecordData] + + +class DeleteRecordRequest(SakeRequestBase): + record_id: int + + +class GetMyRecordsData(BaseModel): + name: str + value: str + + +class GetMyRecordsRequest(SakeRequestBase): + fields: list[GetMyRecordsData] + + +class GetRandomRecordsData(BaseModel): + name: str + value: str + + +class GetRandomRecordsRequest(SakeRequestBase): + max: int + fields: list[GetRandomRecordsData] + + +class GetRecordLimitRequest(SakeRequestBase): + pass + + +class GetSpecificRecordsData(BaseModel): + name: str + type: str + + +class GetSpecificRecordsRequest(SakeRequestBase): + + record_ids: list[GetSpecificRecordsData] + fields: list[GetSpecificRecordsData] + + +class RateRecordRequest(SakeRequestBase): + record_id: str + rating: str + + +class SearchForRecordsData(BaseModel): + name: str + type: str + + +class SearchForRecordsRequest(SakeRequestBase): + filter: str + sort: str + offset: str + max: str + surrounding: str + owner_ids: str + cache_flag: str + fields: list[SearchForRecordsData] + + +class UpdateRecordData(BaseModel): + name: str + type: str + value: str + + +class UpdateRecordRequest(SakeRequestBase): + record_id: str + values: list[UpdateRecordData] + + +# Auth + +class AuthRequestBase(lib.RequestBase): + version: int + partner_code: int + namespace_id: int + game_id: int | None = None + + +class LoginProfileRequest(AuthRequestBase): + email: str + uniquenick: str + cdkey: str + password: str + + +class LoginPS3CertRequest(AuthRequestBase): + ps3_cert: str + npticket: str + + +class LoginRemoteAuthRequest(AuthRequestBase): + auth_token: str + challenge: str + + +class LoginUniqueNickRequest(AuthRequestBase): + uniquenick: str + password: str + + +class CreateUserAccountRequest(AuthRequestBase): + email: str + nick: str + uniquenick: str + password: str + +# D2G + + +class Direct2GameRequestBase(lib.RequestBase): + pass + + +class GetPurchaseHistoryRequest(Direct2GameRequestBase): + game_id: int + access_token: str + proof: str + certificate: str + + +class GetStoreAvailabilityRequest(Direct2GameRequestBase): + game_id: int + version: int + region: str + access_token: str diff --git a/src/backends/protocols/gamespy/web_services/responses.py b/src/backends/protocols/gamespy/web_services/responses.py new file mode 100644 index 000000000..2a12dad96 --- /dev/null +++ b/src/backends/protocols/gamespy/web_services/responses.py @@ -0,0 +1,49 @@ +from backends.library.abstractions.contracts import DataResponse +from frontends.gamespy.protocols.web_services.modules.auth.contracts.results import CreateUserAccountResult, LoginProfileResult, LoginPs3CertResult, LoginRemoteAuthResult, LoginUniqueNickResult +from frontends.gamespy.protocols.web_services.modules.direct2game.contracts.results import GetPurchaseHistoryResult +from frontends.gamespy.protocols.web_services.modules.sake.contracts.results import CreateRecordResult, GetMyRecordsResult, SearchForRecordsResult + +# region Auth + + +class LoginProfileResponse(DataResponse): + result: LoginProfileResult + + +class LoginPS3CertRepsonse(DataResponse): + result: LoginPs3CertResult + + +class LoginRemoteAuthRepsonse(DataResponse): + result: LoginRemoteAuthResult + + +class LoginUniqueNickResponse(DataResponse): + result: LoginUniqueNickResult + + +class GetPurchaceHistoryResponse(DataResponse): + result: GetPurchaseHistoryResult + + +class CreateUserAccountResponse(DataResponse): + result: CreateUserAccountResult + + + +# class GetTargettedAdResponse(DataResponse): +# result: GetTargettedAdResult + +# region Sake + + +class CreateRecordResponse(DataResponse): + result: CreateRecordResult + + +class GetMyRecordsResponse(DataResponse): + result: GetMyRecordsResult + + +class SearchForRecordsResponse(DataResponse): + result: SearchForRecordsResult diff --git a/src/backends/routers/gamespy/chat.py b/src/backends/routers/gamespy/chat.py new file mode 100644 index 000000000..018f3c436 --- /dev/null +++ b/src/backends/routers/gamespy/chat.py @@ -0,0 +1,275 @@ +from backends.library.abstractions.contracts import RESPONSES_DEF, OKResponse, Response +from backends.protocols.gamespy.chat.brocker import MANAGER, launch_brocker +from backends.protocols.gamespy.chat.handlers import ( + CdKeyHandler, + CryptHandler, + GetCKeyHandler, + GetChannelKeyHandler, + GetKeyHandler, + GetUdpRelayHandler, + InviteHandler, + JoinHandler, + ModeHandler, + NamesHandler, + NickHandler, + PartHandler, + PrivateHandler, + PublishMessageHandler, + QuitHandler, + SetCKeyHandler, + SetKeyHandler, + TopicHandler, + UserHandler, + WhoIsHandler, +) +from backends.protocols.gamespy.chat.requests import ( + AtmRequest, + CdkeyRequest, + CryptRequest, + GetCKeyRequest, + GetChannelKeyRequest, + GetKeyRequest, + GetUdpRelayRequest, + InviteRequest, + JoinRequest, + KickRequest, + ListRequest, + LoginRequest, + ModeRequest, + NamesRequest, + NickRequest, + NoticeRequest, + PartRequest, + PrivateRequest, + PublishMessageRequest, + QuitRequest, + SetCKeyRequest, + SetChannelKeyRequest, + SetGroupRequest, + SetKeyRequest, + TopicRequest, + UtmRequest, + UserIPRequest, + UserRequest, + WhoIsRequest, + WhoRequest, +) +from backends.protocols.gamespy.chat.response import AtmResponse, CryptResponse, GetCkeyResponse, GetKeyResponse, JoinResponse, ListResponse, ModeResponse, NamesResponse, NicksResponse, NoticeResponse, PartResponse, PrivateResponse, SetCKeyResponse, SetChannelKeyResponse, TopicResponse, UtmResponse, WhoIsResponse, WhoResponse +from backends.urls import CHAT +from fastapi import APIRouter, FastAPI, WebSocket + + +router = APIRouter(lifespan=launch_brocker) +client_pool = {} + + +@router.post(f"{CHAT}/PublishMessageHandler", responses=RESPONSES_DEF) +def publish_message(request: PublishMessageRequest) -> OKResponse: + handler = PublishMessageHandler(request) + handler.handle() + return handler.response + + +@router.websocket(f"{CHAT}/ws") +async def websocket_endpoint(ws: WebSocket): + await MANAGER.process_websocket(ws) + + +# region General + + +@router.post(f"{CHAT}/CdKeyHandler", responses=RESPONSES_DEF) +def cdkey(request: CdkeyRequest) -> Response: + handler = CdKeyHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{CHAT}/GetKeyHandler", responses=RESPONSES_DEF) +def getkey(request: GetKeyRequest) -> GetKeyResponse: + handler = GetKeyHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{CHAT}/GetUdpRelayHandler", responses=RESPONSES_DEF) +def get_udp_relay(request: GetUdpRelayRequest) -> Response: + handler = GetUdpRelayHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{CHAT}/InviteHandler", responses=RESPONSES_DEF) +def invite(request: InviteRequest) -> Response: + handler = InviteHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{CHAT}/ListHandler", responses=RESPONSES_DEF) +def list_data(request: ListRequest) -> ListResponse: + # handler = ListHandler + raise NotImplementedError() + + +@router.post(f"{CHAT}/LoginHandler", responses=RESPONSES_DEF) +def login(request: LoginRequest) -> Response: + raise NotImplementedError() + + +@router.post(f"{CHAT}/NickHandler", responses=RESPONSES_DEF) +def nick(request: NickRequest) -> NicksResponse: + handler = NickHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{CHAT}/QuitHandler", responses=RESPONSES_DEF) +def quit(request: QuitRequest) -> Response: + handler = QuitHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{CHAT}/SetKeyHandler", responses=RESPONSES_DEF) +def set_key(request: SetKeyRequest) -> OKResponse: + handler = SetKeyHandler(request) + handler.handle + return handler.response + + +@router.post(f"{CHAT}/UserHandler", responses=RESPONSES_DEF) +def user(request: UserRequest) -> Response: + handler = UserHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{CHAT}/UserIPHandler", responses=RESPONSES_DEF) +def user_ip(request: UserIPRequest) -> OKResponse: + return OKResponse() + + +@router.post(f"{CHAT}/WhoHandler", responses=RESPONSES_DEF) +def who(request: WhoRequest) -> WhoResponse: + raise NotImplementedError() + + +@router.post(f"{CHAT}/WhoIsHandler", responses=RESPONSES_DEF) +def whois(request: WhoIsRequest) -> WhoIsResponse: + handler = WhoIsHandler(request) + handler.handle() + return handler.response + + +# region channel +@router.post(f"{CHAT}/GetChannelKeyHandler", responses=RESPONSES_DEF) +def get_channel_key(request: GetChannelKeyRequest) -> Response: + handler = GetChannelKeyHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{CHAT}/GetCKeyHandler", responses=RESPONSES_DEF) +def get_ckey(request: GetCKeyRequest) -> GetCkeyResponse: + handler = GetCKeyHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{CHAT}/JoinHandler", responses=RESPONSES_DEF) +def join(request: JoinRequest) -> JoinResponse: + handler = JoinHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{CHAT}/KickHandler", responses=RESPONSES_DEF) +def kick(request: KickRequest) -> Response: + raise NotImplementedError() + + +@router.post(f"{CHAT}/ModeHandler", responses=RESPONSES_DEF) +def mode(request: ModeRequest) -> ModeResponse | OKResponse: + handler = ModeHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{CHAT}/NamesHandler", responses=RESPONSES_DEF) +def names(request: NamesRequest) -> NamesResponse: + handler = NamesHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{CHAT}/PartHandler", responses=RESPONSES_DEF) +def part(request: PartRequest) -> PartResponse: + handler = PartHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{CHAT}/SetChannelKeyHandler", responses=RESPONSES_DEF) +def set_channel_key(request: SetChannelKeyRequest) -> SetChannelKeyResponse: + raise NotImplementedError() + + +@router.post(f"{CHAT}/SetCKeyHandler", responses=RESPONSES_DEF) +def set_c_key(request: SetCKeyRequest) -> SetCKeyResponse: + handler = SetCKeyHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{CHAT}/SetGroupHandler", responses=RESPONSES_DEF) +def set_group(request: SetGroupRequest) -> Response: + raise NotImplementedError() + + +@router.post(f"{CHAT}/TopicHandler", responses=RESPONSES_DEF) +def topic(request: TopicRequest) -> TopicResponse: + handler = TopicHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{CHAT}/CryptHandler", responses=RESPONSES_DEF) +def crypt(request: CryptRequest) -> CryptResponse: + handler = CryptHandler(request) + handler.handle() + return handler.response + + +# region Message + + +@router.post(f"{CHAT}/ATMHandler", responses=RESPONSES_DEF) +def atm(request: AtmRequest) -> AtmResponse: + raise NotImplementedError() + + +@router.post(f"{CHAT}/NoticeHandler", responses=RESPONSES_DEF) +def notice(request: NoticeRequest) -> NoticeResponse: + raise NotImplementedError() + + +@router.post(f"{CHAT}/PrivateHandler", responses=RESPONSES_DEF) +def private(request: PrivateRequest) -> PrivateResponse: + handler = PrivateHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{CHAT}/UTMHandler", responses=RESPONSES_DEF) +def utm(request: UtmRequest) -> UtmResponse: + raise NotImplementedError() + + +if __name__ == "__main__": + import uvicorn + from fastapi import FastAPI + + app = FastAPI() + app.include_router(router) + uvicorn.run(app, host="0.0.0.0", port=8080) diff --git a/src/backends/routers/gamespy/game_stats.py b/src/backends/routers/gamespy/game_stats.py new file mode 100644 index 000000000..31f0b5457 --- /dev/null +++ b/src/backends/routers/gamespy/game_stats.py @@ -0,0 +1,82 @@ +from fastapi import APIRouter +from backends.library.abstractions.contracts import RESPONSES_DEF, OKResponse, Response +from backends.protocols.gamespy.game_status.handlers import ( + AuthGameHandler, + AuthPlayerHandler, + GetPlayerDataHandler, + GetProfileIdHandler, + NewGameHandler, + SetPlayerDataHandler, + UpdateGameHandler, +) +from backends.protocols.gamespy.game_status.requests import ( + AuthGameRequest, + AuthPlayerRequest, + GetPlayerDataRequest, + GetProfileIdRequest, + NewGameRequest, + SetPlayerDataRequest, + UpdateGameRequest, +) +from backends.protocols.gamespy.game_status.response import AuthGameResponse, AuthPlayerResponse, GetPlayerDataResponse, GetProfileIdResponse, SetPlayerDataResponse +from backends.urls import GAMESTATUS + +router = APIRouter() + + +@router.post(f"{GAMESTATUS}/AuthGameHandler", responses=RESPONSES_DEF) +def auth_game(request: AuthGameRequest) -> AuthGameResponse: + handler = AuthGameHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{GAMESTATUS}/AuthPlayerHandler", responses=RESPONSES_DEF) +def auth_player(request: AuthPlayerRequest) -> AuthPlayerResponse: + handler = AuthPlayerHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{GAMESTATUS}/NewGameHandler", responses=RESPONSES_DEF) +def new_game(request: NewGameRequest) -> OKResponse: + handler = NewGameHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{GAMESTATUS}/GetPlayerDataHandler", responses=RESPONSES_DEF) +def get_player_data(request: GetPlayerDataRequest) -> GetPlayerDataResponse: + handler = GetPlayerDataHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{GAMESTATUS}/SetPlayerDataHandler", responses=RESPONSES_DEF) +def set_player_data(request: SetPlayerDataRequest) -> SetPlayerDataResponse: + handler = SetPlayerDataHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{GAMESTATUS}/UpdateGameHandler", responses=RESPONSES_DEF) +def update_game(request: UpdateGameRequest) -> OKResponse: + handler = UpdateGameHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{GAMESTATUS}/GetProfileIdHandler", responses=RESPONSES_DEF) +def get_profileid(request: GetProfileIdRequest)->GetProfileIdResponse: + handler = GetProfileIdHandler(request) + handler.handle() + return handler.response + + +if __name__ == "__main__": + import uvicorn + from fastapi import FastAPI + + app = FastAPI() + app.include_router(router) + uvicorn.run(app, host="0.0.0.0", port=8080) diff --git a/src/backends/routers/gamespy/game_traffic_relay.py b/src/backends/routers/gamespy/game_traffic_relay.py new file mode 100644 index 000000000..540cd4326 --- /dev/null +++ b/src/backends/routers/gamespy/game_traffic_relay.py @@ -0,0 +1,33 @@ +from fastapi import APIRouter, Request + +from backends.library.abstractions.contracts import RESPONSES_DEF, Response +from backends.library.utils.misc import check_public_ip +from backends.protocols.gamespy.game_traffic_relay.handlers import ( + GtrHeartBeatHandler, +) +from backends.protocols.gamespy.game_traffic_relay.requests import ( + GtrHeartBeatRequest, +) +from backends.urls import GAME_TRAFFIC_RELAY +from frontends.gamespy.library.exceptions.general import UniSpyException + +router = APIRouter() + + +@router.post(f"{GAME_TRAFFIC_RELAY}/Heartbeat", responses=RESPONSES_DEF) +def heartbeat(request: Request, heartbeat: GtrHeartBeatRequest) -> Response: + assert request.client is not None + check_public_ip(request.client.host, heartbeat.public_ip_address) + + handler = GtrHeartBeatHandler(heartbeat) + handler.handle() + return handler.response + + +if __name__ == "__main__": + import uvicorn + from fastapi import FastAPI + + app = FastAPI() + app.include_router(router) + uvicorn.run(app, host="0.0.0.0", port=8080) diff --git a/src/backends/routers/gamespy/natneg.py b/src/backends/routers/gamespy/natneg.py new file mode 100644 index 000000000..437edbc16 --- /dev/null +++ b/src/backends/routers/gamespy/natneg.py @@ -0,0 +1,49 @@ +from fastapi import APIRouter + +from backends.library.abstractions.contracts import RESPONSES_DEF, DataResponse, OKResponse, Response +from backends.protocols.gamespy.natneg.handlers import ConnectHandler, InitHandler, ReportHandler +from backends.protocols.gamespy.natneg.requests import AddressCheckRequest, ConnectRequest, ErtAckRequest, InitRequest, ReportRequest +from backends.protocols.gamespy.natneg.responses import ConnectResponse +from backends.urls import NATNEG + + +router = APIRouter() + + +@router.post(f"{NATNEG}/AddressCheckHandler", responses=RESPONSES_DEF) +def address_check(request: AddressCheckRequest) -> Response: + raise NotImplementedError() + + +@router.post(f"{NATNEG}/ConnectHandler", responses=RESPONSES_DEF) +def connect(request: ConnectRequest) -> ConnectResponse: + handler = ConnectHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{NATNEG}/ErtAckHandler", responses=RESPONSES_DEF) +def ert_ack(request: ErtAckRequest) -> Response: + raise NotImplementedError() + + +@router.post(f"{NATNEG}/InitHandler", responses=RESPONSES_DEF) +def init(request: InitRequest) -> Response: + handler = InitHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{NATNEG}/ReportHandler", responses=RESPONSES_DEF) +def report(request: ReportRequest) -> OKResponse: + handler = ReportHandler(request) + handler.handle() + return handler.response + + +if __name__ == "__main__": + import uvicorn + from fastapi import FastAPI + app = FastAPI() + app.include_router(router) + uvicorn.run(app, host="0.0.0.0", port=8080) diff --git a/src/backends/routers/gamespy/presence_connection_manager.py b/src/backends/routers/gamespy/presence_connection_manager.py new file mode 100644 index 000000000..e4fc021bc --- /dev/null +++ b/src/backends/routers/gamespy/presence_connection_manager.py @@ -0,0 +1,103 @@ +from fastapi import APIRouter + +from backends.library.abstractions.contracts import RESPONSES_DEF, OKResponse +from backends.protocols.gamespy.chat.requests import RegisterNickRequest +from backends.protocols.gamespy.presence_connection_manager.handlers import AddBlockHandler, GetProfileHandler, KeepAliveHandler, LoginHandler, LogoutHandler, NewProfileHandler, NewUserHandler, RegisterCDKeyHandler, RegisterNickHandler, StatusHandler, StatusInfoHandler, UpdateProfileHandler +from backends.protocols.gamespy.presence_connection_manager.requests import GetProfileRequest, LoginRequest, LogoutRequest, NewProfileRequest, RegisterCDKeyRequest, StatusInfoRequest, StatusRequest, UpdateProfileRequest, KeepAliveRequest, NewUserRequest, AddBlockRequest +from backends.protocols.gamespy.presence_connection_manager.responses import GetProfileResponse, LoginResponse +from backends.urls import PRESENCE_CONNECTION_MANAGER + + +router = APIRouter() + + +@router.post(f"{PRESENCE_CONNECTION_MANAGER}/LoginHandler", responses=RESPONSES_DEF) +def login(request: LoginRequest) -> LoginResponse: + handler = LoginHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{PRESENCE_CONNECTION_MANAGER}/LogoutHandler", responses=RESPONSES_DEF) +def logout(request: LogoutRequest) -> OKResponse: + handler = LogoutHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{PRESENCE_CONNECTION_MANAGER}/KeepAliveHandler", responses=RESPONSES_DEF) +def keep_alive(request: KeepAliveRequest) -> OKResponse: + handler = KeepAliveHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{PRESENCE_CONNECTION_MANAGER}/NewUserHandler", responses=RESPONSES_DEF) +def new_user(request: NewUserRequest) -> OKResponse: + handler = NewUserHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{PRESENCE_CONNECTION_MANAGER}/AddBlockHandler", responses=RESPONSES_DEF) +def add_block(request: AddBlockRequest) -> OKResponse: + handler = AddBlockHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{PRESENCE_CONNECTION_MANAGER}/GetProfileHandler", responses=RESPONSES_DEF) +def get_profile(request: GetProfileRequest) -> GetProfileResponse: + handler = GetProfileHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{PRESENCE_CONNECTION_MANAGER}/NewProfileHandler", responses=RESPONSES_DEF) +def new_proflie(request: NewProfileRequest) -> OKResponse: + handler = NewProfileHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{PRESENCE_CONNECTION_MANAGER}/RegisterCDKeyHandler", responses=RESPONSES_DEF) +def register_cdkey(request: RegisterCDKeyRequest) -> OKResponse: + handler = RegisterCDKeyHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{PRESENCE_CONNECTION_MANAGER}/RegisterNickHandler", responses=RESPONSES_DEF) +def register_nick(request: RegisterNickRequest) -> OKResponse: + handler = RegisterNickHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{PRESENCE_CONNECTION_MANAGER}/UpdateProfileHandler", responses=RESPONSES_DEF) +def update_profile(request: UpdateProfileRequest) -> OKResponse: + handler = UpdateProfileHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{PRESENCE_CONNECTION_MANAGER}/StatusHandler", responses=RESPONSES_DEF) +def status(request: StatusRequest) -> OKResponse: + handler = StatusHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{PRESENCE_CONNECTION_MANAGER}/StatusInfoHandler", responses=RESPONSES_DEF) +def status_info(request: StatusInfoRequest) -> OKResponse: + handler = StatusInfoHandler(request) + handler.handle() + return handler.response + + +if __name__ == "__main__": + import uvicorn + from fastapi import FastAPI + app = FastAPI() + app.include_router(router) + uvicorn.run(app, host="0.0.0.0", port=8080) diff --git a/src/backends/routers/gamespy/presence_search_player.py b/src/backends/routers/gamespy/presence_search_player.py new file mode 100644 index 000000000..8d3ec71cd --- /dev/null +++ b/src/backends/routers/gamespy/presence_search_player.py @@ -0,0 +1,89 @@ +from fastapi import APIRouter + +from backends.library.abstractions.contracts import RESPONSES_DEF + +from backends.protocols.gamespy.presence_search_player.handlers import CheckHandler, NewUserHandler, NicksHandler, OthersHandler, OthersListHandler, SearchHandler, SearchUniqueHandler, UniqueSearchHandler, ValidHandler + +from backends.protocols.gamespy.presence_search_player.requests import CheckRequest, NewUserRequest, NicksRequest, OthersListRequest, OthersRequest, SearchRequest, SearchUniqueRequest, UniqueSearchRequest, ValidRequest + +from backends.protocols.gamespy.presence_search_player.responses import CheckResponse, NewUserResponse, NicksResponse, OthersListResponse, OthersResponse, SearchResponse, SearchUniqueResponse, UniqueSearchResponse, ValidResponse + +from backends.urls import PRESENCE_SEARCH_PLAYER + +router = APIRouter() + + +@router.post(f"{PRESENCE_SEARCH_PLAYER}/CheckHandler", responses=RESPONSES_DEF) +def check(request: CheckRequest) -> CheckResponse: + handler = CheckHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{PRESENCE_SEARCH_PLAYER}/NewUserHandler", responses=RESPONSES_DEF) +def new_user(request: NewUserRequest) -> NewUserResponse: + handler = NewUserHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{PRESENCE_SEARCH_PLAYER}/NicksHandler", responses=RESPONSES_DEF) +def nicks(request: NicksRequest) -> NicksResponse: + handler = NicksHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{PRESENCE_SEARCH_PLAYER}/OthersHandler", responses=RESPONSES_DEF) +def others(request: OthersRequest) -> OthersResponse: + handler = OthersHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{PRESENCE_SEARCH_PLAYER}/OthersListHandler", responses=RESPONSES_DEF) +def others_list(request: OthersListRequest) -> OthersListResponse: + handler = OthersListHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{PRESENCE_SEARCH_PLAYER}/PMatchHandler", responses=RESPONSES_DEF) +def player_match(request: dict): + raise NotImplementedError() + + +@router.post(f"{PRESENCE_SEARCH_PLAYER}/SearchHandler", responses=RESPONSES_DEF) +def search(request: SearchRequest) -> SearchResponse: + handler = SearchHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{PRESENCE_SEARCH_PLAYER}/SearchUniqueHandler", responses=RESPONSES_DEF) +def search_unique(request: SearchUniqueRequest) -> SearchUniqueResponse: + handler = SearchUniqueHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{PRESENCE_SEARCH_PLAYER}/UniqueSearchHandler", responses=RESPONSES_DEF) +def unique_search(request: UniqueSearchRequest) -> UniqueSearchResponse: + handler = UniqueSearchHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{PRESENCE_SEARCH_PLAYER}/ValidHandler", responses=RESPONSES_DEF) +def valid(request: ValidRequest) -> ValidResponse: + handler = ValidHandler(request) + handler.handle() + return handler.response + + +if __name__ == "__main__": + import uvicorn + from fastapi import FastAPI + app = FastAPI() + app.include_router(router) + uvicorn.run(app, host="0.0.0.0", port=8080) diff --git a/src/backends/routers/gamespy/query_report.py b/src/backends/routers/gamespy/query_report.py new file mode 100644 index 000000000..e864dcd55 --- /dev/null +++ b/src/backends/routers/gamespy/query_report.py @@ -0,0 +1,67 @@ +from fastapi import APIRouter, WebSocket +from backends.library.abstractions.contracts import RESPONSES_DEF, OKResponse +from backends.protocols.gamespy.query_report.broker import MANAGER, launch_brocker +from backends.protocols.gamespy.query_report.handlers import ( + AvaliableHandler, HeartbeatHandler, KeepAliveHandler, LegacyHeartbeatHandler) +from backends.protocols.gamespy.query_report.requests import ( + AvaliableRequest, ChallengeRequest, ClientMessageRequest, EchoRequest, HeartBeatRequest, KeepAliveRequest, LegacyHeartbeatRequest) +from backends.urls import QUERY_REPORT + + +router = APIRouter(lifespan=launch_brocker) + + +@router.websocket(f"{QUERY_REPORT}/ws") +async def websocket_endpoint(ws: WebSocket): + await MANAGER.process_websocket(ws) + + +@router.post(f"{QUERY_REPORT}/HeartbeatHandler", responses=RESPONSES_DEF) +def heartbeat(request: HeartBeatRequest) -> OKResponse: + handler = HeartbeatHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{QUERY_REPORT}/ChallengeHanler", responses=RESPONSES_DEF) +def challenge(request: ChallengeRequest) -> OKResponse: + raise NotImplementedError() + + +@router.post(f"{QUERY_REPORT}/AvailableHandler", responses=RESPONSES_DEF) +def available(request: AvaliableRequest) -> OKResponse: + handler = AvaliableHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{QUERY_REPORT}/ClientMessageAckHandler", responses=RESPONSES_DEF) +def client_message(request: ClientMessageRequest) -> OKResponse: + raise NotImplementedError() + + +@router.post(f"{QUERY_REPORT}/EchoHandler", responses=RESPONSES_DEF) +def echo(request: EchoRequest) -> OKResponse: + raise NotImplementedError() + + +@router.post(f"{QUERY_REPORT}/KeepAliveHandler", responses=RESPONSES_DEF) +def keep_alive(request: KeepAliveRequest) -> OKResponse: + handler = KeepAliveHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{QUERY_REPORT}/LegacyHeartbeatHandler", responses=RESPONSES_DEF) +def legacy_heartbeat(request: LegacyHeartbeatRequest) -> OKResponse: + handler = LegacyHeartbeatHandler(request) + handler.handle() + return handler.response + + +if __name__ == "__main__": + import uvicorn + from fastapi import FastAPI + app = FastAPI() + app.include_router(router) + uvicorn.run(app, host="0.0.0.0", port=8080) diff --git a/src/backends/routers/gamespy/server_browser.py b/src/backends/routers/gamespy/server_browser.py new file mode 100644 index 000000000..a38448b77 --- /dev/null +++ b/src/backends/routers/gamespy/server_browser.py @@ -0,0 +1,72 @@ +from fastapi import APIRouter, WebSocket, WebSocketDisconnect +from backends.library.abstractions.contracts import RESPONSES_DEF, OKResponse +from backends.protocols.gamespy.server_browser.handlers import P2PGroupRoomListHandler, ServerFullInfoListHandler, ServerInfoHandler, ServerMainListHandler +from backends.protocols.gamespy.server_browser.requests import SendMessageRequest, ServerInfoRequest, ServerListRequest +from backends.protocols.gamespy.server_browser.responses import P2PGroupRoomListResponse, ServerFullInfoListResponse, ServerInfoResponse, ServerMainListResponse +from backends.urls import SERVER_BROWSER_V2 + +router = APIRouter() +# todo maybe implement this in websocket way + +client_pool: dict[str, WebSocket] = {} + + +@router.websocket(f"{SERVER_BROWSER_V2}/AdHocHandler") +def check(websocket: WebSocket): + """ + notify every server browser to send message to its client + """ + raise NotImplementedError() + websocket.accept() + while True: + try: + data = websocket.receive_text() + client_pool[websocket.client.host] = websocket + websocket.send_text( + f"Message text was: {data}", responses=RESPONSES_DEF) + except WebSocketDisconnect: + del client_pool[websocket.client.host] + + +@router.post(f"{SERVER_BROWSER_V2}/SendMessageHandler", responses=RESPONSES_DEF) +def send_message(request: SendMessageRequest) -> OKResponse: + raise NotImplementedError() + + +@router.post(f"{SERVER_BROWSER_V2}/P2PGroupRoomListHandler", responses=RESPONSES_DEF) +def p2p_group_room_list(request: ServerListRequest) -> P2PGroupRoomListResponse: + handler = P2PGroupRoomListHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{SERVER_BROWSER_V2}/ServerInfoHandler", responses=RESPONSES_DEF) +def server_info(request: ServerInfoRequest) -> ServerInfoResponse: + handler = ServerInfoHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{SERVER_BROWSER_V2}/ServerMainListHandler", responses=RESPONSES_DEF) +def server_list(request: ServerListRequest) -> ServerMainListResponse: + """ we send all server data to client to make it have HAS_FULL_RULES_FLAG + and will not send ServerBrowserAuxUpdateServer(sb, server, async, fullUpdate) to + """ + handler = ServerMainListHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{SERVER_BROWSER_V2}/ServerFullInfoListHandler", responses=RESPONSES_DEF) +def full_info_list(request: ServerListRequest) -> ServerFullInfoListResponse: + handler = ServerFullInfoListHandler(request) + handler.handle() + return handler.response + + +if __name__ == "__main__": + import uvicorn + from fastapi import FastAPI + app = FastAPI() + app.include_router(router) + uvicorn.run(app, host="0.0.0.0", port=8080) diff --git a/src/backends/routers/gamespy/web_services.py b/src/backends/routers/gamespy/web_services.py new file mode 100644 index 000000000..9d31c283e --- /dev/null +++ b/src/backends/routers/gamespy/web_services.py @@ -0,0 +1,131 @@ +from fastapi import APIRouter + +from backends.library.abstractions.contracts import RESPONSES_DEF, OKResponse +from backends.protocols.gamespy.web_services.handlers import CreateRecordHandler, CreateUserAccountHandler, GetMyRecordsHandler, LoginProfileHandler, LoginRemoteAuthHandler, LoginUniqueNickHandler, SearchForRecordsHandler +from backends.protocols.gamespy.web_services.responses import CreateRecordResponse, GetMyRecordsResponse, LoginProfileResponse, LoginRemoteAuthRepsonse, LoginUniqueNickResponse, SearchForRecordsResponse +from backends.urls import WEB_SERVICES +from backends.protocols.gamespy.web_services.requests import CreateRecordRequest, CreateUserAccountRequest, GetMyRecordsRequest, LoginProfileRequest, LoginRemoteAuthRequest, LoginUniqueNickRequest, SearchForRecordsRequest + +router = APIRouter() + +# Altas services + + +@router.post(f"{WEB_SERVICES}/CreateRecordHandler", responses=RESPONSES_DEF) +def create_matchless_session(request): + raise NotImplementedError() + + +@router.post(f"{WEB_SERVICES}/CreateSessionHandler", responses=RESPONSES_DEF) +def create_session(request): + raise NotImplementedError() + + +@router.post(f"{WEB_SERVICES}/SetReportIntentionHandler", responses=RESPONSES_DEF) +def set_report_intention(request): + raise NotImplementedError() + + +@router.post(f"{WEB_SERVICES}/SubmitReportHandler", responses=RESPONSES_DEF) +def submit_report(request): + raise NotImplementedError() + + +# Auth services +@router.post(f"{WEB_SERVICES}/LoginProfileHandler", responses=RESPONSES_DEF) +def login_profile(request: LoginProfileRequest) -> LoginProfileResponse: + handler = LoginProfileHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{WEB_SERVICES}/LoginProfileWithGameIdHandler", responses=RESPONSES_DEF) +def login_profile_with_game_id(request: LoginProfileRequest) -> LoginProfileResponse: + return login_profile(request) + + +@router.post(f"{WEB_SERVICES}/LoginRemoteAuthHandler", responses=RESPONSES_DEF) +def login_remote_auth(request: LoginRemoteAuthRequest) -> LoginRemoteAuthRepsonse: + handler = LoginRemoteAuthHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{WEB_SERVICES}/LoginRemoteAuthWithGameIdHandler", responses=RESPONSES_DEF) +def login_remote_auth_with_game_id(request: LoginRemoteAuthRequest) -> LoginRemoteAuthRepsonse: + return login_remote_auth(request) + + +@router.post(f"{WEB_SERVICES}/LoginUniqueNickHandler", responses=RESPONSES_DEF) +def login_uniquenick(request: LoginUniqueNickRequest) -> LoginUniqueNickResponse: + handler = LoginUniqueNickHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{WEB_SERVICES}/LoginUniqueNickWithGameIdHandler", responses=RESPONSES_DEF) +def login_uniquenick_with_game_id(request: LoginUniqueNickRequest) -> LoginUniqueNickResponse: + return login_uniquenick(request) + + +@router.post(f"{WEB_SERVICES}/CreateUserAccountHandler", responses=RESPONSES_DEF) +def create_user_account(request: CreateUserAccountRequest): + handler = CreateUserAccountHandler(request) + handler.handle() + return handler.response + +# SAKE services + + +@router.post(f"{WEB_SERVICES}/CreateRecordHandler", responses=RESPONSES_DEF) +def create_record(request: CreateRecordRequest) -> CreateRecordResponse: + handler = CreateRecordHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{WEB_SERVICES}/DeleteRecordHandler", responses=RESPONSES_DEF) +def delete_record(request) -> OKResponse: + raise NotImplementedError() + + +@router.post(f"{WEB_SERVICES}/GetMyRecordsHandler", responses=RESPONSES_DEF) +def get_my_records(request: GetMyRecordsRequest) -> GetMyRecordsResponse: + handler = GetMyRecordsHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{WEB_SERVICES}/GetRandomRecordsHandler", responses=RESPONSES_DEF) +def get_random_records(request): + raise NotImplementedError() + + +@router.post(f"{WEB_SERVICES}/GetRecordLimitHandler", responses=RESPONSES_DEF) +def get_record_limit(request): + raise NotImplementedError() + + +@router.post(f"{WEB_SERVICES}/RateRecordHandler", responses=RESPONSES_DEF) +def rate_record(request): + raise NotImplementedError() + + +@router.post(f"{WEB_SERVICES}/SearchForRecordsHandler", responses=RESPONSES_DEF) +def search_for_records(request: SearchForRecordsRequest) -> SearchForRecordsResponse: + handler = SearchForRecordsHandler(request) + handler.handle() + return handler.response + + +@router.post(f"{WEB_SERVICES}/UpdateRecordHandler", responses=RESPONSES_DEF) +def update_record(request): + raise NotImplementedError() + + +if __name__ == "__main__": + import uvicorn + from fastapi import FastAPI + app = FastAPI() + app.include_router(router) + uvicorn.run(app, host="0.0.0.0", port=8080) diff --git a/src/backends/routers/home.py b/src/backends/routers/home.py new file mode 100644 index 000000000..cbc05f80c --- /dev/null +++ b/src/backends/routers/home.py @@ -0,0 +1,93 @@ +from ipaddress import IPv4Address +from uuid import UUID +from fastapi import FastAPI, Request, status +from fastapi.exceptions import RequestValidationError +from fastapi.responses import JSONResponse +from pydantic import BaseModel +import uvicorn + +from backends.library.abstractions.contracts import ErrorResponse +from backends.library.database.pg_orm import ENGINE +from backends.library.utils.misc import check_public_ip +from backends.services.register import register_services +from frontends.gamespy.library.exceptions.general import UniSpyException +from frontends.gamespy.library.log.log_manager import LogManager +from frontends.gamespy.library.configs import CONFIG, ServerConfig +from backends.routers.gamespy import ( + chat, + game_stats, + game_traffic_relay, + natneg, + presence_connection_manager, + presence_search_player, + query_report, + server_browser, + web_services, +) + +app = FastAPI() + +app.include_router(chat.router) +app.include_router(game_stats.router) +app.include_router(game_traffic_relay.router) +app.include_router(natneg.router) +app.include_router(presence_connection_manager.router) +app.include_router(presence_search_player.router) +app.include_router(query_report.router) +app.include_router(server_browser.router) +app.include_router(web_services.router) + +logger = LogManager.create("backend") + + +@app.exception_handler(UniSpyException) +def unispy_exception_handler(_, exc: UniSpyException): + str_error = exc.message + logger.error(exc.message) + err_resp = ErrorResponse( + message=str_error, exception_name=type(exc).__name__) + return JSONResponse(err_resp.model_dump(mode="json"), status_code=450) + + +@app.exception_handler(RequestValidationError) +def validation_exception_handler(_, exc: RequestValidationError): + str_error = str(exc.args) + logger.error(str_error) + err_resp = ErrorResponse( + message=str_error, exception_name=type(exc).__name__) + return JSONResponse(err_resp.model_dump(mode="json"), status_code=status.HTTP_400_BAD_REQUEST) + + +@app.exception_handler(Exception) +def general_exception_handler(_, exc: Exception): + str_error = str(exc) + if len(str_error) == 0: + str_error = exc.__class__.__name__ + logger.error(str_error) + err_resp = ErrorResponse( + message=str_error, exception_name=type(exc).__name__) + return JSONResponse(err_resp.model_dump(mode="json"), status_code=status.HTTP_500_INTERNAL_SERVER_ERROR) + + +@app.post("/") +def home(request: Request, config: ServerConfig) -> dict: + # todo add the server config to our database + assert request.client is not None + check_public_ip(request.client.host, config.listening_address) + # response = register_services(config, request.client.host) + return {"status": "online"} + + +class RegisterRequest(BaseModel): + server_id: UUID + client_ip: IPv4Address + + +@app.post("/token") +def get_auth_token(request: RegisterRequest): + pass + + +if __name__ == "__main__": + uvicorn.run("backends.routers.home:app", + host="0.0.0.0", port=8080, reload=True) diff --git a/src/backends/services/register.py b/src/backends/services/register.py new file mode 100644 index 000000000..0ae866ad6 --- /dev/null +++ b/src/backends/services/register.py @@ -0,0 +1,31 @@ + + +from datetime import datetime, timedelta +from backends.library.database.pg_orm import ENGINE, FrontendInfo +from frontends.gamespy.library.configs import ServerConfig +from sqlalchemy.orm import Session + +from frontends.gamespy.library.exceptions.general import UniSpyException + + +def register_services(config: ServerConfig, external_ip: str) -> dict: + expire_time = datetime.now() - timedelta(minutes=5) + with Session(ENGINE) as session: + result = session.query( + FrontendInfo.server_id == config.server_id, + FrontendInfo.update_time >= expire_time).first() + if result is not None: + info = FrontendInfo( + server_id=config.server_id, + server_name=config.server_name, + external_ip="", + listening_ip=config.listening_address, + listening_port=config.listening_port, + update_time=datetime.now() + ) + + session.add(info) + session.commit() + return {"status": "online"} + else: + raise UniSpyException("server is already registered") diff --git a/src/backends/tests/__init__.py b/src/backends/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backends/tests/gamespy/__init__.py b/src/backends/tests/gamespy/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backends/tests/gamespy/chat/__init__.py b/src/backends/tests/gamespy/chat/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backends/tests/gamespy/chat/lib_tests.py b/src/backends/tests/gamespy/chat/lib_tests.py new file mode 100644 index 000000000..d2a356919 --- /dev/null +++ b/src/backends/tests/gamespy/chat/lib_tests.py @@ -0,0 +1,48 @@ +# from typing import cast +# import unittest + +# from fastapi import WebSocket +# from fastapi.datastructures import Address + +# from backends.protocols.gamespy.chat.brocker_manager import ( +# ChatWebSocketClient, +# ChatWebSocketManager, +# ) + + +# class WebSocketMock: +# client: Address = Address("127.0.0.1", 123) + + +# class LibTests(unittest.TestCase): +# def test_ws_manager(self): +# ws = WebSocketMock() +# manager = ChatWebSocketManager() +# ws = cast(WebSocket, ws) +# manager.connect(ws) +# self.assertEqual(list(manager.client_pool.values())[0].ws, ws) +# manager.disconnect(ws) +# self.assertEqual(len(manager.client_pool.values()), 0) + +# def test_chat_ws_manager(self): +# ws = WebSocketMock() +# manager = ChatWebSocketManager() +# ws = cast(WebSocket, ws) +# manager.connect(ws) +# self.assertEqual(list(manager.client_pool.values())[0].ws, ws) + +# channel_name = "gmtest" +# manager.add_to_channel(channel_name, ws) +# client = manager.get_client(ws) +# client = cast(ChatWebSocketClient, client) +# manager.channel_info +# self.assertTrue(channel_name in manager.channel_info) +# self.assertTrue(len(manager.channel_info.values()) != 0) +# self.assertTrue(channel_name in client.channels) +# manager.remove_from_channel(channel_name, ws) +# self.assertTrue(channel_name not in manager.channel_info) +# self.assertTrue(len(manager.channel_info.values()) == 0) +# self.assertTrue(channel_name not in client.channels) + +# manager.disconnect(ws) +# self.assertEqual(len(manager.client_pool.values()), 0) diff --git a/src/backends/tests/gamespy/chat/room_tests.py b/src/backends/tests/gamespy/chat/room_tests.py new file mode 100644 index 000000000..6ab04502f --- /dev/null +++ b/src/backends/tests/gamespy/chat/room_tests.py @@ -0,0 +1,495 @@ +# import unittest + +# from frontends.gamespy.library.tests.mock_objects import BrokerMock +# from frontends.gamespy.protocols.chat.aggregates.channel import Channel +# from frontends.gamespy.protocols.chat.aggregates.channel_user import ChannelUser +# from frontends.gamespy.protocols.chat.tests.mock_objects import create_client + + +# class RoomTests(unittest.TestCase): +# def test_peer_room(self): +# client = create_client() +# client.info.gamename = "test" +# client.info.previously_joined_channel = "stagging" +# client.info.nick_name = "unispy" +# channel = Channel("test", client, brocker_cls=BrokerMock) +# user = ChannelUser(client, channel) +# channel.add_bind_on_user_and_channel(user) +# pass + +# def test_single_join(self, user_name="unispy", nick_name="unispy", channel_name="#GSP!room!test"): +# pass + + +# testclient.TestClient.get() +from fastapi.testclient import TestClient +from backends.routers.home import app +import unittest + +client = TestClient(app) + + +class RoomTest(unittest.TestCase): + def test_sdk(self): + client1_msg = [ + { + "raw_request": "CRYPT des 1 gmtest", + "command_name": "CRYPT", + "version_id": "1", + "gamename": "gmtest", + "websocket_address": "127.0.0.1:60720", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40394, + }, + { + "raw_request": "USRIP", + "command_name": "USRIP", + "websocket_address": "127.0.0.1:60720", + "remote_ip": "172.19.0.5", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40394, + }, + { + "raw_request": "USER ChatCUser 127.0.0.1 unispy_server_dev :ChatCName", + "command_name": "USER", + "user_name": "ChatCUser", + "local_ip_address": "127.0.0.1", + "server_name": "unispy_server_dev", + "name": "ChatCName", + "websocket_address": "127.0.0.1:60720", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40394, + }, + { + "raw_request": "NICK ChatC660", + "command_name": "NICK", + "nick_name": "ChatC660", + "websocket_address": "127.0.0.1:60720", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40394, + }, + { + "raw_request": "JOIN #GSP!gmtest ", + "broad_cast_raw": None, + "password": None, + "command_name": "JOIN", + "channel_name": "#GSP!gmtest", + "websocket_address": "127.0.0.1:60720", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40394, + }, + { + "raw_request": "NAMES #GSP!gmtest", + "broad_cast_raw": None, + "command_name": "NAMES", + "channel_name": "#GSP!gmtest", + "websocket_address": "127.0.0.1:60720", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40394, + }, + { + "raw_request": "MODE #GSP!gmtest", + "broad_cast_raw": None, + "command_name": "MODE", + "channel_name": "#GSP!gmtest", + "mode_operations": {}, + "request_type": 0, + "websocket_address": "127.0.0.1:60720", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40394, + }, + { + "raw_request": "PRIVMSG #GSP!gmtest :Hi", + "broad_cast_raw": "ChatC660!ChatCUser@unispy.net PRIVMSG #GSP!gmtest :Hi", + "command_name": "PRIVMSG", + "channel_name": "#GSP!gmtest", + "type": 0, + "message": "Hi", + "websocket_address": "127.0.0.1:60720", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40394, + }, + { + "raw_request": "NAMES #GSP!gmtest", + "broad_cast_raw": None, + "command_name": "NAMES", + "channel_name": "#GSP!gmtest", + "websocket_address": "127.0.0.1:60720", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40394, + }, + { + "raw_request": "WHOIS ChatC660", + "command_name": "WHOIS", + "nick_name": "ChatC660", + "websocket_address": "127.0.0.1:60720", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40394, + }, + { + "raw_request": "PRIVMSG #GSP!gmtest :Bye", + "broad_cast_raw": "ChatC660!ChatCUser@unispy.net PRIVMSG #GSP!gmtest :Bye", + "command_name": "PRIVMSG", + "channel_name": "#GSP!gmtest", + "type": 0, + "message": "Bye", + "websocket_address": "127.0.0.1:60720", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40394, + }, + { + "raw_request": "PART #GSP!gmtest :", + "broad_cast_raw": None, + "command_name": "PART", + "channel_name": "#GSP!gmtest", + "reason": "", + "websocket_address": "127.0.0.1:60720", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40394, + }, + { + "raw_request": "QUIT :Later!", + "command_name": "QUIT", + "reason": "Later!", + "websocket_address": "127.0.0.1:60720", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40394, + }, + ] + + client2_msg = [ + { + "raw_request": "CRYPT des 1 gmtest", + "command_name": "CRYPT", + "version_id": "1", + "gamename": "gmtest", + "websocket_address": "127.0.0.1:60721", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40395, + }, + { + "raw_request": "USRIP", + "command_name": "USRIP", + "websocket_address": "127.0.0.1:60721", + "remote_ip": "172.19.0.5", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40395, + }, + { + "raw_request": "USER ChatCUser1 127.0.0.1 unispy_server_dev :ChatCName", + "command_name": "USER", + "user_name": "ChatCUser1", + "local_ip_address": "127.0.0.1", + "server_name": "unispy_server_dev", + "name": "ChatCName", + "websocket_address": "127.0.0.1:60721", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40395, + }, + { + "raw_request": "NICK ChatC661", + "command_name": "NICK", + "nick_name": "ChatC661", + "websocket_address": "127.0.0.1:60721", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40395, + }, + { + "raw_request": "JOIN #GSP!gmtest ", + "broad_cast_raw": None, + "password": None, + "command_name": "JOIN", + "channel_name": "#GSP!gmtest", + "websocket_address": "127.0.0.1:60721", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40395, + }, + { + "raw_request": "NAMES #GSP!gmtest", + "broad_cast_raw": None, + "command_name": "NAMES", + "channel_name": "#GSP!gmtest", + "websocket_address": "127.0.0.1:60721", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40395, + }, + { + "raw_request": "MODE #GSP!gmtest", + "broad_cast_raw": None, + "command_name": "MODE", + "channel_name": "#GSP!gmtest", + "mode_operations": {}, + "request_type": 0, + "websocket_address": "127.0.0.1:60721", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40395, + }, + { + "raw_request": "PRIVMSG #GSP!gmtest :Hi", + "broad_cast_raw": "ChatC661!ChatCUser1@unispy.net PRIVMSG #GSP!gmtest :Hi", + "command_name": "PRIVMSG", + "channel_name": "#GSP!gmtest", + "type": 0, + "message": "Hi", + "websocket_address": "127.0.0.1:60721", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40395, + }, + { + "raw_request": "NAMES #GSP!gmtest", + "broad_cast_raw": None, + "command_name": "NAMES", + "channel_name": "#GSP!gmtest", + "websocket_address": "127.0.0.1:60721", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40395, + }, + { + "raw_request": "WHOIS ChatC661", + "command_name": "WHOIS", + "nick_name": "ChatC661", + "websocket_address": "127.0.0.1:60721", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40395, + }, + { + "raw_request": "PRIVMSG #GSP!gmtest :Bye", + "broad_cast_raw": "ChatC661!ChatCUser1@unispy.net PRIVMSG #GSP!gmtest :Bye", + "command_name": "PRIVMSG", + "channel_name": "#GSP!gmtest", + "type": 0, + "message": "Bye", + "websocket_address": "127.0.0.1:60721", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40395, + }, + { + "raw_request": "PART #GSP!gmtest :", + "broad_cast_raw": None, + "command_name": "PART", + "channel_name": "#GSP!gmtest", + "reason": "", + "websocket_address": "127.0.0.1:60721", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40395, + }, + { + "raw_request": "QUIT :Later!", + "command_name": "QUIT", + "reason": "Later!", + "websocket_address": "127.0.0.1:60721", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 40395, + }, + ] + + api = [ + "GameSpy/Chat/CryptHandler", + "GameSpy/Chat/UserIPHandler", + "GameSpy/Chat/UserHandler", + "GameSpy/Chat/NickHandler", + "GameSpy/Chat/JoinHandler", + "GameSpy/Chat/NamesHandler", + "GameSpy/Chat/ModeHandler", + "GameSpy/Chat/PrivateHandler", + "GameSpy/Chat/NamesHandler", + "GameSpy/Chat/WhoIsHandler", + "GameSpy/Chat/PrivateHandler", + "GameSpy/Chat/PartHandler", + "GameSpy/Chat/QuitHandler", + ] + for c1, c2, route in zip(client1_msg, client2_msg, api): + try: + client.post(url=route, json=c1) + client.post(url=route, json=c2) + except Exception as e: + print(e) + pass + + def test_peer(self): + """ + peer test in gamespy sdk + """ + test_msg = [ + { + "raw_request": "CRYPT des 1 gmtest", + "command_name": "CRYPT", + "version_id": "1", + "gamename": "gmtest", + "websocket_address": "127.0.0.1:59754", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 59258 + }, + { + "raw_request": "USRIP", + "command_name": "USRIP", + "websocket_address": "127.0.0.1:59754", + "remote_ip": "172.19.0.5", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 59258 + }, + { + "raw_request": "USER ChatCUser 127.0.0.1 unispy_server_dev :ChatCName", + "command_name": "USER", + "user_name": "ChatCUser", + "local_ip_address": "127.0.0.1", + "server_name": "unispy_server_dev", + "name": "ChatCName", + "websocket_address": "127.0.0.1:59754", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 59258 + }, + { + "raw_request": "NICK ChatC238", + "command_name": "NICK", + "nick_name": "ChatC238", + "websocket_address": "127.0.0.1:59754", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 59258 + }, + { + "raw_request": "JOIN #GSP!gmtest ", + "password": None, + "command_name": "JOIN", + "channel_name": "#GSP!gmtest", + "websocket_address": "127.0.0.1:59754", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 59258 + }, + { + "raw_request": "NAMES #GSP!gmtest", + "command_name": "NAMES", + "channel_name": "#GSP!gmtest", + "websocket_address": "127.0.0.1:59754", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 59258 + }, + { + "raw_request": "MODE #GSP!gmtest", + "command_name": "MODE", + "channel_name": "#GSP!gmtest", + "mode_operations": {}, + "request_type": 0, + "websocket_address": "127.0.0.1:59754", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 59258 + }, + { + "raw_request": "PRIVMSG #GSP!gmtest :Hi", + "command_name": "PRIVMSG", + "channel_name": "#GSP!gmtest", + "type": 0, + "target_name": "#GSP!gmtest", + "message": "Hi", + "websocket_address": "127.0.0.1:59754", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 59258 + }, + { + "raw_request": "NAMES #GSP!gmtest", + "command_name": "NAMES", + "channel_name": "#GSP!gmtest", + "websocket_address": "127.0.0.1:59754", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 59258 + }, + { + "raw_request": "WHOIS ChatC238", + "command_name": "WHOIS", + "nick_name": "ChatC238", + "websocket_address": "127.0.0.1:59754", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 59258 + }, + { + "raw_request": "PRIVMSG #GSP!gmtest :Bye", + "command_name": "PRIVMSG", + "channel_name": "#GSP!gmtest", + "type": 0, + "target_name": "#GSP!gmtest", + "message": "Bye", + "websocket_address": "127.0.0.1:59754", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 59258 + }, + { + "raw_request": "PART #GSP!gmtest :", + "command_name": "PART", + "channel_name": "#GSP!gmtest", + "reason": "", + "websocket_address": "127.0.0.1:59754", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 59258 + }, + { + "raw_request": "QUIT :Later!", + "command_name": "QUIT", + "reason": "Later!", + "websocket_address": "127.0.0.1:59754", + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 59258 + } + ] + test_api = ["GameSpy/Chat/CryptHandler", + "GameSpy/Chat/UserIPHandler", + "GameSpy/Chat/UserHandler", + "GameSpy/Chat/NickHandler", + "GameSpy/Chat/JoinHandler", + "GameSpy/Chat/NamesHandler", + "GameSpy/Chat/ModeHandler", + "GameSpy/Chat/PrivateHandler", + "GameSpy/Chat/NamesHandler", + "GameSpy/Chat/WhoIsHandler", + "GameSpy/Chat/PrivateHandler", + "GameSpy/Chat/PartHandler", + "GameSpy/Chat/QuitHandler"] + for m, route in zip(test_msg, test_api): + try: + print(route) + client.post(url=route, json=m) + except: + pass + + +if __name__ == "__main__": + test = RoomTest() + test.test_sdk() diff --git a/src/backends/tests/gamespy/game_status/__init__.py b/src/backends/tests/gamespy/game_status/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backends/tests/gamespy/game_status/handler_tests.py b/src/backends/tests/gamespy/game_status/handler_tests.py new file mode 100644 index 000000000..2434b6ae1 --- /dev/null +++ b/src/backends/tests/gamespy/game_status/handler_tests.py @@ -0,0 +1,29 @@ +import unittest + +from backends.protocols.gamespy.game_status.handlers import AuthGameHandler +from backends.protocols.gamespy.game_status.requests import AuthGameRequest + + +class HandlerTests(unittest.TestCase): + def test_auth_game(self): + raw = { + "raw_request": "\\auth\\\\gamename\\gmtest\\response\\b7f8b7f83dcc4427c35864c5d53c5fe5\\port\\2667\\id\\1\\final\\", + "request_dict": { + "auth": "", + "gamename": "gmtest", + "response": "b7f8b7f83dcc4427c35864c5d53c5fe5", + "port": "2667", + "id": "1", + }, + "local_id": 1, + "game_name": "gmtest", + "response": "b7f8b7f83dcc4427c35864c5d53c5fe5", + "port": 2667, + "client_ip": "172.19.0.5", + "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", + "client_port": 38996, + } + req = AuthGameRequest(**raw) + h = AuthGameHandler(req) + h.handle() + pass diff --git a/src/backends/tests/gamespy/natneg/__init__.py b/src/backends/tests/gamespy/natneg/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backends/tests/gamespy/natneg/handler_tests.py b/src/backends/tests/gamespy/natneg/handler_tests.py new file mode 100644 index 000000000..f48eccf01 --- /dev/null +++ b/src/backends/tests/gamespy/natneg/handler_tests.py @@ -0,0 +1,35 @@ +import unittest +from backends.protocols.gamespy.natneg.handlers import ConnectHandler, InitHandler, ReportHandler +from backends.protocols.gamespy.natneg.requests import InitRequest, ConnectRequest, ReportRequest +from backends.tests.utils import add_headers +import frontends.gamespy.protocols.natneg.contracts.requests as fnt + + +class HandlerTests(unittest.TestCase): + + @unittest.skip("") + def test_report(self): + req_dict = {"raw_request": "\\xfd\\xfc\u001efj\\xb2\u0004\r\u0000\u0000\u0002\\x9a\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0000\u0000\u0000gmtest\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", + "version": 4, "command_name": 13, "cookie": 666, "port_type": 0, "client_index": 0, "use_game_port": False, "is_nat_success": False, "nat_type": 0, "mapping_scheme": 0, "game_name": "gmtest", "client_ip": "172.19.0.5", "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", "client_port": 36229} + req = ReportRequest.model_validate(req_dict) + handler = ReportHandler(req) + handler.handle() + pass + + def test_connect(self): + raw = b'\xfd\xfc\x1efj\xb2\x03\x00\x00\x00\x03\t\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + r = fnt.ConnectRequest(raw) + data = add_headers(r) + request = ConnectRequest(**data) + handler = ConnectHandler(request) + handler.handle() + pass + + def test_init(self): + raw = b'\xfd\xfc\x1efj\xb2\x03\x00\x00\x00\x03\t\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + r = fnt.InitRequest(raw) + data = add_headers(r) + request = InitRequest(**data) + handler = InitHandler(request) + handler.handle() + pass diff --git a/src/backends/tests/gamespy/natneg/nat_detection_tests.py b/src/backends/tests/gamespy/natneg/nat_detection_tests.py new file mode 100644 index 000000000..c92d208d9 --- /dev/null +++ b/src/backends/tests/gamespy/natneg/nat_detection_tests.py @@ -0,0 +1,247 @@ +from datetime import datetime +import unittest + +from backends.library.database.pg_orm import InitPacketCaches +from backends.protocols.gamespy.natneg.helpers import NatProtocolHelper +from frontends.gamespy.protocols.natneg.aggregations.enums import ( + NatClientIndex, + NatPortType, + NatType, +) + + +class NatDetectionTests(unittest.TestCase): + def test_public_ip(self): + # Create a list of InitPacketCache instances + packet_caches: list[InitPacketCaches] = [ + InitPacketCaches( + port_type=NatPortType.GP, + client_index=NatClientIndex.GAME_CLIENT, + cookie=123, + version=3, + game_name="gmtest", + public_ip="10.0.0.1", + public_port=1, + private_ip="10.0.0.1", + private_port=0, + ), + InitPacketCaches( + port_type=NatPortType.NN1, + client_index=NatClientIndex.GAME_CLIENT, + cookie=123, + version=3, + game_name="gmtest", + public_ip="10.0.0.1", + public_port=2, + private_ip="10.0.0.1", + private_port=0, + ), + InitPacketCaches( + port_type=NatPortType.NN2, + client_index=NatClientIndex.GAME_CLIENT, + cookie=123, + version=3, + game_name="gmtest", + public_ip="10.0.0.1", + public_port=2, + private_ip="10.0.0.1", + private_port=2, + ), + InitPacketCaches( + port_type=NatPortType.NN3, + client_index=NatClientIndex.GAME_CLIENT, + cookie=123, + version=3, + game_name="gmtest", + public_ip="10.0.0.1", + public_port=2, + private_ip="10.0.0.1", + private_port=2, + ), + ] + + # Create an instance of NatInitInfo with the list of packet caches + init_info = NatProtocolHelper(packet_caches) + + # Determine NAT type + NatProtocolHelper._determine_nat_type_version4(init_info) + + # Assert that the NAT type is NoNat + self.assertEqual(init_info.nat_type, NatType.NO_NAT) + + def test_full_cone(self): + # Create a list of InitPacketCache instances + packet_caches: list[InitPacketCaches] = [ + InitPacketCaches( + port_type=NatPortType.GP, + client_index=NatClientIndex.GAME_CLIENT, + cookie=123, + version=3, + game_name="gmtest", + public_ip="10.0.0.1", + public_port=1, + private_ip="192.168.1.1", + private_port=0, + + ), + InitPacketCaches( + port_type=NatPortType.NN1, + client_index=NatClientIndex.GAME_CLIENT, + cookie=123, + version=3, + game_name="gmtest", + public_ip="10.0.0.1", + public_port=2, + private_ip="192.168.1.1", + private_port=0, + + ), + InitPacketCaches( + port_type=NatPortType.NN2, + client_index=NatClientIndex.GAME_CLIENT, + cookie=123, + version=3, + game_name="gmtest", + public_ip="10.0.0.1", + public_port=2, + private_ip="192.168.1.1", + private_port=2, + + ), + InitPacketCaches( + port_type=NatPortType.NN3, + client_index=NatClientIndex.GAME_CLIENT, + cookie=123, + version=3, + game_name="gmtest", + public_ip="10.0.0.1", + public_port=2, + private_ip="192.168.1.1", + private_port=2, + + ), + ] + + # Create an instance of NatInitInfo with the list of packet caches + init_info = NatProtocolHelper(packet_caches) + + # Determine NAT type + NatProtocolHelper._determine_nat_type_version4(init_info) + self.assertEqual(init_info.nat_type, NatType.FULL_CONE) + + # Test method + def test_symmetric(self): + # Create a list of InitPacketCaches instances + packet_caches = [ + InitPacketCaches( + port_type=NatPortType.GP, + client_index=NatClientIndex.GAME_CLIENT, + cookie=123, + version=3, + game_name="gmtest", + public_ip="10.0.0.1", + public_port=1, + private_ip="192.168.1.1", + private_port=1, + ), + InitPacketCaches( + port_type=NatPortType.NN1, + client_index=NatClientIndex.GAME_CLIENT, + cookie=123, + version=3, + game_name="gmtest", + public_ip="10.0.0.1", + public_port=2, + private_ip="192.168.1.1", + private_port=2, + ), + InitPacketCaches( + port_type=NatPortType.NN2, + client_index=NatClientIndex.GAME_CLIENT, + cookie=123, + version=3, + game_name="gmtest", + public_ip="10.0.0.1", + public_port=3, + private_ip="192.168.1.1", + private_port=2, + ), + InitPacketCaches( + port_type=NatPortType.NN3, + client_index=NatClientIndex.GAME_CLIENT, + cookie=123, + version=3, + game_name="gmtest", + public_ip="10.0.0.1", + public_port=4, + private_ip="192.168.1.1", + private_port=2, + ), + ] + + # Create an instance of NatInitInfo with the list of packet caches + init_info = NatProtocolHelper(packet_caches) + + # Determine NAT type + NatProtocolHelper._determine_nat_type_version4(init_info) + + # Assert the NAT type is symmetric + self.assertEqual(init_info.nat_type, NatType.SYMMETRIC) + + def test_sposirius_network(self): + # Create a list of InitPacketCaches instances + packet_caches = [ + InitPacketCaches( + port_type=NatPortType.GP, + client_index=NatClientIndex.GAME_CLIENT, + cookie=123, + version=3, + game_name="gmtest", + public_ip="91.52.105.210", + public_port=51520, + private_ip="192.168.0.60", + private_port=0, + ), + InitPacketCaches( + port_type=NatPortType.NN1, + client_index=NatClientIndex.GAME_CLIENT, + cookie=123, + version=3, + game_name="gmtest", + public_ip="91.52.105.210", + public_port=51521, + private_ip="192.168.0.60", + private_port=0, + ), + InitPacketCaches( + port_type=NatPortType.NN2, + client_index=NatClientIndex.GAME_CLIENT, + cookie=123, + version=3, + game_name="gmtest", + public_ip="91.52.105.210", + public_port=49832, + private_ip="192.168.0.60", + private_port=49832, + ), + InitPacketCaches( + port_type=NatPortType.NN3, + client_index=NatClientIndex.GAME_CLIENT, + cookie=123, + version=3, + game_name="gmtest", + public_ip="91.52.105.210", + public_port=49832, + private_ip="192.168.0.60", + private_port=49832, + ), + ] + + # Create an instance of NatInitInfo with the list of packet caches + init_info = NatProtocolHelper(packet_caches) + + # Determine NAT type + NatProtocolHelper._determine_nat_type_version4(init_info) + + # Assert the NAT type is symmetric + self.assertEqual(init_info.nat_type, NatType.SYMMETRIC) diff --git a/src/backends/tests/gamespy/precence_search_player/__init__.py b/src/backends/tests/gamespy/precence_search_player/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backends/tests/gamespy/precence_search_player/data_fetch_tests.py b/src/backends/tests/gamespy/precence_search_player/data_fetch_tests.py new file mode 100644 index 000000000..f9da44f32 --- /dev/null +++ b/src/backends/tests/gamespy/precence_search_player/data_fetch_tests.py @@ -0,0 +1,108 @@ +# the tests related to database operations +from unittest import TestCase +from backends.library.database.pg_orm import ENGINE, Profiles, Users +import backends.protocols.gamespy.presence_search_player.data as data +from sqlalchemy.orm import Session + + +class DataFetchTests(TestCase): + def test_verify_email(self) -> None: + with Session(ENGINE) as session: + result1 = data.verify_email("spyguy@unispy.net", session) + self.assertFalse(result1) + result2 = data.verify_email("spyguy@gamespy.com", session) + self.assertTrue(result2) + + def test_verify_email_and_password(self): + with Session(ENGINE) as session: + result1 = data.verify_email_and_password( + "spyguy@gamespy.com", "4a7d1ed414474e4033ac29ccb8653d91", session + ) + self.assertFalse(result1) + result2 = data.verify_email_and_password( + "spyguy@gamespy.com", "4a7d1ed414474e4033ac29ccb8653d9b", session + ) + self.assertTrue(result2) + + def test_get_profile_id(self): + with Session(ENGINE) as session: + result1 = data.get_profile_id( + "spyguy@gamespy.com", + "4a7d1ed414474e4033ac29ccb8653d9b", + "spyguy1", + 1, + session, + ) + self.assertIsNone(result1) + result2 = data.get_profile_id( + "spyguy@gamespy.com", + "4a7d1ed414474e4033ac29ccb8653d9b", + "spyguy", + 1, + session, + ) + self.assertIsNotNone(result2) + self.assertEqual(result2, 1) + + def test_get_users(self): + with Session(ENGINE) as session: + result1 = data.get_user("spyguy@gamespy.com", session) + self.assertIsNotNone(result1) + self.assertEqual(type(result1), Users) + result2 = data.get_user("spyguy_not_user@gamespy.com", session) + self.assertIsNone(result2) + + def test_get_profile(self): + with Session(ENGINE) as session: + result1 = data.get_profile(1, "spyguy", session) + self.assertEqual(type(result1), Profiles) + + result2 = data.get_profile(1, "spyguy_not_profile", session) + self.assertIsNone(result2) + + def test_get_sub_profile(self): + pass + + def test_get_nick_and_unique_nick_list(self): + with Session(ENGINE) as session: + result = data.get_nick_and_unique_nick_list( + "spyguy@gamespy.com", "4a7d1ed414474e4033ac29ccb8653d9b", 0, session + ) + self.assertIsInstance(result, list) + self.assertEqual(len(result), 1) + self.assertIsInstance(result[0], tuple) + + def test_get_matched_profile_info_list(self): + with Session(ENGINE) as session: + result = data.get_matched_profile_info_list([1], 0, session) + self.assertIsInstance(result, list) + self.assertNotEqual(len(result), 0) + + def test_get_matched_info_by_nick(self): + with Session(ENGINE) as session: + result = data.get_matched_info_by_nick("spyguy", session) + self.assertIsNotNone(result) + self.assertNotEqual(len(result), 0) + + def test_get_matched_info_by_email(self): + with Session(ENGINE) as session: + result = data.get_matched_info_by_email("spyguy@gamespy.com", session) + self.assertEqual(result[0]["nick"], "spyguy") + self.assertEqual(result[0]["profile_id"], 1) + + def test_is_uniquenick_exist(self): + with Session(ENGINE) as session: + result1 = data.is_uniquenick_exist("spyguy", 0, "gmtests", session) + self.assertTrue(result1) + + result2 = data.is_uniquenick_exist( + "spyguy_not_uniquenick", 0, "gmtests", session + ) + self.assertFalse(result2) + + def test_is_email_exist(self): + with Session(ENGINE) as session: + result1 = data.is_email_exist("spyguy@gamespy.com", session) + self.assertTrue(result1) + result2 = data.is_email_exist("spyguy@gamespy.net", session) + self.assertFalse(result2) diff --git a/src/backends/tests/gamespy/precence_search_player/handler_tests.py b/src/backends/tests/gamespy/precence_search_player/handler_tests.py new file mode 100644 index 000000000..1306f0456 --- /dev/null +++ b/src/backends/tests/gamespy/precence_search_player/handler_tests.py @@ -0,0 +1,85 @@ +# the total requests tests +import unittest +from backends.tests.utils import add_headers +import frontends.gamespy.protocols.presence_search_player.contracts.requests as psp +from frontends.tests.gamespy.presence_search_player.handler_tests import ( + NICKS, + SEARCH_1, + SEARCH_2, + SEARCH_3, + SEARCH_4, + CHECK1, + NEWUSER, + SEARCH_UNIQUENICK, + VALID, +) +import backends.protocols.gamespy.presence_search_player.requests as bkr +import backends.protocols.gamespy.presence_search_player.handlers as bkh + + +class HandlerTest(unittest.TestCase): + """ + test backend and server request compability + """ + + # region PCM + # region PSP + + def test_search(self): + for raw in [SEARCH_1, SEARCH_2, SEARCH_3, SEARCH_4]: + r = psp.SearchRequest(raw) + data = add_headers(r) + request = bkr.SearchRequest(**data) + handler = bkh.SearchHandler(request) + handler.handle() + pass + + def test_chenck(self): + r = psp.CheckRequest(CHECK1) + data = add_headers(r) + request = bkr.CheckRequest(**data) + handler = bkh.CheckHandler(request) + handler.handle() + pass + + def test_new_user(self): + r = psp.NewUserRequest(NEWUSER) + data = add_headers(r) + data["email"] = "xiaojiuwo1@gamespy.com" + data["nick"] = "xiaojiuwo1" + request = bkr.NewUserRequest(**data) + handler = bkh.NewUserHandler(request) + handler.handle() + pass + + def test_nick(self): + r = psp.NicksRequest(NICKS) + data = add_headers(r) + request = bkr.NicksRequest(**data) + handler = bkh.NicksHandler(request) + handler.handle() + pass + + def test_others_list(self): + # r = psp.OthersListRequest() + pass + + def test_others(self): + pass + + def test_search_unique(self): + r = psp.SearchUniqueRequest(SEARCH_UNIQUENICK) + data = add_headers(r) + request = bkr.SearchUniqueRequest(**data) + handler = bkh.SearchUniqueHandler(request) + handler.handle() + pass + + def test_valid(self): + r = psp.ValidRequest(VALID) + data = add_headers(r) + request = bkr.ValidRequest(**data) + handler = bkh.ValidHandler(request) + handler.handle() + self.assertTrue(handler._result.is_account_valid, True) + pass diff --git a/src/backends/tests/gamespy/presence_conection_manager/__init__.py b/src/backends/tests/gamespy/presence_conection_manager/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backends/tests/gamespy/presence_conection_manager/handler_tests.py b/src/backends/tests/gamespy/presence_conection_manager/handler_tests.py new file mode 100644 index 000000000..0f13886d3 --- /dev/null +++ b/src/backends/tests/gamespy/presence_conection_manager/handler_tests.py @@ -0,0 +1,147 @@ +import unittest +from backends.tests.utils import add_headers +import frontends.gamespy.protocols.presence_connection_manager.contracts.requests as pcm +import backends.protocols.gamespy.presence_connection_manager.requests as bkr +import backends.protocols.gamespy.presence_connection_manager.handlers as bkh +import responses +from frontends.tests.gamespy.presence_connection_manager.request_tests import ( + LOGIN_AUTH_TOKEN, + LOGIN_UNIQUE_NICK, + LOGIN_USER, +) + + +class HandlerTest(unittest.TestCase): + # region General + @responses.activate + def test_login_authtoken(self): + r = pcm.LoginRequest(LOGIN_AUTH_TOKEN) + data = add_headers(r) + request = bkr.LoginRequest(**data) + handler = bkh.LoginHandler(request) + handler.handle() + pass + + @responses.activate + def test_login_uniquenick(self): + r = pcm.LoginRequest(LOGIN_UNIQUE_NICK) + data = add_headers(r) + request = bkr.LoginRequest(**data) + handler = bkh.LoginHandler(request) + handler.handle() + pass + + @responses.activate + def test_login_user(self): + r = pcm.LoginRequest(LOGIN_USER) + data = add_headers(r) + request = bkr.LoginRequest(**data) + handler = bkh.LoginHandler(request) + handler.handle() + pass + + @unittest.skip("not implemented") + @responses.activate + def test_new_user(self): + raise NotImplementedError() + + @unittest.skip("not implemented") + @responses.activate + def test_logout(self): + raise NotImplementedError() + + # region Buddy + + @unittest.skip("not implemented") + @responses.activate + def test_buddy_list(self): + r = pcm.BuddyListRequest(profile_id=1, namespace_id=0) + data = add_headers(r) + request = bkr.BuddyListRequest(**data) + handler = bkh.BuddyListHandler(request) + handler.handle() + pass + + @unittest.skip("not implemented") + @responses.activate + def test_block_list(self): + r = pcm.BlockListRequest(profile_id=1, namespace_id=0) + data = add_headers(r) + request = bkr.BlockListRequest(**data) + handler = bkh.BlockListHandler(request) + handler.handle() + pass + + @unittest.skip("not implemented") + @responses.activate + def test_add_buddy(self): + # r = pcm.AddBuddyRequest() + raise NotImplementedError() + pass + + @unittest.skip("not implemented") + @responses.activate + def test_del_buddy(self): + raise NotImplementedError() + pass + + @unittest.skip("not implemented") + @responses.activate + def test_add_block(self): + raise NotImplementedError() + pass + + @unittest.skip("not implemented") + @responses.activate + def test_del_block(self): + raise NotImplementedError() + pass + + @unittest.skip("not implemented") + @responses.activate + def test_invite_to(self): + raise NotImplementedError() + pass + + @unittest.skip("not implemented") + @responses.activate + def test_status_info(self): + raise NotImplementedError() + pass + + @unittest.skip("not implemented") + @responses.activate + def test_statue(self): + raise NotImplementedError() + pass + + # region Profile + @unittest.skip("not implemented") + @responses.activate + def test_get_profile(self): + raise NotImplementedError() + + @unittest.skip("not implemented") + @responses.activate + def test_new_profile(self): + raise NotImplementedError() + + @unittest.skip("not implemented") + @responses.activate + def test_register_cdkey(self): + raise NotImplementedError() + + @unittest.skip("not implemented") + @responses.activate + def test_register_nick(self): + raise NotImplementedError() + + @unittest.skip("not implemented") + @responses.activate + def test_update_profile(self): + raise NotImplementedError() + + @unittest.skip("not implemented") + @responses.activate + def test_update_user_info(self): + raise NotImplementedError() diff --git a/src/backends/tests/gamespy/query_report/__init__.py b/src/backends/tests/gamespy/query_report/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backends/tests/gamespy/query_report/data_fetch_tests.py b/src/backends/tests/gamespy/query_report/data_fetch_tests.py new file mode 100644 index 000000000..1f572cee9 --- /dev/null +++ b/src/backends/tests/gamespy/query_report/data_fetch_tests.py @@ -0,0 +1,32 @@ +from datetime import datetime, timezone +import unittest + +from pydantic import ValidationError +from backends.library.database.pg_orm import ENGINE, ChatChannelCaches +import backends.protocols.gamespy.query_report.data as data +from sqlalchemy.orm import Session + + +class DataFetchTests(unittest.TestCase): + def test_get_peer_staging_channels(self): + cache = ChatChannelCaches( + channel_name="#GSP!unispy_test_game_name!*", + server_id="b6480a17-5e3d-4da0-aeec-c421620bff71", + game_name="unispy_test_game_name", + room_name="unispy_test_room_name", + group_id=0, + max_num_user=100, + update_time=datetime.now(timezone.utc), + ) + with Session(ENGINE) as session: + session.add(cache) + session.commit() + self.assertRaises( + ValidationError, + data.get_peer_staging_channels, + "unispy_test_game_name", + 0, + session, + ) + session.delete(cache) + session.commit() diff --git a/src/backends/tests/gamespy/query_report/handler_tests.py b/src/backends/tests/gamespy/query_report/handler_tests.py new file mode 100644 index 000000000..040db7317 --- /dev/null +++ b/src/backends/tests/gamespy/query_report/handler_tests.py @@ -0,0 +1,31 @@ +import unittest + +from backends.protocols.gamespy.query_report.handlers import HeartbeatHandler, AvaliableHandler, KeepAliveHandler +from backends.protocols.gamespy.query_report.requests import HeartBeatRequest, AvaliableRequest, KeepAliveRequest + + +class HandlerTests(unittest.IsolatedAsyncioTestCase): + def test_heartbeat(self): + request = {"server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", "raw_request": "\\u0003\\\\xe5\\\\xcfaZlocalip0\\u0000172.19.0.5\\u0000localport\\u000011111\\u0000natneg\\u00001\\u0000statechanged\\u00003\\u0000gamename\\u0000gmtest\\u0000hostname\\u0000GameSpy QR2 Sample\\u0000gamever\\u00002.00\\u0000hostport\\u000025000\\u0000mapname\\u0000gmtmap1\\u0000gametype\\u0000arena\\u0000numplayers\\u00005\\u0000numteams\\u00002\\u0000maxplayers\\u000032\\u0000gamemode\\u0000openplaying\\u0000teamplay\\u00001\\u0000fraglimit\\u00000\\u0000timelimit\\u000040\\u0000gravity\\u0000800\\u0000rankingon\\u00001\\u0000\\u0000\\u0000\\u0005player_\\u0000score_\\u0000deaths_\\u0000ping_\\u0000team_\\u0000time_\\u0000\\u0000Joe Player\\u000030\\u000012\\u0000411\\u00000\\u000010\\u0000L33t 0n3\\u00000\\u00006\\u0000233\\u00001\\u0000325\\u0000Raptor\\u000015\\u000025\\u000063\\u00001\\u0000462\\u0000Gr81\\u00000\\u000016\\u0000294\\u00000\\u0000870\\u0000Flubber\\u000017\\u000012\\u0000232\\u00001\\u0000384\\u0000\\u0000\\u0002team_t\\u0000score_t\\u0000avgping_t\\u0000\\u0000Red\\u0000294\\u0000357\\u0000Blue\\u0000498\\u0000454\\u0000", "client_ip": "172.19.0.5", "client_port": 11111, + "instant_key": "3855573338", "command_name": 3, "data": {"localip0": "172.19.0.5", "localport": "11111", "natneg": "1", "statechanged": "3", "gamename": "gmtest", "hostname": "GameSpy QR2 Sample", "gamever": "2.00", "hostport": "25000", "mapname": "gmtmap1", "gametype": "arena", "numplayers": "5", "numteams": "2", "maxplayers": "32", "gamemode": "openplaying", "teamplay": "1", "fraglimit": "0", "timelimit": "40", "gravity": "800", "rankingon": "1", "player_0": "Joe Player", "score_0": "30", "deaths_0": "12", "ping_0": "411", "team_0": "0", "time_0": "10", "player_1": "L33t 0n3", "score_1": "0", "deaths_1": "6", "ping_1": "233", "team_1": "1", "time_1": "325", "player_2": "Raptor", "score_2": "15", "deaths_2": "25", "ping_2": "63", "team_2": "1", "time_2": "462", "player_3": "Gr81", "score_3": "0", "deaths_3": "16", "ping_3": "294", "team_3": "0", "time_3": "870", "player_4": "Flubber", "score_4": "17", "deaths_4": "12", "ping_4": "232", "team_4": "1", "time_4": "384", "team_t0": "Red", "score_t0": "294", "avgping_t0": "357", "team_t1": "Blue", "score_t1": "498", "avgping_t1": "454"}, "status": 3, "group_id": None, "game_name": "gmtest"} + req = HeartBeatRequest(**request) + handler = HeartbeatHandler(req) + handler.handle() + handler.response + + def test_available(self): + request = {"raw_request": "\\t\\u0000\\u0000\\u0000\\u0000\\t\\u0000\\u0000\\u0000\\u0000gamespy\\u0000", "command_name": 9, + "instant_key": "0", "client_ip": "127.0.0.1", "server_id": "a8893d8a-664e-4302-bb55-41b3a9229bd1", "client_port": "1234"} + new_req = AvaliableRequest(**request) + handler = AvaliableHandler(new_req) + handler.handle() + pass + + @unittest.skip("game not found") + def test_keep_alive(self): + request = {"raw_request": "\bg\\xd4\\xcbl", "command_name": 8, "instant_key": "1741998956", + "client_ip": "172.19.0.4", "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", "client_port": 11111} + new_req = KeepAliveRequest(**request) + handler = KeepAliveHandler(new_req) + handler.handle() + self.assertIsNotNone(new_req.instant_key) diff --git a/src/backends/tests/gamespy/server_browser/__init__.py b/src/backends/tests/gamespy/server_browser/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backends/tests/gamespy/server_browser/data_fetch_tests.py b/src/backends/tests/gamespy/server_browser/data_fetch_tests.py new file mode 100644 index 000000000..8460236a0 --- /dev/null +++ b/src/backends/tests/gamespy/server_browser/data_fetch_tests.py @@ -0,0 +1,13 @@ +import unittest + + + +class DataFetchTests(unittest.TestCase): + def test_server_main_list(self): + pass + + def test_p2p_group_room_list(self): + pass + + def test_server_info(self): + pass diff --git a/src/backends/tests/gamespy/server_browser/filter_tests.py b/src/backends/tests/gamespy/server_browser/filter_tests.py new file mode 100644 index 000000000..9c1dfe2d6 --- /dev/null +++ b/src/backends/tests/gamespy/server_browser/filter_tests.py @@ -0,0 +1,71 @@ +# 导入 Interpreter +from asteval import Interpreter +import re + +if __name__ == "__main__": + # 步骤1:创建 Interpreter 实例 + aeval = Interpreter() + + # 步骤2:定义服务器数据字典列表 + server_data_list = [ + { + "natneg": "1", + "gamever": "2.00", + "gravity": 800, + "mapname": "gmtmap2", + "gamemode": "openplaying", + "gamename": "gmtest2", + "gametype": "arena", + "hostname": "Server 1", + "hostport": "25000", + "localip0": "172.19.0.4", + "numteams": 2, + "teamplay": 1, + "fraglimit": 0, + "localport": 11111, + "rankingon": 1, + "timelimit": 40, + "maxplayers": 32, + "numplayers": 8, + "statechanged": 1, + }, + { + "natneg": "1", + "gamever": "2.00", + "gravity": 600, + "mapname": "gmtmap2", + "gamemode": "openplaying", + "gamename": "gmtest2", + "gametype": "arena", + "hostname": "Server 2", + "hostport": "25000", + "localip0": "172.19.0.4", + "numteams": 2, + "teamplay": 1, + "fraglimit": 0, + "localport": 11111, + "rankingon": 1, + "timelimit": 40, + "maxplayers": 32, + "numplayers": 4, + "statechanged": 1, + } + ] + + # 步骤3:定义条件 + condition = "gravity > 700 and numplayers > 5 and gamemode == 'openplaying'" + + # 步骤4:提取条件中的键 + pattern = r'(\w+)\s*([<>!=]+)\s*([\'\"]?)(.*?)\3' + matches = re.findall(pattern, condition) + keys = [match[0] for match in matches] + print(f"提取的键: {keys}") + + # 步骤5:评估每个服务器数据字典的条件 + for server in server_data_list: + # 更新上下文:动态加载提取的键 + for key in keys: + if key in server: + aeval.symtable[key] = server[key] + result = aeval(condition) + print(f"服务器 {server['hostname']} (Gravity: {server['gravity']}, Players: {server['numplayers']}): {result}") diff --git a/src/backends/tests/gamespy/server_browser/handler_tests.py b/src/backends/tests/gamespy/server_browser/handler_tests.py new file mode 100644 index 000000000..17d0072f2 --- /dev/null +++ b/src/backends/tests/gamespy/server_browser/handler_tests.py @@ -0,0 +1,39 @@ +import unittest +from backends.protocols.gamespy.server_browser.handlers import ( + ServerInfoHandler, + ServerMainListHandler, +) +from backends.protocols.gamespy.server_browser.requests import ( + ServerInfoRequest, + ServerListRequest, +) +from backends.tests.utils import add_headers +import frontends.gamespy.protocols.server_browser.v2.contracts.requests as fnt + + +class HandlerTests(unittest.TestCase): + def test_server_main_list(self): + raw = b"\x00\x9a\x00\x01\x03\x8fU\x00\x00anno1701\x00anno1701\x00D:@o)Okhgroupid is null\x00\\hostname\\gamemode\\gamever\\gametype\\password\\mapname\\numplayers\\numaiplayers\\openslots\\gamevariant\x00\x00\x00\x00\x04" + r = fnt.ServerListRequest(raw) + data = add_headers(r) + request = ServerListRequest(**data) + handler = ServerMainListHandler(request) + handler.handle() + pass + + @unittest.skip("not implemented") + def test_p2p_group_room_list(self): + raise NotImplementedError() + + @unittest.skip("not implemented") + def test_server_network_info_list(self): + raise NotImplementedError() + + def test_server_info(self): + raw = b"\x00\t\x01\xc0\xa8z\xe2+g" + r = fnt.ServerInfoRequest(raw) + data = add_headers(r) + request = ServerInfoRequest(**data) + handler = ServerInfoHandler(request) + handler.handle() + pass diff --git a/src/backends/tests/gamespy/web/__init__.py b/src/backends/tests/gamespy/web/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backends/tests/gamespy/web/handler_tests.py b/src/backends/tests/gamespy/web/handler_tests.py new file mode 100644 index 000000000..ddefa0ff9 --- /dev/null +++ b/src/backends/tests/gamespy/web/handler_tests.py @@ -0,0 +1,27 @@ +import unittest + +from backends.protocols.gamespy.web_services.handlers import LoginRemoteAuthHandler +from backends.protocols.gamespy.web_services.requests import LoginRemoteAuthRequest +from frontends.gamespy.protocols.web_services.modules.auth.exceptions.general import AuthException + + +class HandlerTests(unittest.TestCase): + def test_sdk_login_remote_auth(self): + with self.assertRaises(AuthException) as context: + raw = {"raw_request": "1000GMTy13lsJmiY7L19ojyN3XTM08ll0C4EWWijwmJyq3ttiZmoDUQJ0OSnar9nQCu5MpOGvi4Z0EcC2uNaS4yKrUA+h+tTDDoJHF7ZjoWKOTj00yNOEdzWyG08cKdVQwFRkF+h8oG/Jd+Ik3sWviXq/+5bhZQ7iXxTbbDwNL6Lagp/pLZ9czLnYPhY7VEcoQlx9oOLH8c.DLe", + "version": 1, "partner_code": 0, "namespace_id": 0, "auth_token": "GMTy13lsJmiY7L19ojyN3XTM08ll0C4EWWijwmJyq3ttiZmoDUQJ0OSnar9nQCu5MpOGvi4Z0EcC2uNaS4yKrUA+h+tTDDoJHF7ZjoWKOTj00yNOEdzWyG08cKdVQwFRkF+h8oG/Jd+Ik3sWviXq/+5bhZQ7iXxTbbDwNL6Lagp/pLZ9czLnYPhY7VEcoQlx9oO", "challenge": "LH8c.DLe", "game_id": 0, "client_ip": "172.19.0.4", "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", "client_port": 57502} + request = LoginRemoteAuthRequest.model_validate(raw) + handler = LoginRemoteAuthHandler(request) + handler.handle() + handler.response + + def test_sdk_login_remote_auth_fake_data(self): + raw = {"raw_request": "", + "version": 1, "partner_code": 0, "namespace_id": 0, "auth_token": "example_auth", "challenge": "LH8c.DLe", "game_id": 0, "client_ip": "172.19.0.4", "server_id": "950b7638-a90d-469b-ac1f-861e63c8c613", "client_port": 57502} + request = LoginRemoteAuthRequest.model_validate(raw) + handler = LoginRemoteAuthHandler(request) + handler.handle() + handler.response + + def test_sdk_login_uniquenick(self): + raw = {} diff --git a/src/backends/tests/http_tests/chat.http b/src/backends/tests/http_tests/chat.http new file mode 100644 index 000000000..e69de29bb diff --git a/src/backends/tests/http_tests/game_stats.http b/src/backends/tests/http_tests/game_stats.http new file mode 100644 index 000000000..e69de29bb diff --git a/src/backends/tests/http_tests/natneg.http b/src/backends/tests/http_tests/natneg.http new file mode 100644 index 000000000..e69de29bb diff --git a/src/backends/tests/http_tests/presence_connection_manager.http b/src/backends/tests/http_tests/presence_connection_manager.http new file mode 100644 index 000000000..e69de29bb diff --git a/src/backends/tests/http_tests/presence_search_player.http b/src/backends/tests/http_tests/presence_search_player.http new file mode 100644 index 000000000..e69de29bb diff --git a/src/backends/tests/http_tests/query_report.http b/src/backends/tests/http_tests/query_report.http new file mode 100644 index 000000000..e69de29bb diff --git a/src/backends/tests/http_tests/server_browser.http b/src/backends/tests/http_tests/server_browser.http new file mode 100644 index 000000000..e69de29bb diff --git a/src/backends/tests/http_tests/web_services.http b/src/backends/tests/http_tests/web_services.http new file mode 100644 index 000000000..e69de29bb diff --git a/src/backends/tests/utils.py b/src/backends/tests/utils.py new file mode 100644 index 000000000..629210740 --- /dev/null +++ b/src/backends/tests/utils.py @@ -0,0 +1,13 @@ +from frontends.gamespy.library.abstractions.contracts import RequestBase + + +def add_headers(request: RequestBase) -> dict: + request.parse() + if isinstance(request.raw_request, bytes): + request.raw_request = request.raw_request.decode( + "ascii", "backslashreplace") + data = request.to_dict() + data["client_ip"] = "192.168.0.1" + data["server_id"] = "950b7638-a90d-469b-ac1f-861e63c8c613" + data["client_port"] = 1234 + return data diff --git a/src/backends/urls.py b/src/backends/urls.py new file mode 100644 index 000000000..1a1de63c7 --- /dev/null +++ b/src/backends/urls.py @@ -0,0 +1,10 @@ +PRESENCE_CONNECTION_MANAGER = "/GameSpy/PresenceConnectionManager" +PRESENCE_SEARCH_PLAYER = "/GameSpy/PresenceSearchPlayer" +SERVER_BROWSER_V1 = "/GameSpy/ServerBrowserV1" +SERVER_BROWSER_V2 = "/GameSpy/ServerBrowserV2" +QUERY_REPORT = "/GameSpy/QueryReport" +NATNEG = "/GameSpy/NatNegotiation" +GAMESTATUS = "/GameSpy/GameStatus" +CHAT = "/GameSpy/Chat" +WEB_SERVICES = "/GameSpy/WebServices" +GAME_TRAFFIC_RELAY = "/GameSpy/GameTrafficRelay" diff --git a/src/frontends/__init__.py b/src/frontends/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/app.py b/src/frontends/app.py new file mode 100644 index 000000000..cadc6a811 --- /dev/null +++ b/src/frontends/app.py @@ -0,0 +1,32 @@ + + +from frontends.gamespy.library.extentions.debug_helper import DebugHelper + + +if __name__ == "__main__": + from frontends.gamespy.protocols.chat.applications.server_launcher import Service as chat + from frontends.gamespy.protocols.game_status.applications.server_launcher import Service as gs + from frontends.gamespy.protocols.game_traffic_relay.applications.server_launcher import Service as gtr + from frontends.gamespy.protocols.natneg.applications.server_launcher import Service as nn + from frontends.gamespy.protocols.presence_connection_manager.applications.server_launcher import Service as pcm + from frontends.gamespy.protocols.presence_search_player.applications.server_launcher import Service as psp + from frontends.gamespy.protocols.query_report.applications.server_launcher import Service as qr + from frontends.gamespy.protocols.server_browser.applications.server_launcher import Service as sb + from frontends.gamespy.protocols.web_services.applications.server_launcher import Service as web + + from frontends.gamespy.library.abstractions.server_launcher import ServicesFactory + launchers = [ + chat(), + gs(), + gtr(), + nn(), + pcm(), + psp(), + qr(), + sb(), + web() + ] + + factory = ServicesFactory(launchers) + helper = DebugHelper("./frontends", factory) + helper.start() diff --git a/src/frontends/gamespy/__init__.py b/src/frontends/gamespy/__init__.py new file mode 100644 index 000000000..48dc09b0d --- /dev/null +++ b/src/frontends/gamespy/__init__.py @@ -0,0 +1,2 @@ +# from .library.exceptions.general import UniSpyException +# from .protocols.natneg import NatClientIndex diff --git a/src/frontends/gamespy/library/abstractions/__init__.py b/src/frontends/gamespy/library/abstractions/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/gamespy/library/abstractions/brocker.py b/src/frontends/gamespy/library/abstractions/brocker.py new file mode 100644 index 000000000..cecac8ec3 --- /dev/null +++ b/src/frontends/gamespy/library/abstractions/brocker.py @@ -0,0 +1,44 @@ +import abc +from threading import Thread +from typing import final, Callable + + +class BrockerBase: + _subscriber: object + is_started: bool = False + _name: str + _call_back_func: Callable | None + """ + brocker subscribe name + """ + + def __init__(self, name: str, url: str, call_back_func: Callable | None) -> None: + assert isinstance(name, str) + + self._name = name + self.url = url + if call_back_func is not None: + assert callable(call_back_func) + self._call_back_func = call_back_func + + @abc.abstractmethod + def subscribe(self): + """ + define the brocker event binding + """ + pass + + @final + def receive_message(self, message: str): + assert isinstance(message, str) + if self._call_back_func is None: + return + self._call_back_func(message) + + @abc.abstractmethod + def publish_message(self, message: str): + assert isinstance(message, str) + + @abc.abstractmethod + def unsubscribe(self): + pass diff --git a/src/frontends/gamespy/library/abstractions/client.py b/src/frontends/gamespy/library/abstractions/client.py new file mode 100644 index 000000000..72b901c86 --- /dev/null +++ b/src/frontends/gamespy/library/abstractions/client.py @@ -0,0 +1,156 @@ +from frontends.gamespy.library.encryption.encoding import Encoding +from frontends.gamespy.library.exceptions.general import UniSpyException +from frontends.gamespy.library.log.log_manager import LogWriter +from frontends.gamespy.library.configs import ServerConfig +import threading +from typing import TYPE_CHECKING, Optional + +if TYPE_CHECKING: + from frontends.gamespy.library.abstractions.connections import ConnectionBase + from frontends.gamespy.library.abstractions.handler import CmdHandlerBase + from frontends.gamespy.library.abstractions.switcher import SwitcherBase + from frontends.gamespy.library.abstractions.enctypt_base import EncryptBase + from frontends.gamespy.library.abstractions.contracts import ResponseBase + from frontends.gamespy.library.abstractions.client import ClientInfoBase + + +class ClientInfoBase: + pass + + +class ClientBase: + server_config: ServerConfig + connection: "ConnectionBase" + logger: LogWriter + crypto: Optional["EncryptBase"] + info: "ClientInfoBase" + is_log_raw: bool + # class static property + pool: dict[str, "ClientBase"] = {} + + """ + Note: initialize in child class as class static member + """ + + def __init__( + self, + connection: "ConnectionBase", + server_config: ServerConfig, + logger: LogWriter, + ): + assert isinstance(server_config, ServerConfig) + assert isinstance(logger, LogWriter) + from frontends.gamespy.library.abstractions.connections import ConnectionBase + + assert issubclass(type(connection), ConnectionBase) + self.server_config = server_config + self.connection = connection + self.logger = logger + self.crypto = None + self.is_log_raw = False + self._log_prefix = f"[{self.connection.ip_endpoint}]" + + def on_connected(self) -> None: + lock = threading.Lock() + with lock: + ClientBase.pool[self.connection.ip_endpoint] = self + self.log_debug("client connected") + + def on_disconnected(self) -> None: + lock = threading.Lock() + with lock: + del ClientBase.pool[self.connection.ip_endpoint] + self.log_debug("client disconnected") + + def _create_switcher(self, buffer: bytes) -> "SwitcherBase": # type: ignore + """ + virtual method helps verify buffer type + """ + assert isinstance(buffer, bytes) or isinstance(buffer, str) + + def on_received(self, buffer: bytes) -> None: + if not isinstance(buffer, bytes): + raise UniSpyException("buffer type is invalid") + + if self.crypto is not None: + buffer = self.crypto.decrypt(buffer) + self.log_network_receving(buffer) + switcher = self._create_switcher(buffer) + switcher.handle() + + def decrypt_message(self, buffer: bytes) -> bytes: + if self.crypto is not None: + return self.crypto.decrypt(buffer) + else: + return buffer + + def send(self, response: "ResponseBase") -> None: + from frontends.gamespy.library.abstractions.contracts import ResponseBase + assert response is not None + assert issubclass(type(response), ResponseBase) + response.build() + sending_buffer = response.sending_buffer + if isinstance(sending_buffer, str): + buffer: bytes = Encoding.get_bytes(sending_buffer) + elif isinstance(sending_buffer, bytes): + buffer = sending_buffer + else: + raise UniSpyException("not supported buffer type") + + if self.crypto is not None: + buffer = self.crypto.encrypt(buffer) + + self.connection.send(buffer) + + self.log_network_sending(buffer) + + def log_debug(self, message: str) -> None: + self.logger.debug(f"{self._log_prefix}: {message}") + + def log_info(self, message: str) -> None: + self.logger.info(f"{self._log_prefix}: {message}") + + def log_warn(self, message: str) -> None: + self.logger.warn(f"{self._log_prefix}: {message}") + + def log_error(self, message: str) -> None: + self.logger.error(f"{self._log_prefix}: {message}") + + def log_network_sending(self, data: object) -> None: + self.logger.info(f"{self._log_prefix} [send]: {data}") + + def log_network_broadcast(self, data: object) -> None: + self.logger.info(f"{self._log_prefix} [cast]: {data}") + + def log_network_receving(self, data: object) -> None: + self.logger.info(f"{self._log_prefix} [recv]: {data}") + + def log_network_upload(self, data: object) -> None: + self.logger.info(f"{self._log_prefix} [upload]: {data}") + + def log_network_fetch(self, data: object) -> None: + self.logger.info(f"{self._log_prefix} [fetch]: {data}") + + def log_current_class(self, object: "CmdHandlerBase") -> None: + self.logger.debug( + f"{self._log_prefix} [=>] <{object.__class__.__name__}>") + + +class EasyTimer: + def __init__(self, interval, refresh_interval) -> None: + self.interval = interval + self.refresh_interval = refresh_interval + self.is_expired = False + + def elapsed(self, s, e) -> None: + print() + pass + + def start(self) -> None: + pass + + def refresh_last_active_time(self) -> None: + pass + + def dispose(self) -> None: + pass diff --git a/src/frontends/gamespy/library/abstractions/connections.py b/src/frontends/gamespy/library/abstractions/connections.py new file mode 100644 index 000000000..0b002afb2 --- /dev/null +++ b/src/frontends/gamespy/library/abstractions/connections.py @@ -0,0 +1,103 @@ +import abc +import socketserver +import threading +from frontends.gamespy.library.abstractions.client import ClientBase + +from frontends.gamespy.library.log.log_manager import LogWriter +from frontends.gamespy.library.configs import ServerConfig + + +class ConnectionBase: + remote_ip: str + remote_port: int + _is_started: bool + config: ServerConfig + t_client: type[ClientBase] + logger: LogWriter + handler: socketserver.BaseRequestHandler + _client: ClientBase + ip_endpoint: str + """ + : string + """ + + def __init__( + self, + handler: socketserver.BaseRequestHandler, + config: ServerConfig, + t_client: type[ClientBase], + logger: LogWriter, + ) -> None: + super().__init__() + assert isinstance(config, ServerConfig) + self.handler = handler + self.remote_ip = handler.client_address[0] + self.remote_port = int(handler.client_address[1]) + self.ip_endpoint = f"{self.remote_ip}:{self.remote_port}" + self.config = config + self.t_client = t_client + self.logger = logger + self._client = self.t_client(self, self.config, self.logger) + self._is_started = False + + def on_received(self, data: bytes) -> None: + self._client.on_received(data) + + @abc.abstractmethod + def send(self, data: bytes) -> None: + assert isinstance(data, bytes) + if not self._is_started: + raise Exception("Server is not running.") + assert isinstance(data, bytes) + + +class UcpConnectionBase(ConnectionBase): + pass + + +class TcpConnectionBase(ConnectionBase): + @abc.abstractmethod + def on_connected(self): + pass + + @abc.abstractmethod + def on_disconnected(self): + pass + + @abc.abstractmethod + def disconnect(self): + pass + + +class HttpConnectionBase(TcpConnectionBase): + pass + + +class NetworkServerBase: + _config: ServerConfig + _client_cls: type[ClientBase] + _logger: LogWriter + _server: socketserver.BaseServer + + def __init__( + self, config: ServerConfig, t_client: type[ClientBase], logger: LogWriter + ) -> None: + assert isinstance(config, ServerConfig) + assert issubclass(t_client, ClientBase) + # assert isinstance(logger, LogWriter) + self._config = config + self._client_cls = t_client + self._logger = logger + + def start(self): + """ + server non-blocking start + """ + thread = threading.Thread(target=self._server.serve_forever) + thread.start() + + def __del__(self): + self._server.shutdown() + + def stop(self): + self.__del__() diff --git a/src/frontends/gamespy/library/abstractions/contracts.py b/src/frontends/gamespy/library/abstractions/contracts.py new file mode 100644 index 000000000..717e1372e --- /dev/null +++ b/src/frontends/gamespy/library/abstractions/contracts.py @@ -0,0 +1,56 @@ +import abc + +from pydantic import BaseModel + + +class RequestBase: + command_name: object + raw_request: object + + def __init__(self, raw_request: object) -> None: + """ + raw_request is for gamespy protocol\n + json_dict is for restapi deserialization + """ + super().__init__() + if raw_request is None: + raise Exception("raw_request should not be None") + + if raw_request is not None: + if (not isinstance(raw_request, bytes)) and ( + not isinstance(raw_request, str) + ): + raise Exception("Unsupported raw_request type") + self.raw_request = raw_request + return + # self.command_name = None + # self.raw_request = None + + def parse(self) -> None: + pass + + def to_dict(self) -> dict: + """ + create a json serializable dict of this class + """ + result = {} + for key, value in self.__dict__.items(): + if key[0] != "_": + result[key] = value + return result + + +class ResultBase(BaseModel): + pass + + +class ResponseBase: + sending_buffer: object + _result: ResultBase + def __init__(self, result: ResultBase) -> None: + assert issubclass(type(result), ResultBase) + self._result = result + + @abc.abstractmethod + def build(self) -> None: + pass diff --git a/src/frontends/gamespy/library/abstractions/enctypt_base.py b/src/frontends/gamespy/library/abstractions/enctypt_base.py new file mode 100644 index 000000000..267234a20 --- /dev/null +++ b/src/frontends/gamespy/library/abstractions/enctypt_base.py @@ -0,0 +1,107 @@ +from abc import abstractmethod + +class Byte: + value: int + + def __init__(self, value): + if value > 255: + raise ValueError("byte should be in 0 to 256") + self.value = value + + def _clamp(self, value) -> int: + """clamp value in 0 to 255""" + return value % 256 + + def __add__(self, other): + if not isinstance(other, Byte): + raise TypeError("operation must on Byte object") + new = self._clamp(self.value + other.value) + return Byte(new) + + def __sub__(self, other): + if not isinstance(other, Byte): + raise TypeError("operation must on Byte object") + new = self._clamp(self.value - other.value) + return Byte(new) + + def __mul__(self, other): + if not isinstance(other, Byte): + raise TypeError("operation must on Byte object") + new = self._clamp(self.value * other.value) + return Byte(new) + + def __truediv__(self, other): + if not isinstance(other, Byte): + raise TypeError("operation must on Byte object") + if other.value == 0: + raise ValueError("Cannot divide by zero") + new = self._clamp(self.value // other.value) + return Byte(new) + + def __xor__(self, other): + if not isinstance(other, Byte): + raise TypeError("operation must on Byte object") + new = self._clamp(self.value ^ other.value) + return Byte(new) + + def __lt__(self, other): + if not isinstance(other, Byte): + raise TypeError("operation must be on Byte object") + return self.value < other.value + + def __le__(self, other): + if not isinstance(other, Byte): + raise TypeError("operation must be on Byte object") + return self.value <= other.value + + def __gt__(self, other): + if not isinstance(other, Byte): + raise TypeError("operation must be on Byte object") + return self.value > other.value + + def __ge__(self, other): + if not isinstance(other, Byte): + raise TypeError("operation must be on Byte object") + return self.value >= other.value + + def __eq__(self, other): + if not isinstance(other, Byte): + raise TypeError("operation must be on Byte object") + return self.value == other.value + + def __lshift__(self, other): + """Perform in-place left shift operation.""" + if not isinstance(other, Byte): + raise TypeError("operation must be on Byte object") + if other < Byte(0): + raise ValueError("Shift amount must be non-negative") + return Byte(self.value << other.value) + + def __and__(self, other): + if not isinstance(other, Byte): + raise TypeError("operation must be on Byte object") + return Byte(self.value & other.value) + + def __mod__(self, other): + if not isinstance(other, Byte): + raise TypeError("operation must be on Byte object") + return Byte(self.value % other.value) + + def __repr__(self): + return f"Byte({self.value})" + + @staticmethod + def from_bytes(data: bytes | bytearray): + temp = [] + for d in data: + temp.append(Byte(d)) + return temp + +class EncryptBase: + @abstractmethod + def encrypt(self, data: bytes) -> bytes: + assert isinstance(data, bytes) + + @abstractmethod + def decrypt(self, data: bytes) -> bytes: + assert isinstance(data, bytes) diff --git a/src/frontends/gamespy/library/abstractions/handler.py b/src/frontends/gamespy/library/abstractions/handler.py new file mode 100644 index 000000000..ec479681e --- /dev/null +++ b/src/frontends/gamespy/library/abstractions/handler.py @@ -0,0 +1,224 @@ +import json +from frontends.gamespy.library.abstractions.client import ClientBase +from frontends.gamespy.library.exceptions.general import UniSpyException +from typing import final +import requests + +from frontends.gamespy.library.configs import CONFIG + +# if TYPE_CHECKING: +from frontends.gamespy.library.abstractions.contracts import ( + RequestBase, + ResultBase, + ResponseBase, +) +from frontends.gamespy.library.extentions.encoding import UniSpyJsonEncoder +from frontends.gamespy.library.log.log_manager import GLOBAL_LOGGER + + +class CmdHandlerBase: + _client: "ClientBase" + _request: "RequestBase" + _result: "ResultBase | None" + """ + the result instance, create by annotation in child class + """ + _response: "ResponseBase | None" + """ + the response instance, create by annotation in child class + """ + _result_cls: type["ResultBase"] | None + """ + the result class type, create by annotation in child class + """ + _response_cls: type["ResponseBase"] | None + """ + the response class type, create by annotation in child class + """ + _debug: bool = False + """ + whether is in debug mode, if in debug mode exception will raise from handler + """ + _is_uploading: bool + _is_fetching: bool + """ + this is auto assigned variable + """ + + def __init__(self, client: "ClientBase", request: "RequestBase") -> None: + assert issubclass(type(client), ClientBase) + assert issubclass(type(request), RequestBase) + self._client = client + self._request = request + # create class type by annotation + self._get_property_types() + self._result = None + self._response = None + self._is_uploading = True + if self._result_cls is None: + self._is_fetching = False + else: + self._is_fetching = True + + def _get_property_types(self): + if "_result" in self.__class__.__annotations__: + self._result_cls = self.__class__.__annotations__['_result'] + if self._result_cls == ResultBase: + self._result_cls = None + else: + self._result_cls = None + if "_response" in self.__class__.__annotations__: + self._response_cls = self.__class__.__annotations__['_response'] + if self._response_cls == ResponseBase: + self._response_cls = None + else: + self._response_cls = None + + def handle(self) -> None: + try: + # we first log this class + self._log_current_class() + # then we handle it + self._request_check() + if CONFIG.unittest.is_collect_request: + return + self._data_operate() + self._response_construct() + if self._response is None: + return + self._response_send() + except Exception as ex: + self._handle_exception(ex) + + def _request_check(self) -> None: + """ + raw request is nessesary param + """ + # if there is gamespy raw request we convert it to unispy request + self._request.parse() + + def _data_operate(self) -> None: + """ + virtual function, can be override + """ + if self._is_uploading: + self._prepare_data() + self._upload_data() + if self._is_fetching: + self._fetch_data() + + def _prepare_data(self): + self._temp_data = self._request.to_dict() + if "server_id" in self._temp_data: + raise UniSpyException("server_id name collision in dict") + if "client_ip" in self._temp_data: + raise UniSpyException("client_ip name collision in dict") + if "client_port" in self._temp_data: + raise UniSpyException("client_port name collision in dict") + # add the server info to json request dict + self._temp_data["client_ip"] = self._client.connection.remote_ip + self._temp_data["server_id"] = self._client.server_config.server_id + self._temp_data["client_port"] = self._client.connection.remote_port + + def _get_url(self) -> str: + url = f"{CONFIG.backend.url}/GameSpy/{self._client.server_config.server_name}/{ + self.__class__.__name__ + }" + return url + + @final + def _upload_data(self): + """ + whether need send data to backend + if child class do not require fetch, overide this function to do nothing + """ + self._url = self._get_url() + json_str = json.dumps( + self._temp_data, cls=UniSpyJsonEncoder, ensure_ascii=False + ) + self._client.log_network_upload(f"[{self._url}] {json_str}") + try: + response = requests.post( + self._url, data=json_str, headers={ + "Content-Type": "application/json"} + ) + except requests.exceptions.ConnectionError: + if CONFIG.unittest.is_raise_except: + raise UniSpyException( + f"backends api for {[self.__class__.__name__]} is not mocked" + ) + else: + raise UniSpyException("backends is not avaliable") + + # todo http code to determine object type + if response.status_code in [200, 450, 500]: + self._http_result = response.json() + else: + raise UniSpyException( + f"failed to upload data to backends. reason: {response.text}" + ) + + match response.status_code: + case 200: + pass + case 450: + self._handle_upload_error() + case 500: + self._handle_upload_error() + case _: + raise UniSpyException( + f"failed to upload data to backends. reason: {response.text}" + ) + + def _handle_upload_error(self): + """ + handle the error message response from backend + """ + # we raise the error as UniSpyException + raise UniSpyException(self._http_result["message"]) + + @final + def _fetch_data(self): + """ + whether need get data from backend. + if child class do not require feach, overide this function to do nothing + """ + if self._result_cls is None: + raise UniSpyException( + "_result_cls can not be null when feach data.") + + assert issubclass(self._result_cls, ResultBase) + self._client.log_network_fetch(f"[{self._url}] {self._http_result}") + if "result" not in self._http_result: + raise UniSpyException("result can not be empty when feach data") + self._result = self._result_cls(**self._http_result["result"]) + + def _response_construct(self) -> None: + """construct response here in specific child class""" + if self._response_cls is not None: + if self._result is None: + raise UniSpyException( + "result instance is required for response construction") + self._response = self._response_cls(result=self._result) + + def _response_send(self) -> None: + """ + virtual function, can be override + Send response back to client, this is a virtual function which can be override only by child class + """ + assert isinstance(self._response, ResponseBase) + self._client.send(self._response) + + def _handle_exception(self, ex: Exception) -> None: + """ + override in child class if there are different exception handling behavior + """ + UniSpyException.handle_exception(ex, self._client) + + @final + def _log_current_class(self) -> None: + if self._client is None: + # todo + GLOBAL_LOGGER.debug(f"=> <{self.__class__.__name__}>") + else: + self._client.log_current_class(self) diff --git a/src/frontends/gamespy/library/abstractions/redis_objects.py b/src/frontends/gamespy/library/abstractions/redis_objects.py new file mode 100644 index 000000000..93481107a --- /dev/null +++ b/src/frontends/gamespy/library/abstractions/redis_objects.py @@ -0,0 +1,262 @@ +# from dataclasses import dataclass, field +# from datetime import datetime +# # import threading +# import asyncio +# + +# from redis import Redis + + +# from frontends.gamespy.library.exceptions.general import UniSpyException + +# import json + + +# class RedisJsonEncoder(json.JSONEncoder): +# def default(self, obj): +# if isinstance(obj, datetime): +# return str(obj) + + +# class RedisJsonDecoder(json.JSONDecoder): +# pass + + +# @dataclass +# class RedisQuery: +# key: str +# value: object + + +# @dataclass +# class RedisKey: +# type: "type" +# name: str + +# def __eq__(self, value: object) -> RedisQuery: +# if self.type is not type(value): +# raise ValueError("The value type is not equal to redis key type") +# # return (self.name, value) +# return RedisQuery(self.name, value) + +# def __ne__(self, value: object) -> bool: +# raise UniSpyException( +# "Redis key attribute do not have this method") + +# def __add__(self, other): +# raise UniSpyException( +# "Redis key attribute do not have this method") + +# def __lt__(self, other): +# raise UniSpyException( +# "Redis key attribute do not have this method") + +# def __gt__(self, other): +# raise UniSpyException( +# "Redis key attribute do not have this method") + +# def __ge__(self, other): +# raise UniSpyException( +# "Redis key attribute do not have this method") + +# def __le__(self, other): +# raise UniSpyException( +# "Redis key attribute do not have this method") + + +# class RedisKeyValueObject: +# _DELIMETER = ":" +# _VALID_TYPE = [int, float, str, datetime] +# """ +# The base class of redis keyvalue object + +# ------- +# create the redis key with RedisKey to identity that is a redis key +# """ +# _database: int +# """ +# Init _database in child class __post_init__(self) +# """ +# _redis_client: Redis +# _expire_time: int +# """ +# expire time seconds +# """ + +# def __post_init__(self): +# if not hasattr(self, "_database"): +# raise UniSpyException( +# "You have to initailize _database in child class") +# self._get_all_redis_key() + +# @property +# def _keys(self): +# keys = [] +# for k, v in type(self).__dict__.items(): +# if type(v) is RedisKey: +# keys.append(k) +# return keys + +# def _get_all_redis_key(self): +# for k, v in type(self).__dict__["__annotations__"].items(): +# if v not in RedisKeyValueObject._VALID_TYPE: +# raise UniSpyException(f"type: {v} is not allowed") +# setattr(type(self), k, RedisKey(type=v, name=k)) + +# def to_json_str(self) -> str: +# """ +# convert object to RedisKeyValueObjectjson serializable dict +# """ +# import json +# try: +# output_dict = json.dumps(self) +# except: +# raise UniSpyException("all value must be python basic type") +# return output_dict + +# def build_full_key(self) -> str: +# """ +# key format: +# key1 = value1; key2 = value2; key3=value3 +# every property mus__init__t have +# """ +# full_key = f"db={self._database}:" + +# for index in range(len(self._keys)): +# key = self._keys[index] +# if key not in self.__dict__: +# raise ValueError( +# f"key: {key} is not initialized, in order to build full key every key must have value") +# value = self.__dict__[key] +# if value is None: +# # fmt: r.keys('*')off +# raise UniSpyException( +# f"key: {key} can not be none, in order to build full key every key must have value") +# # fmt: on +# full_key += f"{key}={value}" +# if index != len(self._keys)-1: +# full_key += RedisKeyValueObject._DELIMETER +# return full_key + +# def build_search_key(self) -> str: +# """ +# get keys using to search +# key format: +# key1=value1;key2=*;key3=value3 +# """ +# search_key = f"db={self._database}:" +# for index in range(len(self._keys)): +# key = self._keys[index] +# if key not in self.__dict__: +# search_key += f"{key}=*" + +# if self.__dict__[key] is None: +# search_key += f"{key}=*" +# else: +# value = self.__dict__[key] +# search_key += f"{key}={value}" + +# if index != len(self._keys)-1: +# search_key += RedisKeyValueObject._DELIMETER +# return search_key + +# def _build_search_object(self, query_dict: dict[str, object]) -> "RedisKeyValueObject": +# param_dict = {} +# for k in self._keys: +# if k not in query_dict: +# param_dict[k] = None +# else: +# param_dict[k] = query_dict[k] +# q_obj = type(self)(**param_dict) +# return q_obj + +# def is_all_instance(self, data: list): +# for d in data: +# if not isinstance(d, RedisQuery): +# raise UniSpyException( +# "The queries list contain non RedisQuery object") + +# self._database = 0 + +# def convert_query_to_dict(self, queries: list[RedisQuery]) -> dict[str, object]: +# query_dict = {} +# for q in queries: +# if q.key not in query_dict.keys(): +# query_dict[q.key] = q.value +# else: +# raise UniSpyException( +# f"The query: {q.key} is duplicated, check your query syntax") + +# return query_dict + +# def query(self, queries: list[RedisQuery]) -> list["RedisKeyValueObject"]: +# self.is_all_instance(queries) +# q_dict = self.convert_query_to_dict(queries) +# obj = self._build_search_object(q_dict) +# search_key = obj.build_search_key() +# db_keys = self._redis_client.keys(search_key) +# results: list = self._redis_client.mget(db_keys) # type: ignore + +# objs: list["RedisKeyValueObject"] = [] +# if results is not None: +# for r in results: +# r_dict = json.loads(r) +# objs.append(type(self)(**r_dict)) +# return objs + +# def count(self, queries: list[RedisQuery]) -> int: +# self.is_all_instance(queries) +# param_dict = {} +# for q in queries: +# param_dict[q.key] = q.value +# obj = type(self)(**param_dict) +# search_key = obj.build_search_key() +# db_keys: list = self._redis_client.keys(search_key) # type: ignore +# return len(db_keys) + +# def first(self, queries: list[RedisQuery]) -> Optional["RedisKeyValueObject"]: +# self.is_all_instance(queries) +# param_dict = {} +# for q in queries: +# param_dict[q.key] = q.value +# obj = type(self)(**param_dict) +# search_key = obj.build_search_key() +# db_keys = self._redis_client.keys(search_key) +# if len(db_keys) == 0: +# result = None +# else: +# result = self._redis_client.get(db_keys[0]) +# return result + +# def async_count(self, queries: list[RedisQuery]) -> int: +# loop = asyncio.get_event_loop() +# result = loop.run_in_executor(None, self.count, queries) +# return result + +# def async_query(self, queries: list[RedisQuery]) -> list["RedisKeyValueObject"]: +# loop = asyncio.get_event_loop() +# result = loop.run_in_executor(None, self.query, queries) +# return result + +# def async_first(self, queries: list[RedisQuery]) -> Optional["RedisKeyValueObject"]: +# loop = asyncio.get_event_loop() +# result = loop.run_in_executor(None, self.first, queries) +# return result + + +# @dataclass +# class TestKvObject(RedisKeyValueObject): +# param1: int +# param2: int + +# def __post_init__(self): +# self._database = 0 +# return super().__post_init__() + + +# t = TestKvObject(param1=1, param2=2) +# t.query([TestKvObject.param1 == 1]) +# t.build_full_key() +# t.build_search_key() +# t2 = TestKvObject(param1=1, param2=None) +# t2.build_search_key() diff --git a/src/frontends/gamespy/library/abstractions/server_launcher.py b/src/frontends/gamespy/library/abstractions/server_launcher.py new file mode 100644 index 000000000..6b1b5c44d --- /dev/null +++ b/src/frontends/gamespy/library/abstractions/server_launcher.py @@ -0,0 +1,198 @@ +from types import MappingProxyType + +from frontends.gamespy.library.abstractions.connections import NetworkServerBase +from frontends.gamespy.library.exceptions.general import UniSpyException +import schedule +from frontends.gamespy.library.log.log_manager import LogManager, LogWriter +from frontends.gamespy.library.configs import CONFIG, ServerConfig +import pyfiglet +import requests +from prettytable import PrettyTable +from frontends.gamespy.library.abstractions.client import ClientBase +from typing import final + +VERSION = 0.46 +_SERVER_FULL_SHORT_NAME_MAPPING = MappingProxyType( + { + "PresenceConnectionManager": "PCM", + "PresenceSearchPlayer": "PSP", + "CDKey": "CDKey", + "ServerBrwoserV1": "SBv1", + "ServerBrowserV2": "SBv2", + "QueryReport": "QR", + "NatNegotiation": "NN", + "GameStatus": "GS", + "Chat": "Chat", + "WebServices": "Web", + "GameTrafficRelay": "GTR", + } +) + + +class ServiceBase: + config: ServerConfig + _config_name: str + _network_server_cls: type[NetworkServerBase] + _client_cls: type[ClientBase] + _logger: LogWriter + _network_server: NetworkServerBase + _available_checker: object + + def __init__( + self, + config_name: str, + client_cls: type[ClientBase], + network_server_cls: type[NetworkServerBase], + ): + assert issubclass(client_cls, ClientBase) + assert issubclass(network_server_cls, NetworkServerBase) + assert isinstance(config_name, str) + assert config_name in CONFIG.servers + self.config = CONFIG.servers[config_name] + self._network_server_cls = network_server_cls + self._client_cls = client_cls + self._create_logger() + self._create_network_server() + + @final + def _create_logger(self): + assert self.config is not None + short_name = _SERVER_FULL_SHORT_NAME_MAPPING[self.config.server_name] + self._logger = LogManager.create(short_name) + + @final + def _create_network_server(self): + assert self._logger is not None + assert self._network_server_cls is not None + assert self._client_cls is not None + self._network_server = self._network_server_cls( + self.config, self._client_cls, self._logger) + + @final + def start(self): + self._network_server.start() + + @final + def stop(self): + self._network_server.stop() + + @staticmethod + def get_data_from_backends(url: str, json_str: str): + try: + # post our server config to backends to register + resp = requests.post(url=url, data=json_str) + + data = resp.json() + if resp.status_code != 200: + raise UniSpyException(data["message"]) + else: + return data + except requests.ConnectionError: + raise UniSpyException( + f"backend server: {CONFIG.backend.url} not available." + ) + + @final + def _heartbeat_to_backend(self, url: str, json_str: str): + """ + send heartbeat to backends + """ + assert isinstance(json_str, str) + ServiceBase.get_data_from_backends(url, json_str=json_str) + + def _connect_to_backend(self): + """ + check backend availability + """ + assert self.config is not None + if CONFIG.unittest.is_collect_request: + return + self._heartbeat_to_backend( + CONFIG.backend.url, self.config.model_dump_json()) + + @final + def start_post_tasks(self): + """ + run post tasks + - set the schedular to send heartbeat info to backend to keep the infomation update + """ + # launch schedular + schedule.every(30).seconds.do(self._post_task) + + def _post_task(self): + """ + the post task after network server launched + call this function in server factory + """ + self._connect_to_backend() + + +class ServicesFactory: + _lauchers: list[ServiceBase] + + def __init__( + self, + launchers: list[ServiceBase] + ): + self._lauchers = launchers + + def start(self): + self.__show_unispy_logo() + self._launch_servers() + print("Server successfully launched.") + print("Press ctr+c to Quit\n") + self._run_post_tasks() + self._keep_running() + + def _run_post_tasks(self): + """ + run the launcher post task + """ + for launcher in self._lauchers: + launcher.start_post_tasks() + # call all post tasks immediately + schedule.run_all() + + def __show_unispy_logo(self): + # display logo + print(pyfiglet.Figlet().renderText("UniSpy.Server")) + # display version info + print(f"version {VERSION}") + table = PrettyTable() + table.field_names = [ + "Server Name", + "Listening Address", + "Listening Port", + ] + for info in self._lauchers: + table.add_row( + [ + info.config.server_name, + info.config.listening_address, + info.config.listening_port, + ] + ) + print(table) + + @final + def _launch_servers(self) -> None: + """ + assign data in child class so the related instance can be created here + """ + + for info in self._lauchers: + info.start() + + @final + def _keep_running(self): + from time import sleep + try: + while True: + sleep(1) + # run schedule here + schedule.run_pending() + pass + except KeyboardInterrupt: + for info in self._lauchers: + info.stop() + print("\nUniSpy shutdown.") diff --git a/src/frontends/gamespy/library/abstractions/switcher.py b/src/frontends/gamespy/library/abstractions/switcher.py new file mode 100644 index 000000000..c8c0a52d0 --- /dev/null +++ b/src/frontends/gamespy/library/abstractions/switcher.py @@ -0,0 +1,59 @@ +from abc import abstractmethod +from frontends.gamespy.library.abstractions.client import ClientBase +from frontends.gamespy.library.abstractions.handler import CmdHandlerBase + + +class SwitcherBase: + """ + class member type hint can use class static member, but you can not initialize any class static member here! Init it in the __init__() function + """ + _handlers: list[CmdHandlerBase] + _requests: list[tuple[object, object]] + _raw_request: object + + def __init__(self, client: ClientBase, raw_request: bytes | str) -> None: + assert isinstance(client, ClientBase) + assert isinstance(raw_request, str) or isinstance(raw_request, bytes) + self._client: ClientBase = client + self._raw_request: object = raw_request + self._handlers: list[CmdHandlerBase] = [] + self._requests: list[tuple[object, object]] = [] + """ + [ + (request_name,raw_request), + (request_name,raw_request), + (request_name,raw_request), + ... + ] + + """ + + def handle(self): + from frontends.gamespy.library.exceptions.general import UniSpyException + + try: + self._process_raw_request() + if len(self._requests) == 0: + return + for request in self._requests: + handler = self._create_cmd_handlers(request[0], request[1]) + if handler is None: + self._client.log_warn( + f"Request: <{request[0]}> is ignored.") + continue + self._handlers.append(handler) + if len(self._handlers) == 0: + return + + for handler in self._handlers: + handler.handle() + except Exception as e: + UniSpyException.handle_exception(e, self._client) + + @abstractmethod + def _process_raw_request(self) -> None: + pass + + @abstractmethod + def _create_cmd_handlers(self, name: object, raw_request: object) -> CmdHandlerBase | None: + pass diff --git a/src/frontends/gamespy/library/configs.py b/src/frontends/gamespy/library/configs.py new file mode 100644 index 000000000..7ce7fd779 --- /dev/null +++ b/src/frontends/gamespy/library/configs.py @@ -0,0 +1,108 @@ +import os +from typing import Literal, Optional +from uuid import UUID + +from pydantic import BaseModel, HttpUrl, field_validator + + +class PostgreSql(BaseModel): + server: str + port: int + database: str + username: str + password: str + ssl_mode: str # You might want to restrict this to specific values + trust_server_cert: bool + ssl_key: str | None = None # Optional field for SSL key + ssl_password: str | None = None # Optional field for SSL password + root_cert: str | None = None # Optional field for root certificate + + @property + def url(self) -> str: + return f"postgresql://{self.username}:{self.password}@{self.server}:{self.port}/{self.database}?sslmode={self.ssl_mode}" + + +class RedisConfig(BaseModel): + server: str + port: int + user: str + password: str + ssl: bool # Use bool for SSL flag + ssl_host: str | None = None # Optional field for SSL host + + @property + def url(self) -> str: + if self.ssl: + return f"rediss://{self.user}:{self.password}@{self.server}:{self.port}/0" + else: + return f"redis://{self.user}:{self.password}@{self.server}:{self.port}/0" + + +class ServerConfig(BaseModel): + server_id: UUID + server_name: str + listening_address: str + listening_port: int # Ensures listening_port is between 1 and 65535 + + +class LoggingConfig(BaseModel): + path: str + min_log_level: Literal["debug", "info", "warning", "error"] + + @field_validator("path", mode="before") + def expand_user_path(cls, value): + if "~" in value: + return os.path.expanduser(value) + return value + + +class BackendConfig(BaseModel): + url: str + token_secret_key: str + token_algorithm: str + token_expire_time: int = 30 + is_check_public_ip: bool + + +class UnittestConfig(BaseModel): + """ + unittest related config + """ + + is_raise_except: bool + """ + whether raise exception after log it + """ + is_collect_request: bool + """ + only connect the request do not actually do anything + """ + + +class UniSpyServerConfig(BaseModel): + postgresql: PostgreSql + redis: RedisConfig + backend: BackendConfig + servers: dict[str, ServerConfig] + logging: LoggingConfig + unittest: UnittestConfig + + +unispy_config = os.environ.get("UNISPY_CONFIG") +default_config = "../common/config.json" +if unispy_config is None: + unispy_config = default_config + # raise Exception( + # "Unispy server config not found, you should set the UNISPY_CONFIG in the system enviroment." + # ) +if not os.path.exists(unispy_config): + raise Exception( + "Unispy server config file not exist, check UNISPY_CONFIG path.") +with open(unispy_config, "r") as f: + import json + config = json.load(f) +CONFIG = UniSpyServerConfig.model_validate(config) +pass + +if __name__ == "__main__": + pass diff --git a/src/frontends/gamespy/library/encryption/__init__.py b/src/frontends/gamespy/library/encryption/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/gamespy/library/encryption/encoding.py b/src/frontends/gamespy/library/encryption/encoding.py new file mode 100644 index 000000000..bdc42a1e1 --- /dev/null +++ b/src/frontends/gamespy/library/encryption/encoding.py @@ -0,0 +1,12 @@ + + +class Encoding: + @staticmethod + def get_string(data: bytes) -> str: + assert isinstance(data, bytes) + return data.decode("ascii") + + @staticmethod + def get_bytes(data: str) -> bytes: + assert isinstance(data, str) + return data.encode() diff --git a/src/frontends/gamespy/library/encryption/gs_encryption.py b/src/frontends/gamespy/library/encryption/gs_encryption.py new file mode 100644 index 000000000..fb6feca1f --- /dev/null +++ b/src/frontends/gamespy/library/encryption/gs_encryption.py @@ -0,0 +1,98 @@ +from frontends.gamespy.library.abstractions.enctypt_base import EncryptBase + +DIGITS_HEX = "0123456789abcdef" +DIGITS_CRYPT = "aFl4uOD9sfWq1vGp" +NEW_DIGITS_CRYPT = "qJ1h4N9cP3lzD0Ka" +IP_XOR_MASK = 0xC3801DC7 +CLIENT_KEY = "0000000000000000" +SERVER_KEY = "0000000000000000" + + +class PeerChatCtx: + def __init__(self): + self.buffer1 = 0 + self.buffer2 = 0 + self.sbox = [0] * 256 + + +def init(ctx: PeerChatCtx, challenge_key: str, secret_key: str): + assert isinstance(ctx, PeerChatCtx) + assert isinstance(challenge_key, str) + assert isinstance(secret_key, str) + + challenge_bytes = list(challenge_key.encode("ascii")) + secret_key_bytes = list(secret_key.encode("ascii")) + + ctx.buffer1 = 0 + ctx.buffer2 = 0 + + secret_key_index = 0 + for i in range(len(challenge_bytes)): + if secret_key_index >= len(secret_key_bytes): + secret_key_index = 0 + + challenge_bytes[i] ^= secret_key_bytes[secret_key_index] + secret_key_index += 1 + + index1 = 255 + for i in range(256): + ctx.sbox[i] = index1 + index1 -= 1 + + index1 = 0 + index2 = 0 + for i in range(len(ctx.sbox)): + if index1 >= len(challenge_bytes): + index1 = 0 + + index2 = (challenge_bytes[index1] + ctx.sbox[i] + index2) % 256 + t = ctx.sbox[i] + ctx.sbox[i] = ctx.sbox[index2] + ctx.sbox[index2] = t + index1 += 1 + + +class ChatCrypt(EncryptBase): + def __init__(self, game_secret_key): + self.client_ctx = PeerChatCtx() + self.server_ctx = PeerChatCtx() + init(self.client_ctx, CLIENT_KEY, game_secret_key) + init(self.server_ctx, SERVER_KEY, game_secret_key) + + @staticmethod + def handle(ctx: PeerChatCtx, data): + num1 = ctx.buffer1 + num2 = ctx.buffer2 + buffer = [] + size = len(data) + datapos = 0 + + while size > 0: + num1 = (num1 + 1) % 256 + num2 = (ctx.sbox[num1] + num2) % 256 + t = ctx.sbox[num1] + ctx.sbox[num1] = ctx.sbox[num2] + ctx.sbox[num2] = t + t = (ctx.sbox[num2] + ctx.sbox[num1]) % 256 + temp = data[datapos] ^ ctx.sbox[t] + buffer.append(temp) + datapos += 1 + size -= 1 + + ctx.buffer1 = num1 + ctx.buffer2 = num2 + return bytes(buffer) + + def encrypt(self, data: bytes) -> bytes: + super().encrypt(data) + return ChatCrypt.handle(self.server_ctx, data) + + def decrypt(self, data: bytes) -> bytes: + super().decrypt(data) + return ChatCrypt.handle(self.client_ctx, data) + + +if __name__ == "__main__": + enc = ChatCrypt("123456") + cipher = enc.encrypt("hello".encode()) + pass diff --git a/src/frontends/gamespy/library/encryption/xor_encryption.py b/src/frontends/gamespy/library/encryption/xor_encryption.py new file mode 100644 index 000000000..7f705a95f --- /dev/null +++ b/src/frontends/gamespy/library/encryption/xor_encryption.py @@ -0,0 +1,50 @@ +from enum import IntEnum + +from frontends.gamespy.library.abstractions.enctypt_base import EncryptBase + + +class XorType(IntEnum): + TYPE_0 = 0 + TYPE_1 = 1 + TYPE_2 = 2 + TYPE_3 = 3 + + +class XorEncoding(EncryptBase): + def __init__(self, xor_type): + self.encryption_type = xor_type + + @staticmethod + def encode(plaintext: bytes, enc_type: XorType): + assert isinstance(plaintext, bytes) + assert isinstance(enc_type, XorType) + seed_0 = b"gamespy" + seed_1 = b"GameSpy3D" + seed_2 = b"Industries" + seed_3 = b"ProjectAphex" + index = 0 + key = seed_0 + if enc_type == XorType.TYPE_0: + key = seed_0 + elif enc_type == XorType.TYPE_1: + key = seed_1 + elif enc_type == XorType.TYPE_2: + key = seed_2 + elif enc_type == XorType.TYPE_3: + key = seed_3 + result = [] + key_index = 0 + for index in range(len(plaintext)): + key_index = index % len(key) + enc_byte = (plaintext[index] ^ key[key_index]) % 255 + result.append(enc_byte) + + return bytes(result) + + def encrypt(self, data: bytes): + super().encrypt(data) + return XorEncoding.encode(data, self.encryption_type) + + def decrypt(self, data: bytes): + super().decrypt(data) + return XorEncoding.encode(data, self.encryption_type) diff --git a/src/frontends/gamespy/library/exceptions/__init__.py b/src/frontends/gamespy/library/exceptions/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/gamespy/library/exceptions/general.py b/src/frontends/gamespy/library/exceptions/general.py new file mode 100644 index 000000000..fd2a9b0f4 --- /dev/null +++ b/src/frontends/gamespy/library/exceptions/general.py @@ -0,0 +1,54 @@ +import traceback +from typing import TYPE_CHECKING, Optional + +from frontends.gamespy.library.configs import CONFIG +from frontends.gamespy.library.log.log_manager import GLOBAL_LOGGER + + +if TYPE_CHECKING: + from frontends.gamespy.library.abstractions.client import ClientBase + + +class UniSpyException(Exception): + message: str + """the error message""" + + def __init__(self, message: str) -> None: + self.message = message + + @staticmethod + # def handle_exception(e: Exception, client: ClientBase = None): + def handle_exception(e: Exception, client: Optional["ClientBase"] = None): + # first log the exception + if client is None: + GLOBAL_LOGGER.info(str(e)) + else: + if issubclass(type(e), UniSpyException): + ex: UniSpyException = e # type:ignore + client.log_error(ex.message) + elif issubclass(type(e), BrokenPipeError): + client.log_warn(f"client disconnect before message send") + else: + client.log_error(traceback.format_exc()) + # if we are unittesting we raise the exception out + if CONFIG.unittest.is_raise_except: + raise e + + def __repr__(self) -> str: + # return super().__repr__() + return f'Error message: "{self.message}"' + + +class DatabaseConnectionException(UniSpyException): + def __init__(self, message: str = "Can not connect to database.") -> None: + super().__init__(message) + + +class RedisConnectionException(UniSpyException): + def __init__(self, message: str = "Can not connect to redis") -> None: + super().__init__(message) + + +if __name__ == "__main__": + err = UniSpyException("test") + pass diff --git a/src/frontends/gamespy/library/extentions/__init__.py b/src/frontends/gamespy/library/extentions/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/gamespy/library/extentions/bytes_extentions.py b/src/frontends/gamespy/library/extentions/bytes_extentions.py new file mode 100644 index 000000000..e1fdaf918 --- /dev/null +++ b/src/frontends/gamespy/library/extentions/bytes_extentions.py @@ -0,0 +1,24 @@ +import socket + + +def bytes_to_int(input: bytes) -> int: + assert isinstance(input, bytes) + return int.from_bytes(input, "little") + + +def int_to_bytes(input: int) -> bytes: + assert isinstance(input, int) + return input.to_bytes(4, "little", signed=False) + + +def ip_to_4_bytes(ip: str) -> bytes: + assert isinstance(ip, str) + return socket.inet_aton(ip) + + +def port_to_2_bytes(port: int) -> bytes: + """ + using for qr sb natneg to convert port to bytes + """ + assert isinstance(port, int) + return port.to_bytes(2, "little") diff --git a/src/frontends/gamespy/library/extentions/debug_helper.py b/src/frontends/gamespy/library/extentions/debug_helper.py new file mode 100644 index 000000000..643fc447e --- /dev/null +++ b/src/frontends/gamespy/library/extentions/debug_helper.py @@ -0,0 +1,91 @@ +import argparse +from multiprocessing import Process +import os +import time +from typing import TYPE_CHECKING, Callable +from watchdog.events import FileSystemEventHandler +from watchdog.observers import Observer +if TYPE_CHECKING: + from frontends.gamespy.library.abstractions.server_launcher import ServicesFactory + + +class FileChangeHandler(FileSystemEventHandler): + process: Process | None + monitor_path: str + launch_func: Callable + + def __init__(self, folder_path: str, launch_func: Callable): + assert isinstance(folder_path, str) + super().__init__() + self.process = None + self.monitor_path = os.path.abspath(folder_path) + self.launch_func = launch_func + self.__start_process() + + def __start_process(self): + if self.process is not None: + self.process.terminate() + self.process = Process(target=self.launch_func) + self.process.start() + + def on_modified(self, event): + assert isinstance(event.src_path, str) + abs_event_path = os.path.abspath(event.src_path) + if abs_event_path.endswith('.py'): + common_path = os.path.commonpath( + [abs_event_path, self.monitor_path]) + if common_path == self.monitor_path: + print( + f"File {event.src_path} has been modified. Restarting process...") + self.__start_process() + + +class DebugHelper: + _observer: object + _folder_path: str + _factory: "ServicesFactory" + + def __init__(self, folder_path: str, factory: "ServicesFactory") -> None: + self._folder_path = folder_path + self._factory = factory + + def start(self): + # Initialize the ArgumentParser + parser = argparse.ArgumentParser( + description='Example script to demonstrate argparse with debug mode.') + + # Add a debug argument + parser.add_argument( + '--debug', + action='store_true', + help='Enable debugging mode.' + ) + + # Parse the arguments + args = parser.parse_args() + + # Check if debug mode is enabled + if args.debug: + print( + "\033[93mUniSpy is starting with watchdog, any changes in code will restart the server\033[0m") + self.__start_with_watch() + else: + self.__start_normal() + + def __start_with_watch(self): + event_handler = FileChangeHandler( + self._folder_path, self.__start_normal) + self._observer = Observer() + self._observer.schedule( + event_handler, self._folder_path, recursive=True) + try: + self._observer.start() + while True: + time.sleep(1) + except Exception as e: + print(str(e)) + finally: + self._observer.stop() + + def __start_normal(self): + self._factory.start() diff --git a/src/frontends/gamespy/library/extentions/encoding.py b/src/frontends/gamespy/library/extentions/encoding.py new file mode 100644 index 000000000..559536463 --- /dev/null +++ b/src/frontends/gamespy/library/extentions/encoding.py @@ -0,0 +1,31 @@ +import enum +import json +from uuid import UUID + +from pydantic import BaseModel + + +def get_string(data: bytes) -> str: + return data.decode("ascii") + + +def get_bytes(data: str) -> bytes: + return data.encode("ascii") + + +class UniSpyJsonEncoder(json.JSONEncoder): + def default(self, obj): + # Handle bytes + if isinstance(obj, bytes): + return obj.decode("ascii", "backslashreplace") + # Handle enum and IntEnum + elif isinstance(obj, enum.Enum): + return obj.value + elif isinstance(obj, enum.IntEnum): + return obj.value + elif isinstance(obj, UUID): + return str(obj) + elif isinstance(obj,BaseModel): + return obj.model_dump_json() + # Fallback to the default method for other types + return super().default(obj) diff --git a/src/frontends/gamespy/library/extentions/file_watcher.py b/src/frontends/gamespy/library/extentions/file_watcher.py new file mode 100644 index 000000000..06893cc4e --- /dev/null +++ b/src/frontends/gamespy/library/extentions/file_watcher.py @@ -0,0 +1,29 @@ +import time +from watchdog.observers import Observer +from watchdog.events import FileSystemEventHandler + +class FileWatcher: + pass + +class MyHandler(FileSystemEventHandler): + def on_any_event(self, event): + if event.is_directory: + return None + elif event.event_type == 'created': + print(f"Created: {event.src_path}") + elif event.event_type =='modified': + print(f"Modified: {event.src_path}") + + +if __name__ == "__main__": + event_handler = MyHandler() + observer = Observer() + path = '.' # Monitor the current directory + observer.schedule(event_handler, path, recursive=True) + observer.start() + try: + while True: + time.sleep(1) + except KeyboardInterrupt: + observer.stop() + observer.join() \ No newline at end of file diff --git a/src/frontends/gamespy/library/extentions/gamespy_ramdoms.py b/src/frontends/gamespy/library/extentions/gamespy_ramdoms.py new file mode 100644 index 000000000..23f1139dc --- /dev/null +++ b/src/frontends/gamespy/library/extentions/gamespy_ramdoms.py @@ -0,0 +1,137 @@ +from enum import IntEnum +import random +import datetime + + +class StringType(IntEnum): + ALPHANUMERIC = 0 + ALPHA = 1 + HEX = 2 + + +def generate_random_string(count: int, type: StringType) -> str: + random.seed(datetime.datetime.now().timestamp()) + + alpha_chars = [ + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + ] + + alpha_num_chars = [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + ] + + hex_chars = [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "a", + "b", + "c", + "d", + "e", + "f", + ] + + builder = [] + for _ in range(count): + if type == StringType.ALPHANUMERIC: + builder.append(random.choice(alpha_num_chars)) + elif type == StringType.HEX: + builder.append(random.choice(hex_chars)) + else: + builder.append(random.choice(alpha_chars)) + + return "".join(builder) diff --git a/src/frontends/gamespy/library/extentions/gamespy_utils.py b/src/frontends/gamespy/library/extentions/gamespy_utils.py new file mode 100644 index 000000000..bf15b21ba --- /dev/null +++ b/src/frontends/gamespy/library/extentions/gamespy_utils.py @@ -0,0 +1,76 @@ +from email_validator import validate_email, EmailNotValidError + + +def is_email_format_correct(email: str) -> bool: + assert isinstance(email, str) + try: + validate_email(email, check_deliverability=False) + + except EmailNotValidError: + return False + + return True + + +def convert_to_key_value(request: str) -> dict: + assert isinstance(request, str) + command_parts = request.replace("\\final\\", "").lstrip("\\").split("\\") + + parts = [part for part in command_parts if part != "final"] + dict = {} + try: + for i in range(0, len(parts), 2): + if parts[i] not in dict: + dict[parts[i].lower()] = parts[i + 1] + # Some game send uppercase key to us, so we have to deal with it + except IndexError: + pass + return dict + + +def is_valid_date(day: int, month: int, year: int) -> bool: + # Check for a blank. + if (day, month, year) == (0, 0, 0): + return False + + # Validate the day of the month. + match month: + case 0: + # Can't specify a day without a month. + if day != 0: + return False + case 1, 3, 5, 7, 8, 10, 12: + # 31-day month. + if day > 31: + return False + case 4, 6, 9, 11: + # 30-day month. + if day > 30: + return False + case 2: + # 28/29-day month. + # Leap year? + if ((year % 4 == 0) and (year % 100 != 0)) or (year % 400 == 0): + if day > 29: + return False + else: + if day > 28: + return False + case _: + # Invalid month. + return False + + # Check that the date is in the valid range. + if year < 1900 or year > 2079: + return False + elif year == 2079: + match month: + case 6 if day > 6: + return False + case _: + if month > 6: + return False + + return True + + diff --git a/src/frontends/gamespy/library/extentions/password_encoder.py b/src/frontends/gamespy/library/extentions/password_encoder.py new file mode 100644 index 000000000..bb1769d13 --- /dev/null +++ b/src/frontends/gamespy/library/extentions/password_encoder.py @@ -0,0 +1,77 @@ +import hashlib +import base64 + +from frontends.gamespy.library.exceptions.general import UniSpyException + + +def process_password(request: dict): + """process password in standard format and return the password""" + assert isinstance(request, dict) + if "passwordenc" in request: + md5_password = get_md5_hash(decode(request["passwordenc"])) + elif "passenc" in request: + md5_password = get_md5_hash(request["passenc"]) + elif "pass" in request: + md5_password = get_md5_hash(request["pass"]) + elif "password" in request: + md5_password = get_md5_hash(request["password"]) + else: + raise UniSpyException("Can not find password field in request") + return md5_password + + +def encode(password: str): + assert isinstance(password, str) + password_bytes = password.encode("utf-8") + pass_encoded = base64.b64encode(game_spy_encode_method(password_bytes)) + pass_encoded = pass_encoded.decode("utf-8") + pass_encoded = pass_encoded.replace("=", "_").replace("+", "[").replace("/", "]") + return pass_encoded + + +def decode(password: str): + assert isinstance(password, str) + password = password.replace("_", "=").replace("[", "+").replace("]", "/") + password_bytes = base64.b64decode(password) + return game_spy_encode_method(password_bytes).decode("utf-8") + + +def game_spy_encode_method(password_bytes: bytes): + assert isinstance(password_bytes, bytes) + a = 0 + num = 0x79707367 # gamespy + temp_data = list(password_bytes) + for i in range(len(password_bytes)): + num = game_spy_byte_shift(num) + a = num % 0xFF + temp_data[i] ^= a + return bytes(temp_data) + + +def game_spy_byte_shift(num): + assert isinstance(num, int) + c = (num >> 16) & 0xFFFF + a = num & 0xFFFF + + c *= 0x41A7 + a *= 0x41A7 + a += (c & 0x7FFF) << 16 + + if a < 0: + a &= 0x7FFFFFFF + a += 1 + + a += c >> 15 + + if a < 0: + a &= 0x7FFFFFFF + a += 1 + + return a + + +def get_md5_hash(data): + isinstance(data, str) + md5_hash = hashlib.md5() + md5_hash.update(data.encode("utf-8")) + return md5_hash.hexdigest() diff --git a/src/frontends/gamespy/library/extentions/redis_orm.py b/src/frontends/gamespy/library/extentions/redis_orm.py new file mode 100644 index 000000000..5c2117118 --- /dev/null +++ b/src/frontends/gamespy/library/extentions/redis_orm.py @@ -0,0 +1,37 @@ +# import redis + + +# class RedisORM: +# def __init__(self, host="localhost", port=6379, db=0): +# # self.redis_conn = redis.StrictRedis(host=host, port=port, db=db) +# pass + +# def query(self, table_class): +# return QueryBuilder(self.redis_conn, table_class) + + +# class QueryBuilder: +# def __init__(self, redis_conn, table_class): +# self.redis_conn = redis_conn +# self.table_class = table_class + +# def filter_by(self, **kwargs): +# self.filter_criteria = kwargs +# return self + +# def first(self): +# key = f"{self.table_class.__name__}:{self.filter_criteria['url']}" +# data = self.redis_conn.hgetall(key) +# return data + + +# # Example usage +# class User: +# pass + + +# redis_orm = RedisORM() +# query = QueryBuilder(None, None) +# result = query.filter_by(url="example.com", name="hello").first() +# print(result) + diff --git a/src/frontends/gamespy/library/extentions/string_extentions.py b/src/frontends/gamespy/library/extentions/string_extentions.py new file mode 100644 index 000000000..1cbc9317b --- /dev/null +++ b/src/frontends/gamespy/library/extentions/string_extentions.py @@ -0,0 +1,101 @@ +from typing import Literal + + +def convert_nonprintable_bytes_to_hex_string(buffer: bytes) -> str: + assert isinstance(buffer, bytes) + temp = "" + for byte in buffer: + if byte < 0x1F or byte > 0x7E: + temp += f"[{byte:02X}]" + else: + temp += chr(byte) + return temp + + +def convert_printable_bytes_to_string(buffer: bytes) -> str: + assert isinstance(buffer, bytes) + delimiter = " " + temp = "" + for byte in buffer: + if byte < 0x1F or byte > 0x7E: + if temp and temp[-1] != delimiter: + temp += delimiter + else: + temp += chr(byte) + return temp + + +def convert_kvstring_to_dictionary(kv_str: str): + assert isinstance(kv_str, str) + dic = {} + key_value_list = kv_str.split("\\") + + for i in range(0, len(key_value_list), 2): + if len(key_value_list) < i + 2: + dic[key_value_list[i]] = "" + else: + dic[key_value_list[i]] = key_value_list[i + 1].replace("\x00", "") + + return dic + + +def convert_keystr_to_list(key_str: str): + assert isinstance(key_str, str) + + data = key_str.split("\\") + # Remove empty strings from the list + data = [item for item in data if item] + + return data + + +def convert_byte_to_hex_string(buffer: bytes): + assert isinstance(buffer, bytes) + hex_string = ", ".join(["0x" + format(byte, "02X") for byte in buffer]) + return hex_string + + +def from_hex_string_to_bytes(hex_str: str): + """ + use in webservice auth public key convertion + """ + assert isinstance(hex_str, str) + data = [int(hex_str[i: i + 2], 16) for i in range(0, len(hex_str), 2)] + return bytes(data) + + +if __name__ == "__main__": + sig = "0001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003020300C06082A864886F70D020505000410" + + data = from_hex_string_to_bytes(sig) + pass + + +def get_first_capitalized_char(name: str): + assert isinstance(name, str) + result = "" + for char in name: + if char.isupper(): + result += char + return result + + +def get_server_short_name(name: str): + if len(name) >= 4: + short_name = get_first_capitalized_char(name) + else: + short_name = name + return short_name + + +def format_network_message( + type: Literal["recv", "send"], message: bytes, is_log_raw: bool = False +): + assert type in ["recv", "send"] + if is_log_raw: + tempLog = f"{convert_printable_bytes_to_string( + message)} [{convert_byte_to_hex_string(message)}]" + else: + tempLog = convert_nonprintable_bytes_to_hex_string(message) + + return f"[{type}] {tempLog}" diff --git a/src/frontends/gamespy/library/log/__init__.py b/src/frontends/gamespy/library/log/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/gamespy/library/log/log_manager.py b/src/frontends/gamespy/library/log/log_manager.py new file mode 100644 index 000000000..e75592d3a --- /dev/null +++ b/src/frontends/gamespy/library/log/log_manager.py @@ -0,0 +1,108 @@ +import logging +from logging.handlers import TimedRotatingFileHandler +import os + +from frontends.gamespy.library.configs import CONFIG + + +class LogWriter: + original_logger: logging.Logger + + def __init__(self, logger) -> None: + self.original_logger = logger + + def debug(self, message: str): + self.original_logger.debug(message) + + def info(self, message: str): + self.original_logger.info(message) + + def error(self, message: str): + self.original_logger.error(message) + + def warn(self, message: str): + self.original_logger.warn(message) + + +def create_dir(path): + """ + 创建对应目录,如果该目录不存在 + """ + log_path = os.path.dirname(path) + if not os.path.exists(log_path): + os.makedirs(log_path) + + +class ColoredFormatter(logging.Formatter): + COLORS = { + "DEBUG": "\033[94m", # Blue + "INFO": "\033[92m", # Green + "WARNING": "\033[93m", # Yellow + "ERROR": "\033[91m", # Red + "CRITICAL": "\033[41m", # White text on Red background + } + RESET = "\033[0m" # Reset to default color + + def format(self, record): + # Get the color for the levelname + color = self.COLORS.get(record.levelname, self.RESET) + # Format the levelname with color + record.levelname = f"{color}{record.levelname}{self.RESET}" + return super().format(record) + + +class LogManager: + @staticmethod + def create(logger_name: str) -> "LogWriter": + log_file_path = CONFIG.logging.path + create_dir(log_file_path) + file_name = f"{log_file_path}/{logger_name}.log" + if CONFIG.logging.min_log_level == "debug": + log_level = logging.DEBUG + else: + log_level = logging.INFO + + logging.basicConfig( + filename=file_name, + level=log_level, + format=f"%(asctime)s [{logger_name}] [%(levelname)s]: %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + ) + # 滚动日志文件 + file_handler = TimedRotatingFileHandler( + file_name, + when="midnight", + interval=1, + backupCount=7, + encoding="utf-8", + ) + formater = logging.Formatter( + f"%(asctime)s [{logger_name}] [%(levelname)s]: %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + ) + color_formatter = ColoredFormatter( + f"%(asctime)s [{logger_name}] [%(levelname)s]: %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + ) + file_handler.setFormatter(formater) + + # create console log handler + console_handler = logging.StreamHandler() + console_handler.setFormatter(color_formatter) + # create logger + logger = logging.getLogger(logger_name) + logger.addHandler(file_handler) + logger.addHandler(console_handler) + return LogWriter(logger) + + @staticmethod + def logger_exists(name) -> bool: + logger = logging.getLogger(name) + is_exist = len(logger.handlers) > 0 + return is_exist + + +GLOBAL_LOGGER = LogManager.create("unispy") +""" +the global logger of unispy +""" diff --git a/src/frontends/gamespy/library/network/__init__.py b/src/frontends/gamespy/library/network/__init__.py new file mode 100644 index 000000000..b2652cdb1 --- /dev/null +++ b/src/frontends/gamespy/library/network/__init__.py @@ -0,0 +1,9 @@ +DATA_SIZE = 2048 +import abc + + +class Server(abc.ABC): + + @abc.abstractmethod + def start(self): + pass diff --git a/src/frontends/gamespy/library/network/http_handler.py b/src/frontends/gamespy/library/network/http_handler.py new file mode 100644 index 000000000..92fdf7d4e --- /dev/null +++ b/src/frontends/gamespy/library/network/http_handler.py @@ -0,0 +1,68 @@ +from frontends.gamespy.library.abstractions.client import ClientBase +from frontends.gamespy.library.abstractions.connections import ( + ConnectionBase, + NetworkServerBase, +) +from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer +from frontends.gamespy.library.configs import CONFIG, ServerConfig +from frontends.gamespy.library.log.log_manager import LogWriter + + +class HttpConnection(ConnectionBase): + handler: BaseHTTPRequestHandler + + def send(self, data: bytes) -> None: + assert isinstance(data, bytes) + self.handler.send_response(200) + self.handler.send_header("Content-type", "text/xml") + self.handler.send_header("Content-Length", str(len(data))) + self.handler.end_headers() + self.handler.wfile.write(data) + +class HttpHandler(BaseHTTPRequestHandler): + conn: HttpConnection + + def do_POST(self) -> None: + # parsed_url = urlparse(self.path).geturl() + content_length = int(self.headers["Content-Length"]) + data = self.rfile.read(content_length).decode() + self.conn = HttpConnection( + self, *self.server.unispy_params) # type: ignore + self.conn.on_received(data.encode()) + + def log_message(self, format, *args): + pass + + +class HttpServer(NetworkServerBase): + def __init__( + self, config: ServerConfig, t_client: type[ClientBase], logger: LogWriter + ) -> None: + super().__init__(config, t_client, logger) + self._server = ThreadingHTTPServer( + (self._config.listening_address, + self._config.listening_port), HttpHandler + ) + self._server.unispy_params = ( # type: ignore + self._config, + self._client_cls, + self._logger) + + +class TestClient(ClientBase): + def _create_switcher(self, buffer) -> None: + # return super().create_switcher(buffer) + print(buffer) + pass + + def on_connected(self) -> None: + # return super().on_connected() + print("connected!") + pass + + +if __name__ == "__main__": + # create_http_server(list(CONFIG.servers.values())[0], ClientBase) + from frontends.tests.gamespy.library.mock_objects import LogMock + + s = HttpServer(list(CONFIG.servers.values())[0], TestClient, LogMock()) diff --git a/src/frontends/gamespy/library/network/tcp_handler.py b/src/frontends/gamespy/library/network/tcp_handler.py new file mode 100644 index 000000000..f4390c04b --- /dev/null +++ b/src/frontends/gamespy/library/network/tcp_handler.py @@ -0,0 +1,88 @@ +import socket +import socketserver + +from frontends.gamespy.library.abstractions.client import ClientBase +from frontends.gamespy.library.abstractions.connections import ( + ConnectionBase, + NetworkServerBase, +) + +from frontends.gamespy.library.log.log_manager import LogWriter +from frontends.gamespy.library.network import DATA_SIZE +from frontends.gamespy.library.configs import CONFIG, ServerConfig + + +class TcpConnection(ConnectionBase): + def send(self, data) -> None: + sock: socket.socket = self.handler.request + sock.sendall(data) + + def on_connected(self) -> None: + self._client.on_connected() + + def on_disconnected(self) -> None: + self._client.on_disconnected() + + def disconnect(self) -> None: + sock: socket.socket = self.handler.request + sock.close() + + +class TcpHandler(socketserver.BaseRequestHandler): + request: socket.socket + conn: TcpConnection + + def handle(self) -> None: + self.conn = TcpConnection( + self, *self.server.unispy_params) # type: ignore + self.conn.on_connected() + while True: + try: + data = self.request.recv(DATA_SIZE) + # ignore disconnect data + if not data: + break + self.conn.on_received(data) + except ConnectionResetError: + self.conn.on_disconnected() + except Exception as e: + print(e) + pass + + +class TcpServer(NetworkServerBase): + + def __init__( + self, config: ServerConfig, t_client: type[ClientBase], logger: LogWriter + ) -> None: + super().__init__(config, t_client, logger) + self._server = socketserver.ThreadingTCPServer( + (self._config.listening_address, self._config.listening_port), + TcpHandler, + bind_and_activate=False + ) + self._server.allow_reuse_address = True # type:ignore + self._server.unispy_params = ( # type: ignore + self._config, self._client_cls, self._logger) + self._server.server_bind() + self._server.server_activate() + + +class TestClient(ClientBase): + def _create_switcher(self, buffer) -> None: + # return super().create_switcher(buffer) + print(buffer) + pass + + def on_connected(self) -> None: + # return super().on_connected() + print("connected!") + pass + + +if __name__ == "__main__": + from frontends.tests.gamespy.library.mock_objects import LogMock + + s = TcpServer(list(CONFIG.servers.values())[0], TestClient, LogMock()) + s.start() + pass diff --git a/src/frontends/gamespy/library/network/udp_handler.py b/src/frontends/gamespy/library/network/udp_handler.py new file mode 100644 index 000000000..852782962 --- /dev/null +++ b/src/frontends/gamespy/library/network/udp_handler.py @@ -0,0 +1,67 @@ +import socket +import socketserver + +from frontends.gamespy.library.abstractions.client import ClientBase +from frontends.gamespy.library.abstractions.connections import ( + ConnectionBase, + NetworkServerBase, +) +from frontends.gamespy.library.configs import CONFIG, ServerConfig +from frontends.gamespy.library.log.log_manager import LogWriter + + +class UdpConnection(ConnectionBase): + def send(self, data) -> None: + conn: socket.socket = self.handler.request[1] + conn.sendto(data, self.handler.client_address) + + +class UdpHandler(socketserver.BaseRequestHandler): + request: tuple[bytes, socket.socket] + conn: UdpConnection + + def handle(self) -> None: + data = self.request[0] + conn = UdpConnection(self, *self.server.unispy_params) # type: ignore + conn.on_received(data) + + def send(self, data: bytes) -> None: + conn: socket.socket = self.request[1] + conn.sendto(data, self.client_address) + + +class UdpServer(NetworkServerBase): + def __init__( + self, config: ServerConfig, t_client: type[ClientBase], logger: LogWriter + ) -> None: + super().__init__(config, t_client, logger) + self._server = socketserver.ThreadingUDPServer( + (self._config.listening_address, self._config.listening_port), + UdpHandler, + ) + # inject the handler params to ThreadingUDPServer + self._server.unispy_params = (self._config, self._client_cls, self._logger) # type: ignore + + def __exit__(self, *args): + self._server.__exit__(*args) + + +class TestClient(ClientBase): + def _create_switcher(self, buffer) -> None: + # return super().create_switcher(buffer) + print(buffer) + pass + + def on_connected(self) -> None: + # return super().on_connected() + print("connected!") + pass + + +if __name__ == "__main__": + # create_udp_server(list(CONFIG.servers.values())[0], ClientBase) + from frontends.tests.gamespy.library.mock_objects import LogMock + + s = UdpServer(list(CONFIG.servers.values())[0], TestClient, LogMock()) + s.start() + pass diff --git a/src/frontends/gamespy/library/network/websocket_brocker.py b/src/frontends/gamespy/library/network/websocket_brocker.py new file mode 100644 index 000000000..7beaad61a --- /dev/null +++ b/src/frontends/gamespy/library/network/websocket_brocker.py @@ -0,0 +1,76 @@ +import threading +from uuid import UUID +from websockets import ConnectionClosed +from frontends.gamespy.library.abstractions.brocker import BrockerBase + +from frontends.gamespy.library.log.log_manager import GLOBAL_LOGGER +from websockets.sync.client import connect, ClientConnection + + +class WebSocketBrocker(BrockerBase): + _subscriber: ClientConnection + _publisher: ClientConnection + + def subscribe(self): + self._publisher = self._subscriber = connect(self.url) + th = threading.Thread(target=self._listen) + th.start() + + @property + def ip_port(self) -> str: + name = self._subscriber.socket.getsockname() + return f"{name[0]}:{name[1]}" + + def _listen(self): + # we do not listen to channel, if the call back is none + if self._call_back_func is None: + return + + try: + while True: + message = self._subscriber.recv() + self._call_back_func(message) + except ConnectionClosed: + GLOBAL_LOGGER.warn("backend websocket server is not avaliable") + # raise UniSpyException("websocket connection is not established") + + def unsubscribe(self): + self._subscriber.close() + + def publish_message(self, message: str): + super().publish_message(message) + if self._publisher is None: + raise ValueError("websocket connection is not established") + self._publisher.send(message) + + +COUNT = 0 + + +def call_back(str): + global COUNT + COUNT += 1 + print(COUNT) + # print(f"{datetime.now()}:{str}") + + +if __name__ == "__main__": + ws = WebSocketBrocker( + name="test_channel", + url="ws://127.0.0.1:8080/GameSpy/Chat/ws", + call_back_func=call_back, + ) + ws.subscribe() + from frontends.gamespy.protocols.chat.abstractions.contract import BrockerMessage + + msg = BrockerMessage( + server_id=UUID("08ed7859-1d9e-448b-8fda-dabb845d85f9"), + channel_name="gmtest", + sender_ip_address="192.168.0.1", + sender_port=80, + message="hello", + ) + # while True: + while True: + ws.publish_message(msg.model_dump_json()) + pass diff --git a/src/frontends/gamespy/protocols/__init__.py b/src/frontends/gamespy/protocols/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/gamespy/protocols/chat/__init__.py b/src/frontends/gamespy/protocols/chat/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/gamespy/protocols/chat/abstractions/contract.py b/src/frontends/gamespy/protocols/chat/abstractions/contract.py new file mode 100644 index 000000000..31b3de87a --- /dev/null +++ b/src/frontends/gamespy/protocols/chat/abstractions/contract.py @@ -0,0 +1,99 @@ +from uuid import UUID + +from pydantic import BaseModel +import frontends.gamespy.library.abstractions.contracts as lib + + +class RequestBase(lib.RequestBase): + raw_request: str + command_name: str + _prefix: str | None + _cmd_params: list[str] + _long_param: str | None + websocket_address: str + + def __init__(self, raw_request: str) -> None: + assert isinstance(raw_request, str) + super().__init__(raw_request) + self._prefix = None + self._cmd_params = [] + self._long_param = None + + def parse(self) -> None: + # at most 2 colon character + # we do not sure about all command + # so i block this code here + self.raw_request = self.raw_request.replace("\r", "").replace("\n", "") + dataFrag = [] + + if self.raw_request.count(":") > 2: + raise Exception(f"IRC request is invalid {self.raw_request}") + if ":" not in self.raw_request: + index_of_colon = -1 + else: + index_of_colon = self.raw_request.index(":") + + raw = self.raw_request + if index_of_colon == 0 and index_of_colon != -1: + if " " not in raw: + prefixIndex = -1 + else: + prefixIndex = raw.index(" ") + self._prefix = raw[index_of_colon:prefixIndex] + raw = raw[prefixIndex:] + + if ":" not in raw: + index_of_colon = 0 + else: + index_of_colon = raw.index(":") + if index_of_colon != 0 and index_of_colon != -1: + self._long_param = raw[index_of_colon + 1 :] + # reset the request string + raw = raw[:index_of_colon] + + dataFrag = raw.strip(" ").split(" ") + + self.command_name = dataFrag[0] + + if len(dataFrag) > 1: + self._cmd_params = dataFrag[1:] + + +class ResultBase(lib.ResultBase): + pass + + +SERVER_DOMAIN = "unispy.net" + + +class ResponseBase(lib.ResponseBase): + sending_buffer: str + _result: ResultBase + + def __init__(self, result: ResultBase) -> None: + super().__init__(result) + if result is not None: + assert issubclass(type(result), ResultBase) + + @staticmethod + def build_irc_user_prefix(nick_name: str, user_name: str): + return f"{nick_name}!{user_name}@{SERVER_DOMAIN}" + + +# region Brocker + + +class BrockerMessage(BaseModel): + server_id: UUID + channel_name: str + sender_ip_address: str + sender_port: int + message: str + + +if __name__ == "__main__": + # Example usage: + request = RequestBase("") + request.raw_request = "your_raw_request_here" + request.parse() + print(request.command_name) diff --git a/src/frontends/gamespy/protocols/chat/abstractions/handler.py b/src/frontends/gamespy/protocols/chat/abstractions/handler.py new file mode 100644 index 000000000..accfa3091 --- /dev/null +++ b/src/frontends/gamespy/protocols/chat/abstractions/handler.py @@ -0,0 +1,164 @@ +from backends.library.database.pg_orm import ChatChannelCaches +from frontends.gamespy.protocols.chat.aggregates.enums import MessageType +from frontends.gamespy.protocols.chat.abstractions.contract import ( + BrockerMessage, + RequestBase, + ResponseBase, + ResultBase, +) +from frontends.gamespy.protocols.chat.aggregates.exceptions import ( + ChatException, + NoSuchNickException, +) +from frontends.gamespy.library.abstractions.client import ClientBase +from frontends.gamespy.protocols.chat.applications.client import Client +from frontends.gamespy.protocols.chat.aggregates.exceptions import IRCException +import frontends.gamespy.library.abstractions.handler as lib +from typing import cast + + +class CmdHandlerBase(lib.CmdHandlerBase): + _client: Client + _request: RequestBase + _result: ResultBase + + def __init__(self, client: ClientBase, request: RequestBase): + super().__init__(client, request) + assert issubclass(type(request), RequestBase) + + def _request_check(self) -> None: + super()._request_check() + assert self._client.brocker + try: + self._request.websocket_address = self._client.brocker.ip_port + except: + raise ChatException("websocket is disconnected") + + def _handle_exception(self, ex: Exception) -> None: + t_ex = type(ex) + if t_ex is IRCException: + ex = cast(IRCException, ex) + self._client.connection.send(ex.message.encode()) + super()._handle_exception(ex) + + +class PostLoginHandlerBase(CmdHandlerBase): + pass + + +# region Channel + + +class ChannelRequestBase(RequestBase): + channel_name: str + + def __init__(self, raw_request: str) -> None: + super().__init__(raw_request) + + def parse(self) -> None: + super().parse() + if self._cmd_params is None or len(self._cmd_params) < 1: + raise ChatException("Channel name is missing.") + self.channel_name = self._cmd_params[0] + + +class ChannelResponseBase(ResponseBase): + def __init__(self, result: ResultBase) -> None: + assert isinstance(result, ResultBase) + super().__init__(result) + + @staticmethod + def build_value_str(keys: list, kv: dict) -> str: + v_str = "" + for k in keys: + v_str += "\\" + if k in kv: + v_str += kv[k] + return v_str + + @staticmethod + def build_key_value_str(kv: dict) -> str: + kv_str = "" + for k, v in kv.items(): + kv_str += f"\\{k}\\{v}" + return kv_str + + +class ChannelHandlerBase(PostLoginHandlerBase): + _request: ChannelRequestBase + _response: ResponseBase + _result: ResultBase + _channel: ChatChannelCaches + _is_broadcast: bool + + def __init__(self, client: ClientBase, request: RequestBase): + super().__init__(client, request) + """ + we handle message broadcasting in backend api + frontends -> backends -> backends_api -> websocket broadcast. -> frontends.client.brocker.receive + """ + self._is_broadcast = False + + def _response_send(self) -> None: + if self._is_broadcast: + # send message to backend websocket + self.broadcast() + else: + super()._response_send() + + def broadcast(self): + self._response.build() + assert self._request.channel_name + msg = BrockerMessage( + server_id=self._client.server_config.server_id, + channel_name=self._request.channel_name, + sender_ip_address=self._client.connection.remote_ip, + sender_port=self._client.connection.remote_port, + message=self._response.sending_buffer, + ) + assert self._client.brocker + self._client.brocker.publish_message(msg.model_dump_json()) + self._client.log_network_broadcast(msg) + + +# region Message +class MessageRequestBase(ChannelRequestBase): + type: MessageType + nick_name: str + message: str + target_name: str + + def parse(self): + super().parse() + if self.channel_name is None: + raise NoSuchNickException( + "the channel name is missing from the request") + if "#" in self.channel_name: + self.type = MessageType.CHANNEL_MESSAGE + self.target_name = self.channel_name + else: + if self._cmd_params is None or len(self._cmd_params) < 1: + raise ChatException("cmd params is invalid") + self.type = MessageType.USER_MESSAGE + self.nick_name = self._cmd_params[0] + self.target_name = self.nick_name + if self._long_param is None: + raise ChatException("long param is invalid") + self.message = self._long_param + + +class MessageResultBase(ResultBase): + sender_nick_name: str + sender_user_name: str + target_name: str + message: str + + +class MessageHandlerBase(ChannelHandlerBase): + _request: MessageRequestBase + _result: MessageResultBase + + def __init__(self, client: ClientBase, request: MessageRequestBase): + assert isinstance(request, MessageRequestBase) + super().__init__(client, request) + self._is_broadcast = True diff --git a/src/frontends/gamespy/protocols/chat/aggregates/enums.py b/src/frontends/gamespy/protocols/chat/aggregates/enums.py new file mode 100644 index 000000000..2a0fdb0b1 --- /dev/null +++ b/src/frontends/gamespy/protocols/chat/aggregates/enums.py @@ -0,0 +1,180 @@ +from enum import Enum, IntEnum + + +class LoginRequestType(IntEnum): + UNIQUE_NICK_LOGIN = 1 + NICK_AND_EMAIL_LOGIN = 2 + + +class WhoRequestType(IntEnum): + GET_CHANNEL_USER_INFO = 0 + GET_USER_INFO = 1 + + +class MessageType(IntEnum): + CHANNEL_MESSAGE = 0 + USER_MESSAGE = 1 + + +class GetKeyRequestType(IntEnum): + GET_CHANNEL_ALL_USER_KEY_VALUE = 0 + GET_CHANNEL_SPECIFIC_USER_KEY_VALUE = 1 + + +class ModeOperation(Enum): + SET = "+" + UNSET = "-" + + +class ModeName(Enum): + USER_QUIET_FLAG = "q" + CHANNEL_PASSWORD = "k" + CHANNEL_USER_LIMITS = "l" + BAN_ON_USER = "b" + CHANNEL_OPERATOR = "co" + USER_VOICE_PERMISSION = "cv" + INVITED_ONLY = "i" + PRIVATE_CHANNEL_FLAG = "p" + SECRET_CHANNEL_FLAG = "s" + MODERATED_CHANNEL_FLAG = "m" + EXTERNAL_MESSAGES_FLAG = "n" + TOPIC_CHANGE_BY_OPERATOR_FLAG = "t" + OPERATOR_ABEY_CHANNEL_LIMITS = "e" + + +# class ModeOperationType(Enum): +# ENABLE_USER_QUIET_FLAG = "+q" +# DISABLE_USER_QUIET_FLAG = "-q" +# ADD_CHANNEL_PASSWORD = "+k" +# REMOVE_CHANNEL_PASSWORD = "-k" +# ADD_CHANNEL_USER_LIMITS = "+l" +# REMOVE_CHANNEL_USER_LIMITS = "-l" +# ADD_BAN_ON_USER = "+b" +# GET_BANNED_USERS = "+b" +# REMOVE_BAN_ON_USER = "-b" +# ADD_CHANNEL_OPERATOR = "+co" +# REMOVE_CHANNEL_OPERATOR = "-co" +# ENABLE_USER_VOICE_PERMISSION = "+cv" +# DISABLE_USER_VOICE_PERMISSION = "-cv" +# SET_INVITED_ONLY = "+i" +# REMOVE_INVITED_ONLY = "-i" +# SET_PRIVATE_CHANNEL_FLAG = "+p" +# REMOVE_PRIVATE_CHANNEL_FLAG = "-p" +# SET_SECRET_CHANNEL_FLAG = "+s" +# REMOVE_SECRET_CHANNEL_FLAG = "-s" +# SET_MODERATED_CHANNEL_FLAG = "+m" +# REMOVE_MODERATED_CHANNEL_FLAG = "-m" +# ENABLE_EXTERNAL_MESSAGES_FLAG = "+n" +# DISABLE_EXTERNAL_MESSAGES_FLAG = "-n" +# SET_TOPIC_CHANGE_BY_OPERATOR_FLAG = "+t" +# REMOVE_TOPIC_CHANGE_BY_OPERATOR_FLAG = "-t" +# SET_OPERATOR_ABEY_CHANNEL_LIMITS = "+e" +# REMOVE_OPERATOR_ABEY_CHANNEL_LIMITS = "-e" + + +class ModeRequestType(IntEnum): + GET_CHANNEL_MODES = 0 + SET_CHANNEL_MODES = 1 + SET_CHANNEL_USER_MODES = 2 + + +class TopicRequestType(IntEnum): + GET_CHANNEL_TOPIC = 0 + SET_CHANNEL_TOPIC = 1 + + +class ResponseCode(Enum): + WELCOME = "001" + USRIP = "302" + WHOISUSER = "311" + ENDOFWHO = "315" + ENDOFWHOIS = "318" + WHOISCHANNELS = "319" + LISTSTART = "321" + LIST = "322" + LISTEND = "323" + CHANNELMODEIS = "324" + NOTOPIC = "331" + TOPIC = "332" + WHOREPLY = "352" + NAMEREPLY = "353" + ENDOFNAMES = "366" + BANLIST = "367" + ENDOFBANLIST = "368" + GETKEY = "700" + ENDGETKEY = "701" + GETCKEY = "702" + ENDGETCKEY = "703" + GETCHANKEY = "704" + SECUREKEY = "705" + CDKEY = "706" + LOGIN = "707" + GETUDPRELAY = "712" + PONG = "PONG" + JOIN = "JOIN" + KICK = "KICK" + QUIT = "QUIT" + PART = "PART" + ATM = "ATM" + UTM = "UTM" + PRIVMSG = "PRIVMSG" + NOTICE = "NOTICE" + + +# region IRC error code +class IRCErrorCode(Enum): + NO_SUCH_NICK = "401" + NO_SUCH_CHANNEL = "403" + TOO_MANY_CHANNELS = "405" + ERR_ONE_US_NICK_NAME = "432" + NICK_NAME_IN_USE = "433" + MORE_PARAMETERS = "461" + CHANNEL_IS_FULL = "471" + INVITE_ONLY_CHAN = "473" + BANNED_FROM_CHAN = "474" + BAD_CHANNEL_KEY = "475" + BAD_CHAN_MASK = "476" + LOGIN_FAILED = "708" + NO_UNIQUE_NICK = "709" + UNIQUE_NICK_EXPIRED = "710" + REGISTER_NICK_FAILED = "711" + + +# region Peer room + + +class PeerRoomType(IntEnum): + Group = 0 + Staging = 1 + Title = 2 + Normal = 3 + + +class RequestType(Enum): + CRYPT = "CRYPT" + CDKEY = "CDKEY" + GETKEY = "GETKEY" + LIST = "LIST" + LOGIN = "LOGIN" + NICK = "NICK" + PING = "PING" + QUIT = "QUIT" + SETKEY = "SETKEY" + USER = "USER" + USRIP = "USRIP" + WHO = "WHO" + WHOIS = "WHOIS" + GETCHANKEY = "GETCHANKEY" + GETCKEY = "GETCKEY" + JOIN = "JOIN" + KICK = "KICK" + MODE = "MODE" + NAMES = "NAMES" + PART = "PART" + SETCHANKEY = "SETCHANKEY" + SETCKEY = "SETCKEY" + TOPIC = "TOPIC" + ATM = "ATM" + NOTICE = "NOTICE" + PRIVMSG = "PRIVMSG" + UTM = "UTM" diff --git a/src/frontends/gamespy/protocols/chat/aggregates/exceptions.py b/src/frontends/gamespy/protocols/chat/aggregates/exceptions.py new file mode 100644 index 000000000..e8cf2b469 --- /dev/null +++ b/src/frontends/gamespy/protocols/chat/aggregates/exceptions.py @@ -0,0 +1,158 @@ +from frontends.gamespy.protocols.chat.abstractions.contract import SERVER_DOMAIN +from frontends.gamespy.protocols.chat.aggregates.enums import IRCErrorCode + +from frontends.gamespy.library.exceptions.general import UniSpyException as ER + + +class ChatException(ER): + pass + + +class IRCException(ChatException): + error_code: "IRCErrorCode" + sending_buffer: "str" + + def __init__(self, message: "str", error_code: "IRCErrorCode") -> None: + super().__init__(message) + assert isinstance(error_code, IRCErrorCode) + self.error_code = error_code + + def build(self): + raise ChatException( + "IRCException is abstracted class, should not be initialized") + + +class IRCChannelException(IRCException): + channel_name: str + + def __init__(self, message: str, error_code: IRCErrorCode) -> None: + super().__init__(message, error_code) + + def build(self): + self.sending_buffer = f":{SERVER_DOMAIN} {self.error_code} * {self.channel_name} :{self.message}\r\n" # noqa: E501 + + +class ErrOneUSNickNameException(IRCException): + def __init__( + self, + message: "str", + error_code: "IRCErrorCode" = IRCErrorCode.ERR_ONE_US_NICK_NAME, + ) -> None: + super().__init__(message, error_code) + + +class LoginFailedException(IRCException): + def __init__( + self, + message: "str", + error_code: "IRCErrorCode" = IRCErrorCode.LOGIN_FAILED, + ) -> None: + super().__init__(message, error_code) + + +class MoreParametersException(IRCException): + def __init__( + self, + message: "str", + error_code: "IRCErrorCode" = IRCErrorCode.MORE_PARAMETERS, + ) -> None: + super().__init__(message, error_code) + + +class NickNameInUseException(IRCException): + old_nick: str + new_nick: str + + def __init__( + self, + old_nick: str, + new_nick: str, + message: str, + error_code: IRCErrorCode = IRCErrorCode.NICK_NAME_IN_USE, + ) -> None: + super().__init__(message, error_code) + self.old_nick = old_nick + self.new_nick = new_nick + + def build(self): + self.sending_buffer = f"{SERVER_DOMAIN} {self.error_code} {self.old_nick} {self.new_nick} *\r\n" # noqa: E501 + + +class NoSuchNickException(IRCException): + def __init__( + self, message: str, error_code: IRCErrorCode = IRCErrorCode.NO_SUCH_NICK + ) -> None: + super().__init__(message, error_code) + + +class NoUniqueNickException(IRCException): + def __init__( + self, message: str, error_code: IRCErrorCode = IRCErrorCode.NO_UNIQUE_NICK + ) -> None: + super().__init__(message, error_code) + + +class RegisterNickFaildException(IRCException): + def __init__( + self, message: str, error_code: IRCErrorCode = IRCErrorCode.REGISTER_NICK_FAILED + ) -> None: + super().__init__(message, error_code) + + +class TooManyChannelsException(IRCException): + def __init__( + self, message: str, error_code: IRCErrorCode = IRCErrorCode.TOO_MANY_CHANNELS + ) -> None: + super().__init__(message, error_code) + + +class UniqueNickExpiredException(IRCException): + def __init__( + self, message: str, error_code: IRCErrorCode = IRCErrorCode.UNIQUE_NICK_EXPIRED + ) -> None: + super().__init__(message, error_code) + + +# region Channel Exceptions + + +class BadChannelMaskException(IRCChannelException): + def __init__( + self, message: str, error_code: IRCErrorCode = IRCErrorCode.BAD_CHAN_MASK + ) -> None: + super().__init__(message, error_code) + + +class BadChannelKeyException(IRCChannelException): + def __init__( + self, message: str, error_code: IRCErrorCode = IRCErrorCode.BAD_CHANNEL_KEY + ) -> None: + super().__init__(message, error_code) + + +class BannedFromChanException(IRCChannelException): + def __init__( + self, message: str, error_code: IRCErrorCode = IRCErrorCode.BANNED_FROM_CHAN + ) -> None: + super().__init__(message, error_code) + + +class ChannelIsFullException(IRCChannelException): + def __init__( + self, message: str, error_code: IRCErrorCode = IRCErrorCode.CHANNEL_IS_FULL + ) -> None: + super().__init__(message, error_code) + + +class InviteOnlyChanException(IRCChannelException): + def __init__( + self, message: str, error_code: IRCErrorCode = IRCErrorCode.INVITE_ONLY_CHAN + ) -> None: + super().__init__(message, error_code) + + +class NoSuchChannelException(IRCChannelException): + def __init__( + self, message: str, error_code: IRCErrorCode = IRCErrorCode.NO_SUCH_CHANNEL + ) -> None: + super().__init__(message, error_code) diff --git a/src/frontends/gamespy/protocols/chat/aggregates/peer_room.py b/src/frontends/gamespy/protocols/chat/aggregates/peer_room.py new file mode 100644 index 000000000..b4af8e63b --- /dev/null +++ b/src/frontends/gamespy/protocols/chat/aggregates/peer_room.py @@ -0,0 +1,64 @@ +from frontends.gamespy.protocols.chat.aggregates.enums import PeerRoomType + + +class PeerRoom: + TitleRoomPrefix = "#GSP" + """ When game connects to the server, the player will enter the default channel for communicating with other players.""" + StagingRoomPrefix = "#GSP" + """ + When a player creates their own game and is waiting for others to join they are placed in a separate chat room called the "staging room"\n + Staging rooms have two title seperator like #GSP!xxxx!xxxx + """ + GroupRoomPrefix = "#GPG" + """ + group rooms is used split the list of games into categories (by gametype, skill, region, etc.). In this case, when entering the title room, the user would get a list of group rooms instead of a list of games\n + Group room have one title seperator like #GPG!xxxxxx + """ + TitleSeperator = "!" + + """ + Group room #GPG!622\n + Staging room #GSP!worms3!Ml4lz344lM\n + Normal room #islanbul + """ + + @staticmethod + def get_room_type(channel_name: str) -> PeerRoomType: + if PeerRoom.is_group_room(channel_name): + return PeerRoomType.Group + elif PeerRoom.is_staging_room(channel_name): + return PeerRoomType.Staging + elif PeerRoom.is_title_room(channel_name): + return PeerRoomType.Title + else: + return PeerRoomType.Normal + + @staticmethod + def is_staging_room(channel_name: str) -> bool: + a = channel_name.count(PeerRoom.TitleSeperator) == 2 + b = channel_name.startswith( + PeerRoom.StagingRoomPrefix, 0, len(PeerRoom.StagingRoomPrefix) + ) + return a and b + + @staticmethod + def is_title_room(channel_name: str) -> bool: + a = channel_name.count(PeerRoom.TitleSeperator) == 1 + b = channel_name.startswith( + PeerRoom.TitleRoomPrefix, 0, len(PeerRoom.TitleRoomPrefix) + ) + return a and b + + @staticmethod + def is_group_room(channel_name: str) -> bool: + a = channel_name.count(PeerRoom.TitleSeperator) == 1 + b = channel_name.startswith( + PeerRoom.GroupRoomPrefix, 0, len(PeerRoom.GroupRoomPrefix) + ) + return a and b + + +if __name__ == "__main__": + result = PeerRoom.get_room_type("#GSP!worms3!Ml4lz344lM") + result = PeerRoom.get_room_type("#GPG!700") + pass diff --git a/src/frontends/gamespy/protocols/chat/applications/broker.py b/src/frontends/gamespy/protocols/chat/applications/broker.py new file mode 100644 index 000000000..e99634ed2 --- /dev/null +++ b/src/frontends/gamespy/protocols/chat/applications/broker.py @@ -0,0 +1,7 @@ + + +from frontends.gamespy.library.network.websocket_brocker import WebSocketBrocker + + +# class Brocker(WebSocketBrocker): + diff --git a/src/frontends/gamespy/protocols/chat/applications/client.py b/src/frontends/gamespy/protocols/chat/applications/client.py new file mode 100644 index 000000000..1b0c2a597 --- /dev/null +++ b/src/frontends/gamespy/protocols/chat/applications/client.py @@ -0,0 +1,84 @@ +from frontends.gamespy.library.abstractions.client import ClientBase + +from frontends.gamespy.library.abstractions.switcher import SwitcherBase +from frontends.gamespy.library.log.log_manager import LogWriter +from frontends.gamespy.library.network.websocket_brocker import WebSocketBrocker +from frontends.gamespy.library.network.tcp_handler import TcpConnection +from frontends.gamespy.library.configs import CONFIG, ServerConfig + + +from frontends.gamespy.protocols.chat.abstractions.contract import ( + SERVER_DOMAIN, + BrockerMessage, +) + + +class ClientInfo: + previously_joined_channel: str | None + joined_channels: list[str] + nick_name: str | None + gamename: str | None + user_name: str | None + + def __init__(self) -> None: + self.joined_channels = [] + self.nick_name = None + self.gamename = None + self.user_name = None + self.previously_joined_channel = None + + @property + def irc_prefix(self) -> str: + assert self.nick_name + assert self.user_name + return f"{self.nick_name}!{self.user_name}@{SERVER_DOMAIN}" + + +class Client(ClientBase): + info: ClientInfo + brocker: WebSocketBrocker | None + + def __init__( + self, connection: TcpConnection, server_config: ServerConfig, logger: LogWriter + ): + super().__init__(connection, server_config, logger) + self.info = ClientInfo() + self.brocker = None + + def _create_switcher(self, buffer: bytes) -> SwitcherBase: + from frontends.gamespy.protocols.chat.applications.switcher import Switcher + + switcher = Switcher(self, buffer.decode()) + return switcher + + def on_connected(self) -> None: + self.start_brocker() + super().on_connected() + + def on_disconnected(self) -> None: + self.stop_brocker() + super().on_disconnected() + + def start_brocker(self): + self.brocker = WebSocketBrocker( + name=self.server_config.server_name, + url=f"{CONFIG.backend.url.replace('http', 'ws')}/GameSpy/Chat/ws", + call_back_func=self._process_brocker_message, + ) + self.brocker.subscribe() + + def stop_brocker(self): + assert self.brocker is not None + self.brocker.unsubscribe() + + def _process_brocker_message(self, message: str): + # responsible for receive message and send out + # TODO: check whether exception here will cause brocker stop + try: + assert isinstance(message, str) + r = BrockerMessage.model_validate_strings(message) + self.log_network_broadcast(r.model_dump_json()) + self.connection.send(r.message.encode()) + except Exception as e: + # todo change to log and handle exception here + print(e) diff --git a/src/frontends/gamespy/protocols/chat/applications/handlers.py b/src/frontends/gamespy/protocols/chat/applications/handlers.py new file mode 100644 index 000000000..bf7697f02 --- /dev/null +++ b/src/frontends/gamespy/protocols/chat/applications/handlers.py @@ -0,0 +1,453 @@ +from frontends.gamespy.library.encryption.gs_encryption import ChatCrypt +from frontends.gamespy.protocols.chat.applications.client import Client +from frontends.gamespy.protocols.chat.contracts.results import ( + AtmResult, + NoticeResult, + PrivateResult, + SetCKeyResult, + UtmResult, + GetCKeyResult, + GetChannelKeyResult, + JoinResult, + KickResult, + ModeResult, + NamesResult, + PartResult, + SetChannelKeyResult, + TopicResult, + CryptResult, + GetKeyResult, + ListResult, + LoginResult, + NickResult, + PingResult, + UserIPResult, + WhoIsResult, + WhoResult, +) +from frontends.gamespy.protocols.chat.contracts.responses import ( + AtmResponse, + GetCKeyResponse, + GetChannelKeyResponse, + JoinResponse, + KickResponse, + ModeResponse, + NamesResponse, + NoticeResponse, + PartResponse, + PrivateResponse, + SetCKeyResponse, + SetChannelKeyResponse, + TopicResponse, + CdKeyResponse, + CryptResponse, + GetKeyResponse, + ListResponse, + LoginResponse, + NickResponse, + PingResponse, + UtmResponse, + UserIPResponse, + WhoIsResponse, + WhoResponse, +) +from frontends.gamespy.protocols.chat.contracts.requests import ( + AtmRequest, + NoticeRequest, + PrivateRequest, + PublishMessageRequest, + UtmRequest, + GetCKeyRequest, + GetChannelKeyRequest, + JoinRequest, + KickRequest, + ModeRequest, + NamesRequest, + PartRequest, + SetCKeyRequest, + SetChannelKeyRequest, + TopicRequest, + CdkeyRequest, + CryptRequest, + GetKeyRequest, + InviteRequest, + ListRequest, + LoginRequest, + NickRequest, + PingRequest, + QuitRequest, + SetKeyRequest, + UserIPRequest, + UserRequest, + WhoIsRequest, + WhoRequest, + GetUdpRelayRequest, +) +from frontends.gamespy.protocols.chat.aggregates.enums import ModeRequestType +from frontends.gamespy.protocols.chat.abstractions.contract import RequestBase +from frontends.gamespy.protocols.chat.abstractions.handler import ( + ChannelHandlerBase, + CmdHandlerBase, + MessageHandlerBase, + PostLoginHandlerBase, +) +# region General + + +class CdKeyHandler(CmdHandlerBase): + _request: CdkeyRequest + + def __init__(self, client: Client, request: CdkeyRequest): + assert isinstance(request, CdkeyRequest) + super().__init__(client, request) + + def _response_construct(self) -> None: + self._response = CdKeyResponse() + + +class CryptHandler(CmdHandlerBase): + _request: CryptRequest + _result: CryptResult + + def __init__(self, client: Client, request: RequestBase): + assert isinstance(request, CryptRequest) + super().__init__(client, request) + self._result_cls = CryptResult + + def _data_operate(self) -> None: + super()._data_operate() + self._client.info.gamename = self._request.gamename + + def _response_construct(self) -> None: + self._response = CryptResponse() + + def _response_send(self) -> None: + super()._response_send() + self._client.crypto = ChatCrypt(self._result.secret_key) + + +class GetKeyHandler(CmdHandlerBase): + _request: GetKeyRequest + _result: GetKeyResult + _response: GetKeyResponse + + def __init__(self, client: Client, request: GetKeyRequest): + assert isinstance(request, GetKeyRequest) + super().__init__(client, request) + + +class GetUdpRelayHandler(CmdHandlerBase): + _request: GetUdpRelayRequest + + def __init__(self, client: Client, request: GetUdpRelayRequest): + assert isinstance(request, GetUdpRelayRequest) + super().__init__(client, request) + + +class InviteHandler(CmdHandlerBase): + _request: InviteRequest + + def __init__(self, client: Client, request: InviteRequest): + assert isinstance(request, InviteRequest) + super().__init__(client, request) + + +class ListHandler(PostLoginHandlerBase): + _request: ListRequest + _result: ListResult + _response: ListResponse + + def __init__(self, client: Client, request: ListRequest): + assert isinstance(request, ListRequest) + super().__init__(client, request) + + +class LoginHandler(CmdHandlerBase): + _request: LoginRequest + _result: LoginResult + _response: LoginResponse + + def __init__(self, client: Client, request: LoginRequest): + assert isinstance(request, LoginRequest) + super().__init__(client, request) + + +class NickHandler(CmdHandlerBase): + _request: NickRequest + _result: NickResult + _response: NickResponse + + def __init__(self, client: Client, request: NickRequest): + assert isinstance(request, NickRequest) + super().__init__(client, request) + + def _data_operate(self) -> None: + super()._data_operate() + self._client.info.nick_name = self._request.nick_name + + +class PingHandler(CmdHandlerBase): + _request: PingRequest + _result: PingResult + _response: PingResponse + + def __init__(self, client: Client, request: PingRequest): + assert isinstance(request, PingRequest) + super().__init__(client, request) + + +class QuitHandler(CmdHandlerBase): + _request: QuitRequest + + def __init__(self, client: Client, request: QuitRequest): + assert isinstance(request, QuitRequest) + super().__init__(client, request) + + +class SetKeyHandler(PostLoginHandlerBase): + _request: SetKeyRequest + + def __init__(self, client: Client, request: SetKeyRequest): + assert isinstance(request, SetKeyRequest) + super().__init__(client, request) + + +class UserHandler(CmdHandlerBase): + _request: UserRequest + + def __init__(self, client: Client, request: UserRequest): + assert isinstance(request, UserRequest) + super().__init__(client, request) + + def _data_operate(self) -> None: + super()._data_operate() + self._client.info.user_name = self._request.user_name + + +class UserIPHandler(CmdHandlerBase): + _request: UserIPRequest + _response: UserIPResponse + + def __init__(self, client: Client, request: UserIPRequest): + assert isinstance(request, UserIPRequest) + super().__init__(client, request) + + def _request_check(self) -> None: + super()._request_check() + self._request.remote_ip = self._client.connection.remote_ip + + def _data_operate(self) -> None: + super()._data_operate() + self._result = UserIPResult( + remote_ip=self._client.connection.remote_ip) + + +class WhoHandler(CmdHandlerBase): + _request: WhoRequest + _result: WhoResult + _response: WhoResponse + + def __init__(self, client: Client, request: WhoRequest): + assert isinstance(request, WhoRequest) + super().__init__(client, request) + + +class WhoIsHandler(CmdHandlerBase): + _request: WhoIsRequest + _result: WhoIsResult + _response: WhoIsResponse + + def __init__(self, client: Client, request: WhoIsRequest): + assert isinstance(request, WhoIsRequest) + super().__init__(client, request) + + +# region channel + + +class GetChannelKeyHandler(ChannelHandlerBase): + _request: GetChannelKeyRequest + _result: GetChannelKeyResult + _response: GetChannelKeyResponse + + def __init__(self, client: Client, request: GetChannelKeyRequest): + assert isinstance(request, GetChannelKeyRequest) + super().__init__(client, request) + + def _publish_message(self): + pass + + def _update_channel_cache(self): + pass + + +class GetCKeyHandler(ChannelHandlerBase): + _request: GetCKeyRequest + _result: GetCKeyResult + _response: GetCKeyResponse + + def __init__(self, client: Client, request: GetCKeyRequest): + assert isinstance(request, GetCKeyRequest) + super().__init__(client, request) + + +class JoinHandler(ChannelHandlerBase): + _request: JoinRequest + _result: JoinResult + _response: JoinResponse + + def __init__(self, client: Client, request: JoinRequest): + assert isinstance(request, JoinRequest) + super().__init__(client, request) + self._is_broadcast = True + + def _response_send(self) -> None: + super()._response_send() + # gamespy sdk join require ciNameReplyHandler + names_raw = NamesRequest.build(self._request.channel_name) + names_req = NamesRequest(names_raw) + names_handler = NamesHandler(self._client, names_req) + names_handler.handle() + + mode_raw = ModeRequest.build(self._request.channel_name) + mode_req = ModeRequest(mode_raw) + mode_handler = ModeHandler(self._client, mode_req) + mode_handler.handle() + + +class KickHandler(ChannelHandlerBase): + _request: KickRequest + _result: KickResult + _response: KickResponse + + def __init__(self, client: Client, request: KickRequest): + assert isinstance(request, KickRequest) + super().__init__(client, request) + + +class ModeHandler(ChannelHandlerBase): + _request: ModeRequest + _result: ModeResult + _response: ModeResponse + + def __init__(self, client: Client, request: ModeRequest): + assert isinstance(request, ModeRequest) + super().__init__(client, request) + + def _request_check(self) -> None: + super()._request_check() + if self._request.request_type == ModeRequestType.SET_CHANNEL_MODES: + self._is_fetching = False + if self._request.request_type == [ + ModeRequestType.SET_CHANNEL_MODES, + ModeRequestType.SET_CHANNEL_USER_MODES, + ]: + self._is_broadcast = True + + def _response_construct(self): + if self._request.request_type == ModeRequestType.GET_CHANNEL_MODES: + super()._response_construct() + + +class NamesHandler(ChannelHandlerBase): + _request: NamesRequest + _result: NamesResult + _response: NamesResponse + + def __init__(self, client: Client, request: NamesRequest): + assert isinstance(request, NamesRequest) + super().__init__(client, request) + + +class PartHandler(ChannelHandlerBase): + _request: PartRequest + _result: PartResult + _response: PartResponse + + def __init__(self, client: Client, request: PartRequest): + assert isinstance(request, PartRequest) + super().__init__(client, request) + + +class SetChannelKeyHandler(ChannelHandlerBase): + _request: SetChannelKeyRequest + _result: SetChannelKeyResult + _response: SetChannelKeyResponse + + def __init__(self, client: Client, request: SetChannelKeyRequest): + assert isinstance(request, SetChannelKeyRequest) + super().__init__(client, request) + self._is_broadcast = True + + +class SetCKeyHandler(ChannelHandlerBase): + _request: SetCKeyRequest + _result: SetCKeyResult + _response: SetCKeyResponse + + def __init__(self, client: Client, request: SetCKeyRequest): + assert isinstance(request, SetCKeyRequest) + super().__init__(client, request) + + +class TopicHandler(ChannelHandlerBase): + _request: TopicRequest + _result: TopicResult + _response: TopicResponse + + def __init__(self, client: Client, request: TopicRequest): + assert isinstance(request, TopicRequest) + super().__init__(client, request) + self._is_broadcast = True + + +# region Message + + +class ATMHandler(MessageHandlerBase): + _request: AtmRequest + _result: AtmResult + _response: AtmResponse + + def __init__(self, client: Client, request: AtmRequest): + assert isinstance(request, AtmRequest) + super().__init__(client, request) + + +class UTMHandler(MessageHandlerBase): + _request: UtmRequest + _result: UtmResult + _response: UtmResponse + + def __init__(self, client: Client, request: UtmRequest): + assert isinstance(request, UtmRequest) + super().__init__(client, request) + + +class NoticeHandler(MessageHandlerBase): + _request: NoticeRequest + _result: NoticeResult + _response: NoticeResponse + + def __init__(self, client: Client, request: NoticeRequest): + assert isinstance(request, NoticeRequest) + super().__init__(client, request) + + +class PrivateHandler(MessageHandlerBase): + _request: PrivateRequest + _result: PrivateResult + _response: PrivateResponse + + def __init__(self, client: Client, request: PrivateRequest): + assert isinstance(request, PrivateRequest) + super().__init__(client, request) + + +# region publish message handler +class PublishMessageHandler(CmdHandlerBase): + _request: PublishMessageRequest + + def __init__(self, client: Client, request: PublishMessageRequest): + assert isinstance(request, PublishMessageRequest) + super().__init__(client, request) diff --git a/src/frontends/gamespy/protocols/chat/applications/server_launcher.py b/src/frontends/gamespy/protocols/chat/applications/server_launcher.py new file mode 100644 index 000000000..a4e0e855a --- /dev/null +++ b/src/frontends/gamespy/protocols/chat/applications/server_launcher.py @@ -0,0 +1,21 @@ +from frontends.gamespy.library.abstractions.server_launcher import ServiceBase, ServicesFactory +from frontends.gamespy.library.network.tcp_handler import TcpServer +from frontends.gamespy.protocols.chat.applications.client import Client + + +class Service(ServiceBase): + + def __init__(self) -> None: + super().__init__( + config_name="Chat", + client_cls=Client, + network_server_cls=TcpServer, + ) + + +if __name__ == "__main__": + from frontends.gamespy.library.extentions.debug_helper import DebugHelper + + chat = Service() + helper = DebugHelper("./frontends/", ServicesFactory([chat])) + helper.start() diff --git a/src/frontends/gamespy/protocols/chat/applications/switcher.py b/src/frontends/gamespy/protocols/chat/applications/switcher.py new file mode 100644 index 000000000..e55e78294 --- /dev/null +++ b/src/frontends/gamespy/protocols/chat/applications/switcher.py @@ -0,0 +1,153 @@ + +from typing import TYPE_CHECKING +from frontends.gamespy.library.abstractions.client import ClientBase +from frontends.gamespy.library.abstractions.handler import CmdHandlerBase +from frontends.gamespy.library.abstractions.switcher import SwitcherBase +from frontends.gamespy.protocols.chat.aggregates.enums import RequestType +from frontends.gamespy.protocols.chat.contracts.requests import ( + GetCKeyRequest, + GetChannelKeyRequest, + JoinRequest, + KickRequest, + ModeRequest, + NamesRequest, + PartRequest, + SetCKeyRequest, + SetChannelKeyRequest, + TopicRequest, + CdkeyRequest, + CryptRequest, + GetKeyRequest, + ListRequest, + LoginRequest, + NickRequest, + PingRequest, + QuitRequest, + SetKeyRequest, + UserIPRequest, + UserRequest, + WhoIsRequest, + WhoRequest, + AtmRequest, + NoticeRequest, + PrivateRequest, + UtmRequest, +) +from frontends.gamespy.protocols.chat.applications.handlers import ( + GetCKeyHandler, + GetChannelKeyHandler, + JoinHandler, + KickHandler, + ModeHandler, + NamesHandler, + PartHandler, + SetCKeyHandler, + SetChannelKeyHandler, + TopicHandler, + CdKeyHandler, + CryptHandler, + GetKeyHandler, + ListHandler, + LoginHandler, + NickHandler, + PingHandler, + QuitHandler, + SetKeyHandler, + UserHandler, + UserIPHandler, + WhoHandler, + WhoIsHandler, + ATMHandler, + NoticeHandler, + PrivateHandler, + UTMHandler, +) + +from frontends.gamespy.protocols.chat.applications.client import Client + + +class Switcher(SwitcherBase): + _raw_request: str + _client: Client + + def __init__(self, client: ClientBase, raw_request: str) -> None: + assert isinstance(raw_request, str) + super().__init__(client, raw_request) + + def _process_raw_request(self) -> None: + splited_raw_requests = [ + req for req in self._raw_request.replace("\r", "").split("\n") if req] + for raw_request in splited_raw_requests: + name = raw_request.strip(" ").split(" ")[0] + if name not in RequestType: + self._client.log_debug( + f"Request: {name} is not a valid request.") + continue + self._requests.append((RequestType(name), raw_request)) + + def _create_cmd_handlers(self, name: RequestType, raw_request: str) -> CmdHandlerBase | None: + assert isinstance(name, RequestType) + r_type = RequestType(name) + match r_type: + # region General + case RequestType.CRYPT: + return CryptHandler(self._client, CryptRequest(raw_request)) + case RequestType.CDKEY: + return CdKeyHandler(self._client, CdkeyRequest(raw_request)) + case RequestType.GETKEY: + return GetKeyHandler(self._client, GetKeyRequest(raw_request)) + case RequestType.LIST: + return ListHandler(self._client, ListRequest(raw_request)) + case RequestType.LOGIN: + return LoginHandler(self._client, LoginRequest(raw_request)) + case RequestType.NICK: + return NickHandler(self._client, NickRequest(raw_request)) + case RequestType.PING: + return PingHandler(self._client, PingRequest(raw_request)) + case RequestType.QUIT: + return QuitHandler(self._client, QuitRequest(raw_request)) + case RequestType.SETKEY: + return SetKeyHandler(self._client, SetKeyRequest(raw_request)) + case RequestType.USER: + return UserHandler(self._client, UserRequest(raw_request)) + case RequestType.USRIP: + return UserIPHandler(self._client, UserIPRequest(raw_request)) + case RequestType.WHO: + return WhoHandler(self._client, WhoRequest(raw_request)) + case RequestType.WHOIS: + return WhoIsHandler(self._client, WhoIsRequest(raw_request)) + + # Channel commands + case RequestType.GETCHANKEY: + return GetChannelKeyHandler(self._client, GetChannelKeyRequest(raw_request)) + case RequestType.GETCKEY: + return GetCKeyHandler(self._client, GetCKeyRequest(raw_request)) + case RequestType.JOIN: + return JoinHandler(self._client, JoinRequest(raw_request)) + case RequestType.KICK: + return KickHandler(self._client, KickRequest(raw_request)) + case RequestType.MODE: + return ModeHandler(self._client, ModeRequest(raw_request)) + case RequestType.NAMES: + return NamesHandler(self._client, NamesRequest(raw_request)) + case RequestType.PART: + return PartHandler(self._client, PartRequest(raw_request)) + case RequestType.SETCHANKEY: + return SetChannelKeyHandler(self._client, SetChannelKeyRequest(raw_request)) + case RequestType.SETCKEY: + return SetCKeyHandler(self._client, SetCKeyRequest(raw_request)) + case RequestType.TOPIC: + return TopicHandler(self._client, TopicRequest(raw_request)) + + # Message commands + case RequestType.ATM: + return ATMHandler(self._client, AtmRequest(raw_request)) + case RequestType.NOTICE: + return NoticeHandler(self._client, NoticeRequest(raw_request)) + case RequestType.PRIVMSG: + return PrivateHandler(self._client, PrivateRequest(raw_request)) + case RequestType.UTM: + return UTMHandler(self._client, UtmRequest(raw_request)) + case _: + return None + # endregion diff --git a/src/frontends/gamespy/protocols/chat/contracts/requests.py b/src/frontends/gamespy/protocols/chat/contracts/requests.py new file mode 100644 index 000000000..f752fb01f --- /dev/null +++ b/src/frontends/gamespy/protocols/chat/contracts/requests.py @@ -0,0 +1,632 @@ +from frontends.gamespy.protocols.chat.abstractions.handler import ( + ChannelRequestBase, + MessageRequestBase, +) +from frontends.gamespy.protocols.chat.aggregates.enums import ( + GetKeyRequestType, + ModeName, + ModeOperation, + ModeRequestType, + TopicRequestType, +) + +import re +from frontends.gamespy.library.extentions.string_extentions import ( + convert_keystr_to_list, + convert_kvstring_to_dictionary, +) +from frontends.gamespy.protocols.chat.abstractions.contract import RequestBase +from frontends.gamespy.protocols.chat.aggregates.enums import ( + LoginRequestType, + WhoRequestType, +) +from frontends.gamespy.protocols.chat.aggregates.exceptions import ChatException +from frontends.gamespy.protocols.chat.aggregates.exceptions import ( + NickNameInUseException, +) + +# General + + +class CdkeyRequest(RequestBase): + cdkey: str + + def parse(self): + super().parse() + if len(self._cmd_params) < 1: + raise ChatException("The number of IRC cmdParams are incorrect.") + + self.cdkey = self._cmd_params[0] + + +class CryptRequest(RequestBase): + version_id: str + gamename: str + + def parse(self): + super().parse() + if len(self._cmd_params) < 3: + raise ChatException( + "The number of IRC params in CRYPT request is incorrect." + ) + self.version_id = self._cmd_params[1] + self.gamename = self._cmd_params[2] + + +class InviteRequest(RequestBase): + channel_name: str + nick_name: str + + def parse(self): + super().parse() + if len(self._cmd_params) > 2: + raise ChatException( + "The number of IRC cmd params in Invite request is incorrect." + ) + self.channel_name = self._cmd_params[0] + self.nick_name = self._cmd_params[1] + + +class ListLimitRequest(RequestBase): + max_number_of_channels: int + filter: str + + def parse(self): + super().parse() + if len(self._cmd_params) != 2: + raise ChatException( + "The number of IRC cmd params in ListLimit request is incorrect." + ) + try: + self.max_number_of_channels = int(self._cmd_params[0]) + except Exception: + raise ChatException("The max number format is incorrect.") + + self.filter = self._cmd_params[1] + + +class ListRequest(RequestBase): + is_searching_channel: bool = False + is_searching_user: bool = False + filter: str + + def parse(self): + super().parse() + if self._cmd_params is None or len(self._cmd_params) == 0: + raise ChatException("The Search filter is missing.") + + self.is_searching_channel = True + self.filter = self._cmd_params[0] + + +class LoginPreAuth(RequestBase): + auth_token: str + partner_challenge: str + + def parse(self): + super().parse() + self.auth_token = self._cmd_params[0] + self.partner_challenge = self._cmd_params[1] + + +class LoginRequest(RequestBase): + request_type: LoginRequestType + namespace_id: int + nick_name: str + email: str + unique_nick: str + password_hash: str + + def parse(self): + super().parse() + try: + self.namespace_id = int(self._cmd_params[0]) + except Exception: + raise ChatException("The namespaceid format is incorrect.") + + if self._cmd_params[1] == "*": + self.request_type = LoginRequestType.NICK_AND_EMAIL_LOGIN + self.password_hash = self._cmd_params[2] + assert isinstance(self._long_param, str) + if self._long_param.count("@") != 2: + raise ChatException("The profile nick format is incorrect.") + + profile_nick_index = self._long_param.index("@") + self.nick_name = self._long_param[0:profile_nick_index] + self.email = self._long_param[profile_nick_index + 1:] + return + + self.request_type = LoginRequestType.UNIQUE_NICK_LOGIN + self.unique_nick = self._cmd_params[1] + self.password_hash = self._cmd_params[2] + + +class NickRequest(RequestBase): + _invalid_chars = "#@$%^&()~" + nick_name: str + + def parse(self): + super().parse() + if len(self._cmd_params) == 1: + self.nick_name = self._cmd_params[0] + elif self._long_param is None: + assert isinstance(self._long_param, str) + self.nick_name = self._long_param + else: + raise ChatException("NICK request is invalid.") + + for c in self._invalid_chars: + if c in self.nick_name: + raise NickNameInUseException( + self.nick_name, + self.nick_name, + f"The nick name: {self.nick_name} contains invalid character.", + ) + + +class PingRequest(RequestBase): + pass + + +class PongRequest(RequestBase): + echo_message: str + + def parse(self): + super().parse() + if self._long_param is None: + raise ChatException("Echo message is missing.") + self.echo_message = self._long_param + + +class QuitRequest(RequestBase): + reason: str + + def parse(self): + super().parse() + if self._long_param is None: + raise ChatException("Quit reason is missing.") + + self.reason = self._long_param + + +class RegisterNickRequest(RequestBase): + namespace_id: int + unique_nick: str + cdkey: str + + def parse(self): + super().parse() + assert isinstance(self._cmd_params, list) + self.namespace_id = int(self._cmd_params[0]) + self.unique_nick = self._cmd_params[1] + self.cdkey = self._cmd_params[2] + + +class SetKeyRequest(RequestBase): + key_values: dict[str, str] + + def parse(self): + super().parse() + if self._long_param is None: + raise ChatException("The keys and values are missing.") + + self.key_values = convert_kvstring_to_dictionary(self._long_param) + + +class UserIPRequest(RequestBase): + remote_ip: str + + +class UserRequest(RequestBase): + user_name: str + local_ip_address: str + server_name: str + name: str + + def __init__(self, raw_request: str) -> None: + super().__init__(raw_request) + + def parse(self): + super().parse() + if len(self._cmd_params) == 3: + self.user_name = self._cmd_params[0] + self.local_ip_address = self._cmd_params[1] + self.server_name = self._cmd_params[2] + else: + self.local_ip_address = self._cmd_params[0] + self.server_name = self._cmd_params[1] + + assert isinstance(self._long_param, str) + self.name = self._long_param + + +class WhoIsRequest(RequestBase): + nick_name: str + + def parse(self): + super().parse() + if len(self._cmd_params) != 1: + raise ChatException( + "The number of IRC cmd params in WHOIS request is incorrect." + ) + + self.nick_name = self._cmd_params[0] + + +class WhoRequest(RequestBase): + request_type: WhoRequestType + channel_name: str + nick_name: str + + def parse(self): + super().parse() + if len(self._cmd_params) != 1: + raise ChatException( + "The number of IRC cmd params in WHO request is incorrect." + ) + + if "#" in self._cmd_params[0]: + self.request_type = WhoRequestType.GET_CHANNEL_USER_INFO + self.channel_name = self._cmd_params[0] + return + + self.request_type = WhoRequestType.GET_USER_INFO + self.nick_name = self._cmd_params[0] + + +class GetKeyRequest(RequestBase): + is_get_all_user: bool = False + nick_name: str + cookie: str + unknown_cmd_param: str + keys: list[str] + + def parse(self) -> None: + super().parse() + if len(self._cmd_params) < 2: + raise ChatException( + "The number of IRC cmd params in GETKEY request is incorrect." + ) + + if self._long_param is None: + raise ChatException( + "The number of IRC cmd params in GETKEY request is incorrect." + ) + + self.nick_name = self._cmd_params[0] + self.cookie = self._cmd_params[1] + self.unknown_cmd_param = self._cmd_params[2] + + self._long_param = self._long_param[: len(self._long_param)] + if self.nick_name == "*": + self.is_get_all_user = True + + self.keys = convert_keystr_to_list(self._long_param) + + +# region Channel + + +class GetChannelKeyRequest(ChannelRequestBase): + """ + sprintf(buffer, "GETCHANKEY %s %s 0 :", channel, cookie); + """ + + cookie: str + keys: list + + def parse(self): + super().parse() + + if len(self._cmd_params) != 3: + raise ChatException("The cmdParams number is invalid.") + + if self._long_param is None or self._long_param[-1] != "\0": + raise ChatException("The longParam number is invalid.") + self.cookie = self._cmd_params[1] + self.keys = self._long_param.strip("\\").rstrip("\0").split("\\") + + +class GetCKeyRequest(ChannelRequestBase): + """ + sprintf(buffer, "GETCKEY %s %s %s 0 :", channel, nick, cookie); + """ + + nick_name: str | None + cookie: str + keys: list + request_type: GetKeyRequestType + + def parse(self): + super().parse() + if len(self._cmd_params) != 4: + raise ChatException("The number of IRC parameters are incorrect.") + if self._long_param is None: + raise ChatException("The IRC long parameter is incorrect.") + + self.nick_name = self._cmd_params[1] + if self.nick_name == "*": + self.request_type = GetKeyRequestType.GET_CHANNEL_ALL_USER_KEY_VALUE + else: + self.request_type = GetKeyRequestType.GET_CHANNEL_SPECIFIC_USER_KEY_VALUE + + self.cookie = self._cmd_params[2] + + if "\0" not in self._long_param and "\\" not in self._long_param: + raise ChatException("The key provide is incorrect.") + + self.keys = self._long_param.strip("\\").rstrip("\0").split("\\") + + +class GetUdpRelayRequest(ChannelRequestBase): + pass + + +class JoinRequest(ChannelRequestBase): + password: str | None + + def __init__(self, raw_request): + super().__init__(raw_request) + self.password = None + + def parse(self): + super().parse() + if len(self._cmd_params) > 2: + raise ChatException("The number of IRC parameters are incorrect.") + + if len(self._cmd_params) == 2: + self.password = self._cmd_params[1] + + +class KickRequest(ChannelRequestBase): + kickee_nick_name: str + reason: str + + def parse(self): + super().parse() + if len(self._cmd_params) != 2: + raise ChatException("The number of IRC parameters are incorrect.") + self.kickee_nick_name = self._cmd_params[1] + + if self._long_param is None: + raise ChatException("The IRC long parameters is missing.") + + self.reason = self._long_param + + +class ModeRequest(ChannelRequestBase): + # request: + # "MODE +/-q" + + # "MODE +/-k " + + # "MODE +l " + # "MODE -l" + + # "MODE +b *!*@" actually we do not care about this request + # "MODE +/-b " + + # "MODE +/-co " + # "MODE +/-cv " + + # "MODE " + # "MODE " + request_type: ModeRequestType + mode_operations: dict[str, str] + """ + , + o,+ + i,+ + """ + nick_name: str + user_name: str + limit_number: int + mode_flag: str + password: str | None + + def parse(self): + super().parse() + self.mode_operations = {} + if len(self._cmd_params) == 1: + self.request_type = ModeRequestType.GET_CHANNEL_MODES + elif len(self._cmd_params) == 2 or len(self._cmd_params) == 3: + self.request_type = ModeRequestType.SET_CHANNEL_MODES + self.mode_flag = self._cmd_params[1] + mode_flags = [ + s for s in re.split(r"(?=\+|\-)", self.mode_flag) if s.strip() + ] + mode_flags = list(filter(None, mode_flags)) + self.process_mode_flags(mode_flags) + else: + raise ChatException("The number of IRC parameters are incorrect.") + + def process_mode_flags(self, mode_flags: list[str]): + for flag in mode_flags: + try: + operation = ModeOperation(flag[0]) + flag_name = ModeName(flag[1:]) + except Exception: + continue + match flag_name: + case ( + ModeName.OPERATOR_ABEY_CHANNEL_LIMITS + | ModeName.TOPIC_CHANGE_BY_OPERATOR_FLAG + | ModeName.EXTERNAL_MESSAGES_FLAG + | ModeName.MODERATED_CHANNEL_FLAG + | ModeName.SECRET_CHANNEL_FLAG + | ModeName.INVITED_ONLY + | ModeName.PRIVATE_CHANNEL_FLAG + | ModeName.USER_QUIET_FLAG + | ModeName.CHANNEL_PASSWORD + ): + self.mode_operations[flag_name.value] = operation.value + case ModeName.CHANNEL_USER_LIMITS: + if operation == ModeOperation.SET: + self.channel_name = self._cmd_params[0] + self.limit_number = int(self._cmd_params[2]) + else: + self.channel_name = self._cmd_params[0] + self.mode_operations[flag_name.value] = operation.value + case ModeName.BAN_ON_USER: + self.channel_name = self._cmd_params[0] + if len(self._cmd_params) == 3: + self.nick_name = self._cmd_params[2] + self.mode_operations[flag_name.value] = operation.value + case ModeName.CHANNEL_OPERATOR | ModeName.USER_VOICE_PERMISSION: + self.channel_name = self._cmd_params[0] + self.user_name = self._cmd_params[2] + self.mode_operations[flag_name.value] = operation.value + + @staticmethod + def build(channel_name: str): + """ + build the irc request for get the channel modes + """ + raw = f"MODE {channel_name}" + return raw + + +class NamesRequest(ChannelRequestBase): + @staticmethod + def build(channel_name: str): + """ + build raw request to get channel mode + """ + raw = f"NAMES {channel_name}" + return raw + + +class PartRequest(ChannelRequestBase): + reason: str = "Unknown reason" + + def __init__(self, raw_request: str | None = None) -> None: + if raw_request is not None: + super().__init__(raw_request) + + def parse(self): + super().parse() + + if self._long_param is None: + raise ChatException("The reason of living channel is missing.") + self.reason = self._long_param + + +class SetChannelKeyRequest(ChannelRequestBase): + """ + sprintf(buffer, "SETCHANKEY %s :", channel); + BCAST is broadcast flag + """ + + key_value_string: str + key_values: dict[str, str] + is_broadcast: bool + + def parse(self): + super().parse() + if self._long_param is None: + raise ChatException("Channel keys and values are missing.") + self._long_param = self._long_param[1:] + self.key_value_string = self._long_param + self.key_values = convert_kvstring_to_dictionary(self.key_value_string) + is_broadcast = False + for key in self.key_values: + if "b_" in key: + is_broadcast = True + break + if is_broadcast: + self.cookie = "BCAST" + self.is_broadcast = True + +class SetCKeyRequest(ChannelRequestBase): + """ + sprintf(buffer, "SETCKEY %s %s :", channel, user); + BCAST is broadcast flag + """ + + nick_name: str + cookie: str + is_broadcast: bool + key_value_string: str + key_values: dict[str, str] + + def parse(self) -> None: + super().parse() + if self._cmd_params is None: + raise ChatException( + "The cmdParams from SETCKEY request are missing.") + + if self._long_param is None: + raise ChatException( + "The longParam from SETCKEY request is missing.") + + self.channel_name = self._cmd_params[0] + self.nick_name = self._cmd_params[1] + self.key_value_string = self._long_param[1:] + self.key_values = convert_kvstring_to_dictionary(self.key_value_string) + is_broadcast = False + for key in self.key_values: + if "b_" in key: + is_broadcast = True + break + if is_broadcast: + self.cookie = "BCAST" + self.is_broadcast = True + + +class SetGroupRequest(ChannelRequestBase): + group_name: str + + def parse(self) -> None: + super().parse() + if len(self._cmd_params) != 1: + raise ChatException( + "the number of IRC cmd params in GETKEY request is incorrect." + ) + self.group_name = self._cmd_params[0] + + +class TopicRequest(ChannelRequestBase): + channel_topic: str + request_type: TopicRequestType + + def parse(self) -> None: + super().parse() + if self._long_param is None: + self.request_type = TopicRequestType.GET_CHANNEL_TOPIC + else: + self.request_type = TopicRequestType.SET_CHANNEL_TOPIC + self.channel_topic = self._long_param + + +# region Message + + +class AtmRequest(MessageRequestBase): + pass + + +class NoticeRequest(MessageRequestBase): + pass + + +class PrivateRequest(MessageRequestBase): + pass + + +class UtmRequest(MessageRequestBase): + pass + + +# region publish message + +class PublishMessageRequest(RequestBase): + """ + this class is use to send broadcast message to backends + """ + + def parse(self) -> None: + """ + we do not need to parse any irc request, we just send it to backend + """ + pass + # return super().parse() diff --git a/src/frontends/gamespy/protocols/chat/contracts/responses.py b/src/frontends/gamespy/protocols/chat/contracts/responses.py new file mode 100644 index 000000000..ceb35429b --- /dev/null +++ b/src/frontends/gamespy/protocols/chat/contracts/responses.py @@ -0,0 +1,450 @@ +from frontends.gamespy.protocols.chat.abstractions.handler import ChannelResponseBase +from frontends.gamespy.protocols.chat.aggregates.enums import ( + WhoRequestType, + ResponseCode, +) +from frontends.gamespy.protocols.chat.contracts.results import ( + GetCKeyResult, + GetChannelKeyResult, + JoinResult, + KickResult, + ModeResult, + NamesResult, + NamesResultData, + PartResult, + SetCKeyResult, + SetChannelKeyResult, + TopicResult, + AtmResult, + NoticeResult, + PrivateResult, + UtmResult, + GetKeyResult, + ListResult, + LoginResult, + NickResult, + PingResult, + UserIPResult, + WhoIsResult, + WhoResult, +) +from frontends.gamespy.protocols.chat.contracts.requests import ( + GetCKeyRequest, + GetChannelKeyRequest, + JoinRequest, + KickRequest, + ModeRequest, + NamesRequest, + PartRequest, + SetCKeyRequest, + SetChannelKeyRequest, + TopicRequest, + AtmRequest, + NoticeRequest, + PrivateRequest, + UtmRequest, + GetKeyRequest, + WhoRequest, +) +from frontends.gamespy.protocols.chat.abstractions.contract import ( + SERVER_DOMAIN, + ResponseBase, + ResultBase, +) +from frontends.gamespy.library.encryption.gs_encryption import CLIENT_KEY, SERVER_KEY + +# region General + + +class CdKeyResponse(ResponseBase): + def __init__(self) -> None: + pass + + def build(self) -> None: + self.sending_buffer = ( + f":{SERVER_DOMAIN} {ResponseCode.CDKEY.value} * 1 :Authenticated.\r\n" # noqa + ) + + +class CryptResponse(ResponseBase): + def __init__(self) -> None: + pass + + def build(self) -> None: + self.sending_buffer = f":{SERVER_DOMAIN} {ResponseCode.SECUREKEY.value} * {CLIENT_KEY} {SERVER_KEY}\r\n" # noqa + + +class GetKeyResponse(ResponseBase): + + _result: GetKeyResult + + def __init__(self, result: GetKeyResult) -> None: + assert isinstance(result, GetKeyResult) + super().__init__(result) + + def build(self) -> None: + self.sending_buffer = "" + + for value in self._result.values: + self.sending_buffer += f":{SERVER_DOMAIN} {ResponseCode.GETKEY.value} * {self._result.nick_name} {self._result.cookie} {value}\r\n" # noqa + + self.sending_buffer += f":{SERVER_DOMAIN} {ResponseCode.ENDGETKEY.value} * {self._result.cookie} * :End Of GETKEY.\r\n" # noqa + + +class ListResponse(ResponseBase): + _result: ListResult + + def __init__( + self, result: ListResult) -> None: + assert isinstance(result, ListResult) + self._result = result + + def build(self) -> None: + involer_irc_prefix = ResponseBase.build_irc_user_prefix( + self._result.invoker_nick_name, self._result.invoker_user_name + ) + self.sending_buffer = "" + for ( + channel_name, + total_channel_user, + channel_topic, + ) in self._result.channel_info_list: + self.sending_buffer += f":{involer_irc_prefix} {ResponseCode.LISTSTART.value} * {channel_name} {total_channel_user} {channel_topic}\r\n" # noqa + self.sending_buffer += f":{involer_irc_prefix} {ResponseCode.LISTEND.value}\r\n" # noqa + + +class LoginResponse(ResponseBase): + _result: LoginResult + + def __init__( + self, result: LoginResult) -> None: + assert isinstance(result, LoginResult) + self._result = result + + def build(self) -> None: + self.sending_buffer = f":{SERVER_DOMAIN} {ResponseCode.LOGIN.value} * {self._result.user_id} {self._result.profile_id}\r\n" # noqa + + +class NickResponse(ResponseBase): + _result: NickResult + + def __init__( + self, result: NickResult) -> None: + assert isinstance(result, NickResult) + self._result = result + + def build(self) -> None: + self.sending_buffer = f":{SERVER_DOMAIN} {ResponseCode.WELCOME.value} {self._result.nick_name} :Welcome to UniSpy!\r\n" # noqa + + +class PingResponse(ResponseBase): + _result: PingResult + + def __init__( + self, result: PingResult) -> None: + assert isinstance(result, PingResult) + self._result = result + + def build(self) -> None: + requester_irc_prefix = ResponseBase.build_irc_user_prefix( + self._result.nick_name, self._result.user_name + ) + self.sending_buffer = f":{requester_irc_prefix} {ResponseCode.PONG.value}\r\n" + + +class UserIPResponse(ResponseBase): + _result: UserIPResult + + def __init__( + self, result: UserIPResult) -> None: + assert isinstance(result, UserIPResult) + self._result = result + + def build(self) -> None: + self.sending_buffer = f":{SERVER_DOMAIN} {ResponseCode.USRIP.value} :@{self._result.remote_ip}\r\n" + + +class WhoIsResponse(ResponseBase): + _result: WhoIsResult + + def __init__( + self, result: WhoIsResult) -> None: + assert isinstance(result, WhoIsResult) + self._result = result + + def build(self) -> None: + self.sending_buffer = f":{SERVER_DOMAIN} {ResponseCode.WHOISUSER.value} {self._result.nick_name} {self._result.user_name} {self._result.user_name} {self._result.public_ip_address} * :{self._result.user_name}\r\n" # noqa + + if len(self._result.joined_channels) != 0: + channel_name = "" + for name in self._result.joined_channels: + channel_name += f"@{name} " # noqa + + self.sending_buffer += f":{SERVER_DOMAIN} {ResponseCode.WHOISCHANNELS.value} {self._result.nick_name} {self._result.user_name} :{channel_name}\r\n" # noqa + + self.sending_buffer += f":{SERVER_DOMAIN} {ResponseCode.ENDOFWHOIS.value} {self._result.nick_name} {self._result.user_name} :End of WHOIS list. \r\n" # noqa + + +class WhoResponse(ResponseBase): + _result: WhoResult + + def __init__(self, result: WhoResult) -> None: + assert isinstance(result, WhoResult) + super().__init__(result) + + def build(self): + self.sending_buffer = "" + for ( + channel_name, + user_name, + public_ip_address, + nick_name, + modes, + ) in self._result.infos: + self.sending_buffer += f":{SERVER_DOMAIN} {ResponseCode.WHOREPLY.value} * {channel_name} {user_name} {public_ip_address} * {nick_name} {modes} *\r\n" # noqa + + if self._result.request_type == WhoRequestType.GET_CHANNEL_USER_INFO: + # if len(self._result.infos) > 0: + self.sending_buffer += f":{SERVER_DOMAIN} {ResponseCode.ENDOFWHO.value} * {self._result.channel_name} * :End of WHO.\r\n" # noqa + elif self._result.request_type == WhoRequestType.GET_USER_INFO: + # if len(self._result.infos) > 0: + self.sending_buffer += f":{SERVER_DOMAIN} {ResponseCode.ENDOFWHO.value} * {self._result.nick_name} * :End of WHO.\r\n" # noqa + + +# region Channel + + +class GetChannelKeyResponse(ChannelResponseBase): + _result: GetChannelKeyResult + + def build(self) -> None: + involker_irc_prefix = ResponseBase.build_irc_user_prefix( + self._result.nick_name, self._result.user_name + ) + self.sending_buffer = f":{involker_irc_prefix} {ResponseCode.GETCHANKEY.value} * {self._result.channel_name} {self._result.cookie} {self._result.key_values}\r\n" + + +class GetCKeyResponse(ResponseBase): + _result: GetCKeyResult + + def __init__( + self, result: GetCKeyResult) -> None: + assert isinstance(result, GetCKeyResult) + super().__init__(result) + + def build(self) -> None: + self.sending_buffer = "" + for info in self._result.infos: + value_str = ChannelResponseBase.build_value_str( + self._result.keys, info.key_values) + self.sending_buffer += f":{SERVER_DOMAIN} {ResponseCode.GETCKEY.value} * {self._result.channel_name} {info.nick_name} {self._result.cookie} {value_str}\r\n" # noqa + + self.sending_buffer += f"{SERVER_DOMAIN} {ResponseCode.ENDGETCKEY.value} * {self._result.channel_name} {self._result.cookie} :End Of GETCKEY.\r\n" # noqa + + +class JoinResponse(ResponseBase): + + _result: JoinResult + + def __init__(self, result: JoinResult) -> None: + assert isinstance(result, JoinResult) + super().__init__(result) + + def build(self) -> None: + joiner_irc_prefix = ResponseBase.build_irc_user_prefix( + self._result.joiner_nick_name, self._result.joiner_user_name + ) + self.sending_buffer = f":{joiner_irc_prefix} {ResponseCode.JOIN.value} {self._result.channel_name}\r\n" + + +class KickResponse(ResponseBase): + + _result: KickResult + + def __init__(self, result: KickResult) -> None: + assert isinstance(result, KickResult) + super().__init__(result) + + def build(self) -> None: + kicker_irc_prefix = ResponseBase.build_irc_user_prefix( + self._result.kicker_nick_name, self._result.kicker_user_name + ) + self.sending_buffer = f"{kicker_irc_prefix} {ResponseCode.KICK.value} {self._result.channel_name} {self._result.kickee_nick_name} :{self._result.reason}\r\n" + + +class ModeResponse(ResponseBase): + + _result: ModeResult + + def __init__(self, result: ModeResult) -> None: + assert isinstance(result, ModeResult) + super().__init__(result) + + @staticmethod + def get_mode_str(modes: list[str]): + if len(modes) == 0: + return "" + modes_str = "+" + for m in modes: + modes_str += m + return modes_str + + def build(self) -> None: + chann_modes_str = ModeResponse.get_mode_str(self._result.channel_modes) + self.sending_buffer = f":{SERVER_DOMAIN} {ResponseCode.CHANNELMODEIS.value} * {self._result.channel_name} {chann_modes_str}\r\n" + + +class NamesResponse(ChannelResponseBase): + + _result: NamesResult + + def __init__(self, result: NamesResult) -> None: + assert isinstance(result, NamesResult) + super().__init__(result) + + @staticmethod + def get_nicks_list(data: list[NamesResultData]): + nicks_str = "" + for i in range(len(data)): + user = data[i] + assert isinstance(user.is_channel_creator, bool) + assert isinstance(user.nick_name, str) + if user.is_channel_creator: + nicks_str += f"@{user.nick_name}" + else: + nicks_str += user.nick_name + # use space as seperator + if i != (len(data) - 1): + nicks_str += " " + return nicks_str + + def build(self) -> None: + nicks_str = NamesResponse.get_nicks_list(self._result.channel_nicks) + self.sending_buffer = f":{SERVER_DOMAIN} {ResponseCode.NAMEREPLY.value} {self._result.requester_nick_name} = {self._result.channel_name} :{nicks_str}\r\n" + self.sending_buffer += f":{SERVER_DOMAIN} {ResponseCode.ENDOFNAMES.value} {self._result.requester_nick_name} {self._result.channel_name} :End of NAMES list. \r\n" + + +class PartResponse(ResponseBase): + + _result: PartResult + + def __init__(self, result: PartResult) -> None: + assert isinstance(result, PartResult) + super().__init__(result) + + def build(self) -> None: + leaver_irc_prefix = ResponseBase.build_irc_user_prefix( + self._result.leaver_nick_name, self._result.leaver_user_name + ) + self.sending_buffer = f":{leaver_irc_prefix} {ResponseCode.PART.value} {self._result.channel_name} :{self._result.reason}\r\n" + + +class SetChannelKeyResponse(ChannelResponseBase): + _result: SetChannelKeyResult + + def __init__(self, result: SetChannelKeyResult) -> None: + super().__init__(result) + assert isinstance(result, SetChannelKeyResult) + + def build(self) -> None: + setter_irc_prefix = ResponseBase.build_irc_user_prefix( + self._result.setter_nick_name, self._result.setter_user_name + ) + key_value_str = ChannelResponseBase.build_key_value_str( + self._result.key_value) + self.sending_buffer = f":{setter_irc_prefix} {ResponseCode.GETCHANKEY.value} * {self._result.channel_name} BCAST {key_value_str}\r\n" + + +class SetCKeyResponse(ResponseBase): + _result: SetCKeyResult + + def __init__(self, result: SetCKeyResult) -> None: + super().__init__(result) + + def build(self) -> None: + kv_str = ChannelResponseBase.build_key_value_str( + self._result.key_value) + self.sending_buffer = f":{SERVER_DOMAIN} {ResponseCode.GETCKEY.value} * {self._result.channel_name} {self._result.setter_nick_name} {self._result.cookie} {kv_str}\r\n" + + self.sending_buffer += f":{SERVER_DOMAIN} {ResponseCode.ENDGETCKEY.value} * {self._result.channel_name} {self._result.setter_nick_name} {self._result.cookie} :End Of SETCKEY.\r\n" + + +class TopicResponse(ResponseBase): + + _result: TopicResult + + def __init__(self, result: TopicResult) -> None: + assert isinstance(result, TopicResult) + super().__init__(result) + + def build(self) -> None: + if self._result.channel_topic == "" or self._result.channel_topic is None: + self.sending_buffer = f":{SERVER_DOMAIN} {ResponseCode.NOTOPIC.value} * {self._result.channel_name}\r\n" + else: + self.sending_buffer = f":{SERVER_DOMAIN} {ResponseCode.TOPIC.value} * {self._result.channel_name} :{self._result.channel_topic}\r\n" + + +# region Message + + +class AtmResponse(ResponseBase): + + _result: AtmResult + + def __init__(self, result: AtmResult) -> None: + assert isinstance(result, AtmResult) + super().__init__(result) + + def build(self) -> None: + irc_prefix = ResponseBase.build_irc_user_prefix( + self._result.sender_nick_name, self._result.sender_user_name + ) + self.sending_buffer = f":{irc_prefix} {ResponseCode.ATM.value} {self._result.target_name} :{self._result.message}\r\n" + + +class NoticeResponse(ResponseBase): + + _result: NoticeResult + + def __init__( + self, result: NoticeResult) -> None: + assert isinstance(result, NoticeResult) + super().__init__(result) + + def build(self) -> None: + irc_prefix = ResponseBase.build_irc_user_prefix( + self._result.sender_nick_name, self._result.sender_user_name + ) + + self.sending_buffer = f":{irc_prefix} {ResponseCode.NOTICE.value} {self._result.target_name} {self._result.message}\r\n" + + +class PrivateResponse(ResponseBase): + + _result: PrivateResult + + def __init__(self, result: PrivateResult) -> None: + assert isinstance(result, PrivateResult) + super().__init__(result) + + def build(self) -> None: + irc_prefix = ResponseBase.build_irc_user_prefix( + self._result.sender_nick_name, self._result.sender_user_name + ) + self.sending_buffer = f":{irc_prefix} {ResponseCode.PRIVMSG.value} {self._result.target_name} :{self._result.message}\r\n" + + +class UtmResponse(ResponseBase): + + _result: UtmResult + + def __init__(self, result: UtmResult) -> None: + assert isinstance(result, UtmResult) + super().__init__(result) + + def build(self) -> None: + irc_prefix = ResponseBase.build_irc_user_prefix( + self._result.sender_nick_name, self._result.sender_user_name + ) + + self.sending_buffer = f":{irc_prefix} {ResponseCode.UTM.value} {self._result.target_name} :{self._result.message}\r\n" diff --git a/src/frontends/gamespy/protocols/chat/contracts/results.py b/src/frontends/gamespy/protocols/chat/contracts/results.py new file mode 100644 index 000000000..b184be4c5 --- /dev/null +++ b/src/frontends/gamespy/protocols/chat/contracts/results.py @@ -0,0 +1,191 @@ +from pydantic import BaseModel +from frontends.gamespy.protocols.chat.abstractions.contract import ResultBase +from frontends.gamespy.protocols.chat.abstractions.handler import MessageResultBase +from frontends.gamespy.protocols.chat.aggregates.enums import WhoRequestType + +# region General + + +class CryptResult(ResultBase): + secret_key: str + pass + + +class GetKeyResult(ResultBase): + nick_name: str + values: list + cookie: str + + +class ListResult(ResultBase): + class ListInfo(BaseModel): + channel_name: str + total_channel_user: int + channel_topic: str + invoker_nick_name: str + invoker_user_name: str + channel_info_list: list[ListInfo] = [] + """(channel_name:str,total_channel_user:int,channel_topic:str)""" + + +class LoginResult(ResultBase): + profile_id: int + user_id: int + + +class NickResult(ResultBase): + nick_name: str + + +class PingResult(ResultBase): + nick_name:str + user_name:str + + +class QuitResult(ResultBase): + class QuitInfo(BaseModel): + channel_name: str + is_peer_server: bool + is_channel_operator: bool + leave_reply_sending_buffer: str + kick_replay_sending_buffer: str + + quiter_prefix: str + channel_infos: list[QuitInfo] + # (channel_name: str, is_peer_server: bool, is_channel_operator: bool,leave_reply_sending_buffer: str,kick_replay_sending_buffer: str) + message: str + + +class UserIPResult(ResultBase): + remote_ip: str + + +class WhoIsResult(ResultBase): + nick_name: str + user_name: str + public_ip_address: str + joined_channels: list[str] + + +class WhoResult(ResultBase): + class WhoInfo(BaseModel): + user_name: str + nick_name: str + channel_name: str + public_ip_addr: str + modes: str + + infos: list[WhoInfo] + request_type: WhoRequestType + channel_name: str + nick_name: str +# region Channel + + +class GetChannelKeyResult(ResultBase): + nick_name: str + user_name: str + channel_name: str + key_values: dict + cookie: str + + +class GetCKeyResult(ResultBase): + class GetCKeyInfos(BaseModel): + nick_name: str + key_values: dict + infos: list[GetCKeyInfos] + """ nick_name:str, user_values:str""" + channel_name: str + cookie: str + keys: list[str] + + +class ModeResult(ResultBase): + channel_name: str + channel_modes: list[str] + joiner_nick_name: str + + +class NamesResultData(BaseModel): + nick_name: str + is_channel_creator: bool = False + is_channel_operator: bool = False + + +class NamesResult(ResultBase): + channel_nicks: list[NamesResultData] + channel_name: str + requester_nick_name: str + + +class JoinResult(ResultBase): + joiner_nick_name: str + joiner_user_name: str + channel_name: str + + +class KickResult(ResultBase): + channel_name: str + kicker_nick_name: str + kicker_user_name: str + kickee_nick_name: str + reason: str + + +class PartResult(ResultBase): + leaver_nick_name: str + leaver_user_name: str + is_channel_creator: bool + channel_name: str + reason: str + + +class TopicResult(ResultBase): + channel_name: str + channel_topic: str + + +class SetChannelKeyResult(ResultBase): + setter_nick_name: str + setter_user_name: str + channel_name: str + key_value: dict[str, str] + + +class SetCKeyResult(ResultBase): + setter_nick_name: str + setter_user_name: str + channel_name: str + cookie: str + key_value: dict + + +if __name__ == "__main__": + dd = { + "infos": [ + {"nick_name": "John", "user_values": "12345"}, + {"nick_name": "Alice", "user_values": "67890"}, + ], + "channel_name": "example_channel", + } + result = GetCKeyResult(**dd) + pass + +# region Message + + +class AtmResult(MessageResultBase): + pass + + +class NoticeResult(MessageResultBase): + pass + + +class PrivateResult(MessageResultBase): + pass + + +class UtmResult(MessageResultBase): + pass diff --git a/src/frontends/gamespy/protocols/game_status/__init__.py b/src/frontends/gamespy/protocols/game_status/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/gamespy/protocols/game_status/abstractions/contracts.py b/src/frontends/gamespy/protocols/game_status/abstractions/contracts.py new file mode 100644 index 000000000..6d2728cad --- /dev/null +++ b/src/frontends/gamespy/protocols/game_status/abstractions/contracts.py @@ -0,0 +1,43 @@ + +import frontends.gamespy.library.abstractions.contracts as lib +from frontends.gamespy.library.extentions.gamespy_utils import convert_to_key_value +from frontends.gamespy.protocols.game_status.aggregations.exceptions import GSException + + +class RequestBase(lib.RequestBase): + command_name: str + raw_request: str + local_id: int | None + _request_dict: dict[str, str] + + @staticmethod + def convert_game_data_to_key_values(game_data: str): + assert isinstance(game_data, str) + game_data = game_data.replace("\u0001", "\\") + convert_to_key_value(game_data) + + def parse(self) -> None: + self._request_dict = convert_to_key_value(self.raw_request) + + if "lid" in self._request_dict: + try: + self.local_id = int(self._request_dict["lid"]) + except: + raise GSException("local id is not valid.") + + if "id" in self._request_dict: + try: + self.local_id = int(self._request_dict["id"]) + except: + raise GSException("local id is not valid.") + + +class ResultBase(lib.ResultBase): + local_id: int + pass + + +class ResponseBase(lib.ResponseBase): + _request: RequestBase + _result: ResultBase + sending_buffer: str diff --git a/src/frontends/gamespy/protocols/game_status/abstractions/handlers.py b/src/frontends/gamespy/protocols/game_status/abstractions/handlers.py new file mode 100644 index 000000000..5edbf9e80 --- /dev/null +++ b/src/frontends/gamespy/protocols/game_status/abstractions/handlers.py @@ -0,0 +1,17 @@ + +from frontends.gamespy.library.abstractions.contracts import ResponseBase +import frontends.gamespy.library.abstractions.handler as lib +from frontends.gamespy.protocols.game_status.abstractions.contracts import RequestBase, ResultBase +from frontends.gamespy.protocols.game_status.applications.client import Client + + +class CmdHandlerBase(lib.CmdHandlerBase): + _client: Client + _request: RequestBase + _result: ResultBase + _response: ResponseBase | None + + def __init__(self, client: Client, request: RequestBase) -> None: + super().__init__(client, request) + assert isinstance(client, Client) + assert issubclass(type(request), RequestBase) diff --git a/src/frontends/gamespy/protocols/game_status/aggregations/enums.py b/src/frontends/gamespy/protocols/game_status/aggregations/enums.py new file mode 100644 index 000000000..d3ef30f2c --- /dev/null +++ b/src/frontends/gamespy/protocols/game_status/aggregations/enums.py @@ -0,0 +1,32 @@ +from enum import Enum, IntEnum + + +class AuthMethod(IntEnum): + UNKNOWN = 0 + PROFILE_ID_AUTH = 0 + PARTNER_ID_AUTH = 1 + CDKEY_AUTH = 2 + + +class PersistStorageType(IntEnum): + PRIVATE_READ_ONLY = 0 + PRIVATE_READ_WRITE = 1 + PUBLIC_READ_ONLY = 2 + PUBLIC_READ_WRITE = 3 + + +class GSErrorCode(IntEnum): + GENERAL = 0 + PARSE = 1 + DATABASE = 2 + NOERROR = 3 + + +class RequestType(Enum): + AUTH = "auth" + AUTHP = "authp" + NEWGAME = "newgame" + GETPD = "getpd" + SETPD = "setpd" + UPDGAME = "updgame" + GETPID = "getpid" \ No newline at end of file diff --git a/src/frontends/gamespy/protocols/game_status/aggregations/exceptions.py b/src/frontends/gamespy/protocols/game_status/aggregations/exceptions.py new file mode 100644 index 000000000..3a85892ff --- /dev/null +++ b/src/frontends/gamespy/protocols/game_status/aggregations/exceptions.py @@ -0,0 +1,5 @@ +from frontends.gamespy.library.exceptions.general import UniSpyException + + +class GSException(UniSpyException): + pass diff --git a/src/frontends/gamespy/protocols/game_status/aggregations/gscrypt.py b/src/frontends/gamespy/protocols/game_status/aggregations/gscrypt.py new file mode 100644 index 000000000..14002a3d7 --- /dev/null +++ b/src/frontends/gamespy/protocols/game_status/aggregations/gscrypt.py @@ -0,0 +1,21 @@ + + +from frontends.gamespy.library.abstractions.enctypt_base import EncryptBase +from frontends.gamespy.library.encryption.xor_encryption import XorEncoding, XorType +from frontends.gamespy.protocols.game_status.aggregations.exceptions import GSException + + +class GSCrypt(EncryptBase): + def decrypt(self, data: bytes) -> bytes: + if b"final" not in data: + raise GSException("Ciphertext must contains delimeter \\final\\") + cipher = data[:-7] + plain = XorEncoding.encode(cipher, XorType.TYPE_1) + return plain + b"\\final\\" + + def encrypt(self, data: bytes) -> bytes: + if b"final" not in data: + raise GSException("Ciphertext must contains delimeter \\final\\") + cipher = data[:-7] + plain = XorEncoding.encode(cipher, XorType.TYPE_1) + return plain + b"\\final\\" \ No newline at end of file diff --git a/src/frontends/gamespy/protocols/game_status/applications/client.py b/src/frontends/gamespy/protocols/game_status/applications/client.py new file mode 100644 index 000000000..3133298da --- /dev/null +++ b/src/frontends/gamespy/protocols/game_status/applications/client.py @@ -0,0 +1,76 @@ + +from frontends.gamespy.library.abstractions.client import ClientBase, ClientInfoBase +from frontends.gamespy.library.abstractions.switcher import SwitcherBase +from frontends.gamespy.library.log.log_manager import LogWriter +from frontends.gamespy.library.network.tcp_handler import TcpConnection +from frontends.gamespy.library.configs import ServerConfig +from frontends.gamespy.protocols.game_status.aggregations.gscrypt import GSCrypt + + +CHALLENGE_RESPONSE = "\\challenge\\00000000000000000000\\final\\" + + +class ClientInfo(ClientInfoBase): + session_key: str | None + game_name: str | None + is_user_authenticated: bool + is_player_authenticated: bool + is_game_authenticated: bool + profile_id: int | None + game_session_key: str | None + + def __init__(self) -> None: + super().__init__() + self.session_key = None + self.game_name = None + self.profile_id = None + self.game_session_key = None + self.is_user_authenticated = False + self.is_player_authenticated = False + self.is_game_authenticated = False + + +class Client(ClientBase): + info: ClientInfo + client_pool: dict[str, "Client"] = {} + + def __init__( + self, connection: TcpConnection, server_config: ServerConfig, logger: LogWriter + ): + super().__init__(connection, server_config, logger) + self.info = ClientInfo() + + def on_connected(self) -> None: + self.crypto = GSCrypt() + self.log_network_sending(CHALLENGE_RESPONSE) + enc_buffer = self.crypto.encrypt(CHALLENGE_RESPONSE.encode("ascii")) + self.connection.send(enc_buffer) + + def decrypt_message(self, buffer: bytes) -> bytes: + if self.crypto is None: + return buffer + + temp = buffer.decode("ascii").split("\\final\\")[0] + + if len(temp) > 1: + message = "" + for t in temp: + complete_buffer = (t + "\\final\\").encode() + message += self.crypto.decrypt(complete_buffer).decode("ascii") + return message.encode() + + return self.crypto.decrypt(buffer) + + def _create_switcher(self, buffer: bytes) -> SwitcherBase: + from frontends.gamespy.protocols.game_status.applications.switcher import ( + Switcher, + ) + # ! sometime the request will decode with exception, something happend in sdk, + # ! we do not process that here, let client login again will resolve the problem + try: + data_str = buffer.decode("ascii") + except UnicodeDecodeError: + self.log_warn( + f"can not decode {buffer} with ascii, change decode method to latin1") + data_str = buffer.decode("latin1") + return Switcher(self, data_str) diff --git a/src/frontends/gamespy/protocols/game_status/applications/handlers.py b/src/frontends/gamespy/protocols/game_status/applications/handlers.py new file mode 100644 index 000000000..69aa48792 --- /dev/null +++ b/src/frontends/gamespy/protocols/game_status/applications/handlers.py @@ -0,0 +1,78 @@ +from frontends.gamespy.protocols.game_status.abstractions.handlers import CmdHandlerBase +from frontends.gamespy.protocols.game_status.applications.client import Client +from frontends.gamespy.protocols.game_status.contracts.requests import AuthGameRequest, AuthPlayerRequest, GetPlayerDataRequest, GetProfileIdRequest, NewGameRequest, SetPlayerDataRequest, UpdateGameRequest +from frontends.gamespy.protocols.game_status.contracts.responses import AuthGameResponse, AuthPlayerResponse, GetPlayerDataResponse, GetProfileIdResponse, SetPlayerDataResponse +from frontends.gamespy.protocols.game_status.contracts.results import AuthGameResult, AuthPlayerResult, GetPlayerDataResult, GetProfileIdResult, SetPlayerDataResult + + +class AuthGameHandler(CmdHandlerBase): + _request: AuthGameRequest + _result: AuthGameResult + _response: AuthGameResponse + + def __init__(self, client: Client, request: AuthGameRequest) -> None: + assert isinstance(request, AuthGameRequest) + super().__init__(client, request) + + def _data_operate(self) -> None: + super()._data_operate() + self._client.info.session_key = self._result.session_key + self._client.info.game_name = self._result.game_name + self._client.info.is_game_authenticated = True + + +class AuthPlayerHandler(CmdHandlerBase): + _request: AuthPlayerRequest + _result: AuthPlayerResult + _response: AuthPlayerResponse + + def __init__(self, client: Client, request: AuthPlayerRequest) -> None: + assert isinstance(request, AuthPlayerRequest) + super().__init__(client, request) + + +class GetPlayerDataHandler(CmdHandlerBase): + _result: GetPlayerDataResult + _response: GetPlayerDataResponse + + def __init__(self, client: Client, request: GetPlayerDataRequest) -> None: + assert isinstance(request, GetPlayerDataRequest) + super().__init__(client, request) + + +class GetProfileIdHandler(CmdHandlerBase): + _result: GetProfileIdResult + _response: GetProfileIdResponse + + def __init__(self, client: Client, request: GetProfileIdRequest) -> None: + assert isinstance(request, GetProfileIdRequest) + super().__init__(client, request) + + +class NewGameHandler(CmdHandlerBase): + _request: NewGameRequest + + def __init__(self, client: Client, request: NewGameRequest) -> None: + assert isinstance(request, NewGameRequest) + super().__init__(client, request) + + +class SetPlayerDataHandler(CmdHandlerBase): + _request: SetPlayerDataRequest + + def __init__(self, client: Client, request: SetPlayerDataRequest) -> None: + assert isinstance(request, SetPlayerDataRequest) + super().__init__(client, request) + + +class UpdateGameHandler(CmdHandlerBase): + """ + old request "\\updgame\\\\sesskey\\%d\\done\\%d\\gamedata\\%s" + + new request "\\updgame\\\\sesskey\\%d\\connid\\%d\\done\\%d\\gamedata\\%s" + """ + _request: UpdateGameRequest + + def __init__(self, client: Client, request: UpdateGameRequest) -> None: + assert isinstance(request, UpdateGameRequest) + super().__init__(client, request) diff --git a/src/frontends/gamespy/protocols/game_status/applications/server_launcher.py b/src/frontends/gamespy/protocols/game_status/applications/server_launcher.py new file mode 100644 index 000000000..5b9c19806 --- /dev/null +++ b/src/frontends/gamespy/protocols/game_status/applications/server_launcher.py @@ -0,0 +1,21 @@ +from frontends.gamespy.protocols.game_status.applications.client import Client +from frontends.gamespy.library.abstractions.server_launcher import ServicesFactory, ServiceBase +from frontends.gamespy.library.network.tcp_handler import TcpServer + + +class Service(ServiceBase): + server: "TcpServer" + + def __init__(self) -> None: + super().__init__( + config_name="GameStatus", + client_cls=Client, + network_server_cls=TcpServer, + ) + + +if __name__ == "__main__": + from frontends.gamespy.library.extentions.debug_helper import DebugHelper + gs = Service() + helper = DebugHelper("./frontends/", ServicesFactory([gs])) + helper.start() diff --git a/src/frontends/gamespy/protocols/game_status/applications/switcher.py b/src/frontends/gamespy/protocols/game_status/applications/switcher.py new file mode 100644 index 000000000..ed1606eb1 --- /dev/null +++ b/src/frontends/gamespy/protocols/game_status/applications/switcher.py @@ -0,0 +1,51 @@ +from typing import cast +from frontends.gamespy.library.abstractions.switcher import SwitcherBase +from frontends.gamespy.protocols.game_status.abstractions.handlers import CmdHandlerBase +from frontends.gamespy.protocols.game_status.aggregations.enums import RequestType +from frontends.gamespy.protocols.game_status.applications.client import Client +from frontends.gamespy.protocols.game_status.contracts.requests import AuthGameRequest, AuthPlayerRequest, GetPlayerDataRequest, GetProfileIdRequest, NewGameRequest, SetPlayerDataRequest, UpdateGameRequest +from frontends.gamespy.protocols.game_status.applications.handlers import AuthGameHandler, AuthPlayerHandler, GetPlayerDataHandler, GetProfileIdHandler, NewGameHandler, SetPlayerDataHandler, UpdateGameHandler + + +class Switcher(SwitcherBase): + _raw_request: str + + def __init__(self, client: Client, raw_request: str) -> None: + super().__init__(client, raw_request) + assert isinstance(client, Client) + assert isinstance(raw_request, str) + + def _process_raw_request(self) -> None: + if self._raw_request[0] != "\\": + self._client.log_info("Invalid request received!") + return + raw_requests = [ + r+"\\final\\" for r in self._raw_request.split("\\final\\") if r] + for raw_request in raw_requests: + name = raw_request.strip("\\").split("\\", 1)[0] + if name not in RequestType: + self._client.log_debug( + f"Request: {name} is not a valid request.") + return + self._requests.append((RequestType(name), raw_request)) + + def _create_cmd_handlers(self, name: RequestType, raw_request: str) -> CmdHandlerBase | None: + assert isinstance(name, RequestType) + self._client = cast(Client, self._client) + match name: + case RequestType.AUTH: + return AuthGameHandler(self._client, AuthGameRequest(raw_request)) + case RequestType.AUTHP: + return AuthPlayerHandler(self._client, AuthPlayerRequest(raw_request)) + case RequestType.NEWGAME: + return NewGameHandler(self._client, NewGameRequest(raw_request)) + case RequestType.GETPD: + return GetPlayerDataHandler(self._client, GetPlayerDataRequest(raw_request)) + case RequestType.SETPD: + return SetPlayerDataHandler(self._client, SetPlayerDataRequest(raw_request)) + case RequestType.UPDGAME: + return UpdateGameHandler(self._client, UpdateGameRequest(raw_request)) + case RequestType.GETPID: + return GetProfileIdHandler(self._client, GetProfileIdRequest(raw_request)) + case _: + return None diff --git a/src/frontends/gamespy/protocols/game_status/contracts/requests.py b/src/frontends/gamespy/protocols/game_status/contracts/requests.py new file mode 100644 index 000000000..0bf1d1ff0 --- /dev/null +++ b/src/frontends/gamespy/protocols/game_status/contracts/requests.py @@ -0,0 +1,277 @@ +from typing import final +from frontends.gamespy.library.extentions.gamespy_utils import convert_to_key_value +from frontends.gamespy.protocols.game_status.abstractions.contracts import RequestBase +from frontends.gamespy.protocols.game_status.aggregations.enums import ( + AuthMethod, + PersistStorageType, +) +from frontends.gamespy.protocols.game_status.aggregations.exceptions import GSException + + +@final +class AuthGameRequest(RequestBase): + game_name: str + + def parse(self) -> None: + super().parse() + if "lid" not in self._request_dict and "id" not in self._request_dict: + raise GSException("localid is missing") + + if "gamename" not in self._request_dict: + raise GSException("gamename is missing") + self.game_name = self._request_dict["gamename"] + + if "response" not in self._request_dict: + raise GSException("response is missing") + self.response = self._request_dict["response"] + + if "port" in self._request_dict: + try: + self.port = int(self._request_dict["port"]) + except ValueError: + raise GSException("port format is incorrect") + + +@final +class AuthPlayerRequest(RequestBase): + auth_type: AuthMethod + profile_id: int + + auth_token: str + response: str + cdkey_hash: str + nick: str + + def parse(self) -> None: + super().parse() + if "lid" not in self._request_dict and "id" not in self._request_dict: + raise GSException("localid is missing from auth game request") + if "pid" in self._request_dict and "resp" in self._request_dict: + try: + self.profile_id = int(self._request_dict["pid"]) + except ValueError: + raise GSException("profile id format is incorrect") + self.auth_type = AuthMethod.PROFILE_ID_AUTH + elif "authtoken" in self._request_dict and "response" in self._request_dict: + self.auth_token = self._request_dict["authtoken"] + self.response = self._request_dict["response"] + self.auth_type = AuthMethod.PARTNER_ID_AUTH + elif "keyhash" in self._request_dict and "nick" in self._request_dict: + self.cdkey_hash = self._request_dict["keyhash"] + self.nick = self._request_dict["nick"] + self.auth_type = AuthMethod.CDKEY_AUTH + else: + raise GSException("unknown authp request type") + + +@final +class GetPlayerDataRequest(RequestBase): + profile_id: int + storage_type: PersistStorageType + data_index: int + is_get_all_data: bool = False + keys: list[str] + + def __init__(self, raw_request: object) -> None: + super().__init__(raw_request) + self.keys = [] + + def parse(self) -> None: + super().parse() + + if "lid" not in self._request_dict and "id" not in self._request_dict: + raise GSException("localid is missing from auth game request") + + if "pid" in self._request_dict: + try: + self.profile_id = int(self._request_dict["pid"]) + except ValueError: + raise GSException("pid format is incorrect") + + if "ptype" in self._request_dict: + try: + self.storage_type = PersistStorageType( + int(self._request_dict["ptype"])) + except ValueError: + raise GSException("ptype format is incorrect") + + if "dindex" in self._request_dict: + try: + self.data_index = int(self._request_dict["dindex"]) + except ValueError: + raise GSException("dindex format is incorrect") + + if "keys" not in self._request_dict: + raise GSException("keys is missing") + + keys = self._request_dict["keys"] + if not keys: + self.is_get_all_data = True + else: + key_list = keys.split("\x01") + for key in key_list: + self.keys.append(key) + self.is_get_all_data = False + + +@final +class GetProfileIdRequest(RequestBase): + nick: str + key_hash: str + + def parse(self) -> None: + super().parse() + if "lid" not in self._request_dict and "id" not in self._request_dict: + raise GSException("localid is missing from auth game request") + + if "nick" not in self._request_dict or "keyhash" not in self._request_dict: + raise GSException("nick or keyhash is missing") + + if "nick" in self._request_dict: + self.nick = self._request_dict["nick"] + if "keyhash" in self._request_dict: + self.key_hash = self._request_dict["keyhash"] + + +@final +class NewGameRequest(RequestBase): + is_client_local_storage_available: bool + challenge: str + connection_id: int + """ + client session key + """ + session_key: str + """ + game session key + """ + + def parse(self) -> None: + super().parse() + self.is_client_local_storage_available = True + if "sesskey" not in self._request_dict: + raise GSException("sesskey is missing") + + self.session_key = self._request_dict["sesskey"] + + if "connid" not in self._request_dict: + raise GSException("connid is missing") + try: + self.connection_id = int(self._request_dict["connid"]) + except ValueError: + raise GSException("connid format is incorrect") + + if "challenge" in self._request_dict: + self.challenge = self._request_dict["challenge"] + + +@final +class SetPlayerDataRequest(RequestBase): + """ + request have 2 different data type + SetPersistData() data type is bytes + SetPersistDataValues() data type is \\key\\value + """ + profile_id: int + storage_type: PersistStorageType + data_index: int + length: int + report: str + data: str + is_key_value: bool + + def parse(self) -> None: + super().parse() + if "pid" not in self._request_dict: + raise GSException("pid is missing") + + if "ptype" not in self._request_dict: + raise GSException("ptype is missing") + + if "dindex" not in self._request_dict: + raise GSException("dindex is missing") + + if "length" not in self._request_dict: + raise GSException("length is missing") + if "kv" not in self._request_dict: + raise GSException("key value type is missing") + + try: + self.is_key_value = bool(int(self._request_dict['kv'])) + except ValueError: + raise GSException("kv format is incorrect") + + try: + self.profile_id = int(self._request_dict["pid"]) + except ValueError: + raise GSException("pid format is incorrect") + + try: + self.storage_type = PersistStorageType( + int(self._request_dict["ptype"])) + except ValueError: + raise GSException("ptype format is incorrect") + + try: + self.data_index = int(self._request_dict["dindex"]) + except ValueError: + raise GSException("dindex format is incorrect") + + try: + self.length = int(self._request_dict["length"]) + except ValueError: + raise GSException("length format is incorrect") + + if "report" in self._request_dict: + self.report = self._request_dict["report"] + + if "data" in self._request_dict: + self.data = self._request_dict["data"] + + +@final +class UpdateGameRequest(RequestBase): + connection_id: int | None + is_done: bool + is_client_local_storage_available: bool + game_data: str + game_data_dict: dict[str, str] + session_key: str + + def __init__(self, raw_request: object) -> None: + super().__init__(raw_request) + self.connection_id = None + + def parse(self) -> None: + super().parse() + if "gamedata" not in self._request_dict: + raise GSException("gamedata is missing") + self.game_data = self._request_dict["gamedata"] + + self.game_data_dict = convert_to_key_value(self.game_data) + + if "dl" in self._request_dict: + self.is_client_local_storage_available = True + + if "done" not in self._request_dict: + raise GSException("done is missing") + + done = self._request_dict["done"] + if done == "1": + self.is_done = True + + elif done == "0": + self.is_done = False + else: + raise GSException("done format is incorrect") + + if "sesskey" not in self._request_dict: + raise GSException("sesskey is missing") + + self.session_key = self._request_dict["sesskey"] + + if "connid" in self._request_dict: + try: + self.connection_id = int(self._request_dict["connid"]) + except ValueError: + raise GSException("connid format is incorrect") diff --git a/src/frontends/gamespy/protocols/game_status/contracts/responses.py b/src/frontends/gamespy/protocols/game_status/contracts/responses.py new file mode 100644 index 000000000..710882134 --- /dev/null +++ b/src/frontends/gamespy/protocols/game_status/contracts/responses.py @@ -0,0 +1,51 @@ + +from typing import final +from frontends.gamespy.library.abstractions.contracts import ResponseBase +from frontends.gamespy.protocols.game_status.contracts.results import AuthGameResult, AuthPlayerResult, GetPlayerDataResult, GetProfileIdResult, SetPlayerDataResult + + +@final +class AuthGameResponse(ResponseBase): + _result: AuthGameResult + + def build(self) -> None: + # fmt: off + self.sending_buffer = f"\\sesskey\\{self._result.session_key}\\lid\\{self._result.local_id}\\final\\" + # fmt: on + + +@final +class AuthPlayerResponse(ResponseBase): + _result: AuthPlayerResult + + def build(self) -> None: + self.sending_buffer = f"\\pauthr\\{self._result.profile_id}\\lid\\{self._result.local_id}\\final\\" + + +@final +class GetPlayerDataResponse(ResponseBase): + _result: GetPlayerDataResult + + def build(self) -> None: + mod_time = int(self._result.modified.timestamp()) + self.sending_buffer = f"\\getpdr\\1\\pid\\{self._result.profile_id}\\lid\\{self._result.local_id}\\mod\\{mod_time}\\length\\{len(self._result.data)}\\data\\{self._result.data}\\final\\" + + +@final +class GetProfileIdResponse(ResponseBase): + _result: GetProfileIdResult + + def build(self) -> None: + # fmt: off + self.sending_buffer = f"\\getpidr\\{self._result.profile_id}\\lid\\{self._result.local_id}\\final\\" + # fmt: on + + +@final +class SetPlayerDataResponse(ResponseBase): + _result: SetPlayerDataResult + + def build(self) -> None: + # \\setpdr\\1\\lid\\2\\pid\\100000\\mod\\12345 + mod_time = int(self._result.modified.timestamp()) + self.sending_buffer = f"\\setpdr\\1\\pid\\{self._result.profile_id}\\lid\\{self._result.local_id}\\mod\\{mod_time}\\final\\" diff --git a/src/frontends/gamespy/protocols/game_status/contracts/results.py b/src/frontends/gamespy/protocols/game_status/contracts/results.py new file mode 100644 index 000000000..49198bda9 --- /dev/null +++ b/src/frontends/gamespy/protocols/game_status/contracts/results.py @@ -0,0 +1,32 @@ +from datetime import datetime +from typing import final +from frontends.gamespy.protocols.game_status.abstractions.contracts import ResultBase + + +@final +class AuthGameResult(ResultBase): + session_key: str + game_name: str + + +@final +class AuthPlayerResult(ResultBase): + profile_id: int + + +@final +class GetPlayerDataResult(ResultBase): + data: str + profile_id: int + modified: datetime + + +@final +class GetProfileIdResult(ResultBase): + profile_id: int + + +@final +class SetPlayerDataResult(ResultBase): + profile_id: int + modified: datetime diff --git a/src/frontends/gamespy/protocols/game_traffic_relay/__init__.py b/src/frontends/gamespy/protocols/game_traffic_relay/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/gamespy/protocols/game_traffic_relay/aggregates/exceptions.py b/src/frontends/gamespy/protocols/game_traffic_relay/aggregates/exceptions.py new file mode 100644 index 000000000..47912d4a6 --- /dev/null +++ b/src/frontends/gamespy/protocols/game_traffic_relay/aggregates/exceptions.py @@ -0,0 +1,5 @@ +from frontends.gamespy.library.exceptions.general import UniSpyException + + +class GameTrafficException(UniSpyException): + pass diff --git a/src/frontends/gamespy/protocols/game_traffic_relay/applications/broker.py b/src/frontends/gamespy/protocols/game_traffic_relay/applications/broker.py new file mode 100644 index 000000000..75dcc740c --- /dev/null +++ b/src/frontends/gamespy/protocols/game_traffic_relay/applications/broker.py @@ -0,0 +1,5 @@ +from frontends.gamespy.library.network.websocket_brocker import WebSocketBrocker + + +class Broker(WebSocketBrocker): + pass diff --git a/src/frontends/gamespy/protocols/game_traffic_relay/applications/client.py b/src/frontends/gamespy/protocols/game_traffic_relay/applications/client.py new file mode 100644 index 000000000..585d8b188 --- /dev/null +++ b/src/frontends/gamespy/protocols/game_traffic_relay/applications/client.py @@ -0,0 +1,36 @@ +from datetime import datetime +from frontends.gamespy.library.abstractions.client import ClientBase +from frontends.gamespy.library.abstractions.switcher import SwitcherBase +from frontends.gamespy.protocols.game_traffic_relay.applications.connection import ConnectStatus, ConnectionListener +from frontends.gamespy.protocols.natneg.abstractions.contracts import MAGIC_DATA +import frontends.gamespy.protocols.natneg.applications.client as natneg + + +class ClientInfo: + cookie: int | None + last_receive_time: datetime + status: ConnectStatus + ping_recv_times: int + + def __init__(self) -> None: + self.cookie = None + self.last_receive_time = datetime.now() + self.status = ConnectStatus.WAITING_FOR_ANOTHER + self.ping_recv_times = 0 + + +class Client(ClientBase): + info: ClientInfo + + def __init__( + self, + connection: natneg.UdpConnection, + server_config: natneg.ServerConfig, + logger: natneg.LogWriter, + ): + super().__init__(connection, server_config, logger) + self.info = ClientInfo() + + def _create_switcher(self, buffer: bytes) -> SwitcherBase: + from frontends.gamespy.protocols.game_traffic_relay.applications.switcher import Switcher + return Switcher(self, buffer) \ No newline at end of file diff --git a/src/frontends/gamespy/protocols/game_traffic_relay/applications/connection.py b/src/frontends/gamespy/protocols/game_traffic_relay/applications/connection.py new file mode 100644 index 000000000..4a0bba74b --- /dev/null +++ b/src/frontends/gamespy/protocols/game_traffic_relay/applications/connection.py @@ -0,0 +1,88 @@ +from enum import Enum +from typing import TYPE_CHECKING + +from frontends.gamespy.library.exceptions.general import UniSpyException + +if TYPE_CHECKING: + from frontends.gamespy.protocols.game_traffic_relay.applications.client import Client + + +class ConnectStatus(Enum): + WAITING_FOR_ANOTHER = 0 + CONNECTING = 1 + FINISHED = 2 + + +class ConnectionListener: + """ + manage and monitor the connections + """ + cookie_pool: dict[int, list["Client"]] = {} + client_pool: dict[str, "Client"] = {} + + @staticmethod + def get_client_by_ip(ip_end: str) -> "Client|None": + if ip_end in ConnectionListener.client_pool: + return ConnectionListener.client_pool[ip_end] + else: + return None + + @staticmethod + def is_client_exist(cookie: int, client: "Client"): + if cookie not in ConnectionListener.cookie_pool: + return False + else: + clients = ConnectionListener.cookie_pool[cookie] + # if current client is not in the pair + if client not in clients: + return False + else: + return True + + @staticmethod + def add_client(cookie: int, client: "Client"): + # add client to client pool + if client.connection.ip_endpoint not in ConnectionListener.client_pool: + ConnectionListener.client_pool[client.connection.ip_endpoint] = client + # then add to cookie pool + if cookie not in ConnectionListener.cookie_pool: + ConnectionListener.cookie_pool[cookie] = [client] + else: + clients = ConnectionListener.cookie_pool[cookie] + ConnectionListener.check_whether_accept_new_connection( + cookie, client, clients) + + @staticmethod + def get_another_client(cookie: int, client: "Client"): + if cookie not in ConnectionListener.cookie_pool: + raise ValueError("cookie not add to pool") + else: + clients = ConnectionListener.cookie_pool[cookie] + # if current client is not in the pair + if client not in clients: + raise ValueError("client not in cookie") + if len(clients) != 2: + raise ValueError("2 clients are not ready") + return clients[0] if clients[1] == client else clients[1] + + @staticmethod + def is_both_client_ready(cookie: int) -> bool: + clients = ConnectionListener.cookie_pool[cookie] + if len(clients) != 2: + return False + else: + return True + + @staticmethod + def check_whether_accept_new_connection(cookie: int, client: "Client", clients: list["Client"]): + # if current clients is in the pair + if len(clients) == 2: + if client in clients: + return + else: + raise UniSpyException( + f"cookie: {cookie} is alive, you can not neogotiate with exist connections") + + # if current client is not in the pair + if len(clients) == 1 and client not in clients: + clients.append(client) diff --git a/src/frontends/gamespy/protocols/game_traffic_relay/applications/handlers.py b/src/frontends/gamespy/protocols/game_traffic_relay/applications/handlers.py new file mode 100644 index 000000000..02057d388 --- /dev/null +++ b/src/frontends/gamespy/protocols/game_traffic_relay/applications/handlers.py @@ -0,0 +1,82 @@ +from datetime import datetime +from frontends.gamespy.library.abstractions.client import ClientBase +from frontends.gamespy.library.abstractions.contracts import RequestBase +from frontends.gamespy.library.abstractions.handler import CmdHandlerBase +from frontends.gamespy.protocols.game_traffic_relay.applications.client import Client +from frontends.gamespy.protocols.game_traffic_relay.applications.connection import ConnectStatus, ConnectionListener +from frontends.gamespy.protocols.game_traffic_relay.contracts.general import MessageRelayRequest +from frontends.gamespy.protocols.natneg.contracts.requests import PingRequest + + +class PingHandler(CmdHandlerBase): + _request: PingRequest + _client: Client + + def __init__(self, client: Client, request: PingRequest) -> None: + assert isinstance(request, PingRequest) + super().__init__(client, request) + self._is_uploading = False + + def _data_operate(self) -> None: + match self._client.info.status: + case ConnectStatus.WAITING_FOR_ANOTHER: + self.__waiting_for_another() + case ConnectStatus.CONNECTING: + if self._client.info.ping_recv_times >= 7: + self._client.log_info( + "Negotiation is finished, ignore ping packet") + return + self.__connecting() + + def __waiting_for_another(self): + is_exist = ConnectionListener.is_client_exist( + self._request.cookie, self._client + ) + if not is_exist: + ConnectionListener.add_client( + self._request.cookie, self._client) + self._client.info.cookie = self._request.cookie + self._client.log_info( + f"Add client to listener cookie:{self._request.cookie}" + ) + else: + assert self._client.info.cookie is not None + is_both_client_ready = ConnectionListener.is_both_client_ready( + self._client.info.cookie) + if is_both_client_ready: + self._client.info.status = ConnectStatus.CONNECTING + + def __connecting(self): + assert self._client.info.cookie is not None + handler = MessageRelayHandler( + self._client, MessageRelayRequest(self._request.raw_request)) + handler.handle() + self._client.info.ping_recv_times += 1 + + if ConnectionListener.is_both_client_ready(self._client.info.cookie): + if self._client.info.ping_recv_times >= 7: + self._client.info.status = ConnectStatus.FINISHED + + +class MessageRelayHandler(CmdHandlerBase): + _request: MessageRelayRequest + _client: Client + + def __init__(self, client: ClientBase, request: RequestBase) -> None: + super().__init__(client, request) + + self._is_uploading = False + + def _data_operate(self) -> None: + """ + when we receive udp message, we check whether the client pair is ready. + if client is ready we send the following data to the another client + """ + self._client.info.last_receive_time = datetime.now() + assert self._client.info.cookie is not None + another_client = ConnectionListener.get_another_client( + self._client.info.cookie, self._client) + another_client.connection.send(self._request.raw_request) + self._client.log_network_sending( + f"=> [{another_client.connection.ip_endpoint}] {self._request.raw_request}" + ) diff --git a/src/frontends/gamespy/protocols/game_traffic_relay/applications/server_launcher.py b/src/frontends/gamespy/protocols/game_traffic_relay/applications/server_launcher.py new file mode 100644 index 000000000..229b47843 --- /dev/null +++ b/src/frontends/gamespy/protocols/game_traffic_relay/applications/server_launcher.py @@ -0,0 +1,57 @@ +from datetime import datetime, timedelta +from frontends.gamespy.library.abstractions.server_launcher import ServicesFactory, ServiceBase +from frontends.gamespy.library.configs import CONFIG +from frontends.gamespy.library.log.log_manager import GLOBAL_LOGGER +from frontends.gamespy.library.network.udp_handler import UdpServer +from frontends.gamespy.protocols.game_traffic_relay.applications.client import Client +from frontends.gamespy.protocols.game_traffic_relay.applications.connection import ConnectionListener +from frontends.gamespy.protocols.game_traffic_relay.contracts.general import ( + GtrHeartbeat, +) + + +class Service(ServiceBase): + + def __init__(self) -> None: + super().__init__( + config_name="GameTrafficRelay", + client_cls=Client, + network_server_cls=UdpServer, + ) + + def _post_task(self): + super()._post_task() + self.__gtr_heartbeat() + self.__check_expired_connection() + + def __gtr_heartbeat(self): + assert self.config + req = GtrHeartbeat( + server_id=self.config.server_id, + public_ip_address=self.config.listening_address, + public_port=self.config.listening_port, + client_count=len(ConnectionListener.client_pool), + ) + req_str = req.model_dump_json() + self._heartbeat_to_backend( + f"{CONFIG.backend.url}/GameSpy/GameTrafficRelay/Heartbeat", req_str + ) + + def __check_expired_connection(self): + expired_time = datetime.now() - timedelta(seconds=30) + try: + for key in ConnectionListener.cookie_pool.keys(): + pair = ConnectionListener.cookie_pool[key] + if pair[0].info.last_receive_time < expired_time: + del ConnectionListener.cookie_pool[key] + del ConnectionListener.client_pool[pair[0].connection.ip_endpoint] + del ConnectionListener.client_pool[pair[1].connection.ip_endpoint] + except Exception as e: + GLOBAL_LOGGER.warn(f"Errors occured when doing cookie delete: {e}") + + +if __name__ == "__main__": + from frontends.gamespy.library.extentions.debug_helper import DebugHelper + gtr = Service() + helper = DebugHelper("./frontends/", ServicesFactory([gtr])) + helper.start() diff --git a/src/frontends/gamespy/protocols/game_traffic_relay/applications/switcher.py b/src/frontends/gamespy/protocols/game_traffic_relay/applications/switcher.py new file mode 100644 index 000000000..d0f538b7a --- /dev/null +++ b/src/frontends/gamespy/protocols/game_traffic_relay/applications/switcher.py @@ -0,0 +1,48 @@ + +from frontends.gamespy.library.abstractions.handler import CmdHandlerBase +from frontends.gamespy.library.abstractions.switcher import SwitcherBase +from frontends.gamespy.library.exceptions.general import UniSpyException +from frontends.gamespy.protocols.game_traffic_relay.applications.client import Client +from frontends.gamespy.protocols.game_traffic_relay.applications.connection import ConnectStatus, ConnectionListener +from frontends.gamespy.protocols.game_traffic_relay.applications.handlers import ( + MessageRelayHandler, + PingHandler) +from frontends.gamespy.protocols.game_traffic_relay.contracts.general import MessageRelayRequest +from frontends.gamespy.protocols.natneg.aggregations.enums import RequestType +from frontends.gamespy.protocols.natneg.contracts.requests import PingRequest + + +class Switcher(SwitcherBase): + _raw_request: bytes + _client: Client + + def __init__(self, client: Client, raw_request: bytes) -> None: + super().__init__(client, raw_request) + assert issubclass(type(client), Client) + assert isinstance(raw_request, bytes) + + def _process_raw_request(self) -> None: + name = self._raw_request[7] + if name == RequestType.PING.value: + self._requests.append((RequestType.PING, self._raw_request)) + else: + self._requests.append((RequestType.RELAY_MSG, self._raw_request)) + + def _create_cmd_handlers( + self, name: RequestType, raw_request: bytes + ) -> CmdHandlerBase: + assert isinstance(name, RequestType) + assert isinstance(raw_request, bytes) + saved_client = ConnectionListener.get_client_by_ip( + self._client.connection.ip_endpoint) + if saved_client is None: + client = self._client + else: + client = saved_client + match name: + case RequestType.PING: + return PingHandler(client, PingRequest(raw_request)) + case RequestType.RELAY_MSG: + return MessageRelayHandler(client, MessageRelayRequest(raw_request)) + case _: + raise UniSpyException("unable to handle the message") diff --git a/src/frontends/gamespy/protocols/game_traffic_relay/contracts/general.py b/src/frontends/gamespy/protocols/game_traffic_relay/contracts/general.py new file mode 100644 index 000000000..6d7615f31 --- /dev/null +++ b/src/frontends/gamespy/protocols/game_traffic_relay/contracts/general.py @@ -0,0 +1,30 @@ +from pydantic import BaseModel, UUID4 + +from frontends.gamespy.library.abstractions.contracts import RequestBase +from frontends.gamespy.protocols.natneg.aggregations.enums import NatClientIndex, NatPortType + + +class InitPacketInfo(BaseModel): + server_id: UUID4 + cookie: int + version: int + port_type: NatPortType + client_index: NatClientIndex + game_name: str + use_game_port: bool + public_ip: str + public_port: int + private_ip: str + private_port: int + + +class GtrHeartbeat(BaseModel): + server_id: UUID4 + public_ip_address: str + public_port: int + client_count: int + + +class MessageRelayRequest(RequestBase): + raw_request: bytes + pass diff --git a/src/frontends/gamespy/protocols/natneg/__init__.py b/src/frontends/gamespy/protocols/natneg/__init__.py new file mode 100644 index 000000000..a752c796b --- /dev/null +++ b/src/frontends/gamespy/protocols/natneg/__init__.py @@ -0,0 +1,4 @@ +# from .aggregations.enums import ( +# NatClientIndex, + +# ) \ No newline at end of file diff --git a/src/frontends/gamespy/protocols/natneg/abstractions/contracts.py b/src/frontends/gamespy/protocols/natneg/abstractions/contracts.py new file mode 100644 index 000000000..ab3447117 --- /dev/null +++ b/src/frontends/gamespy/protocols/natneg/abstractions/contracts.py @@ -0,0 +1,95 @@ + +import frontends.gamespy.library.abstractions.contracts as lib +from frontends.gamespy.protocols.natneg.aggregations.enums import ( + NatClientIndex, + NatPortType, + RequestType, + ResponseType, +) +from frontends.gamespy.library.extentions.bytes_extentions import ip_to_4_bytes + +MAGIC_DATA = b"\xfd\xfc\x1e\x66\x6a\xb2" + + +class RequestBase(lib.RequestBase): + version: int + #! check bytes order + cookie: int + """ + byteorder: + big + """ + port_type: NatPortType + command_name: RequestType + raw_request: bytes + + def __init__(self, raw_request: bytes | None = None): + assert isinstance(raw_request, bytes) + self.raw_request = raw_request + + def parse(self) -> None: + if len(self.raw_request) < 12: + return + + self.version = int(self.raw_request[6]) + self.command_name = RequestType(self.raw_request[7]) + self.cookie = int.from_bytes( + self.raw_request[8:12]) + self.port_type = NatPortType(self.raw_request[12]) + + +class ResultBase(lib.ResultBase): + packet_type: ResponseType + version: int + cookie: int + pass + + +class ResponseBase(lib.ResponseBase): + _result: ResultBase + sending_buffer: bytes + + def __init__(self, result: ResultBase) -> None: + assert issubclass(type(result), ResultBase) + super().__init__(result) + + def build(self) -> None: + data = bytearray() + data.extend(MAGIC_DATA) + data.append(self._result.version) + data.append(self._result.packet_type.value) + data.extend(self._result.cookie.to_bytes(4)) + self.sending_buffer = bytes(data) + + +class CommonRequestBase(RequestBase): + client_index: NatClientIndex + use_game_port: bool + + def parse(self): + super().parse() + self.client_index = NatClientIndex(self.raw_request[13]) + self.use_game_port = bool(self.raw_request[14]) + + +class CommonResultBase(ResultBase): + public_ip_addr: str + public_port: int + port_type: NatPortType + client_index: NatClientIndex + use_game_port: bool + + +class CommonResponseBase(ResponseBase): + _result: CommonResultBase + + def build(self) -> None: + super().build() + data = bytearray() + data.extend(self.sending_buffer) + data.append(self._result.port_type.value) + data.append(self._result.client_index.value) + data.append(int(self._result.use_game_port)) + data.extend(ip_to_4_bytes(self._result.public_ip_addr)) + data.extend(self._result.public_port.to_bytes(2)) + self.sending_buffer = bytes(data) diff --git a/src/frontends/gamespy/protocols/natneg/abstractions/handlers.py b/src/frontends/gamespy/protocols/natneg/abstractions/handlers.py new file mode 100644 index 000000000..590268c37 --- /dev/null +++ b/src/frontends/gamespy/protocols/natneg/abstractions/handlers.py @@ -0,0 +1,19 @@ +from frontends.gamespy.protocols.natneg.applications.client import Client +from frontends.gamespy.protocols.natneg.abstractions.contracts import RequestBase, ResponseBase, ResultBase +import frontends.gamespy.library.abstractions.handler as lib + + +class CmdHandlerBase(lib.CmdHandlerBase): + _request: RequestBase + _result: ResultBase + _response: ResponseBase + + def __init__(self, client: Client, request: RequestBase) -> None: + super().__init__(client, request) + assert isinstance(client, Client) + assert issubclass(type(request), RequestBase) + + +if __name__ == "__main__": + # cmd = CmdHandlerBase(None, None) + pass diff --git a/src/frontends/gamespy/protocols/natneg/aggregations/enums.py b/src/frontends/gamespy/protocols/natneg/aggregations/enums.py new file mode 100644 index 000000000..94c488922 --- /dev/null +++ b/src/frontends/gamespy/protocols/natneg/aggregations/enums.py @@ -0,0 +1,94 @@ +from enum import Enum, IntEnum + + +class RequestType(Enum): + INIT = 0 + ERT_ACK = 3 + CONNECT = 5 + CONNECT_ACK = 6 + """ + only used in client, not used by server + """ + PING = 7 + ADDRESS_CHECK = 10 + NATIFY_REQUEST = 12 + REPORT = 13 + PRE_INIT = 15 + RELAY_MSG = 100 + """ + unispy custom request type for GTR + """ + +class NatPortType(Enum): + GP = 0 + NN1 = 1 + NN2 = 2 + NN3 = 3 + + +class ResponseType(Enum): + INIT_ACK = 1 + ERT_TEST = 2 + ERT_ACK = 3 + CONNECT = 5 + ADDRESS_REPLY = 11 + REPORT_ACK = 14 + PRE_INIT_ACK = 16 + + +class ConnectPacketStatus(Enum): + NO_ERROR = 0 + BAD_HEART_BEAT = 1 + INIT_PACKET_TIMEOUT = 2 + + +class NatifyPacketType(Enum): + PACKET_MAP_1A = 0 + PACKET_MAP_2 = 1 + PACKET_MAP_3 = 2 + PACKET_MAP_1B = 3 + NUM_PACKETS = 4 + + +class PreInitState(Enum): + WAITING_FOR_CLIENT = 0 + WAITING_FOR_MATCH_UP = 1 + READY = 2 + + +class NatType(IntEnum): + NO_NAT = 0 + FIRE_WALL_ONLY = 1 + """ + C发数据到210.21.12.140:8000,NAT会将数据包送到A(192.168.0.4:5000).因为NAT上已经有了192.168.0.4:5000到210.21.12.140:8000的映射 + """ + FULL_CONE = 2 + """ + C无法和A通信,因为A从来没有和C通信过,NAT将拒绝C试图与A连接的动作.但B可以通过210.21.12.140:8000与A的 192.168.0.4:5000通信,且这里B可以使用任何端口与A通信.如:210.15.27.166:2001 -> 210.21.12.140:8000,NAT会送到A的5000端口上 + """ + ADDRESS_RESTRICTED_CONE = 3 + """ + C无法与A通信,因为A从来没有和C通信过.而B也只能用它的210.15.27.166:2000与A的192.168.0.4:5000通信,因为A也从来没有和B的其他端口通信过.该类型NAT是端口受限的. + """ + PORT_RESTRICTED_CONE = 4 + """ + 上面3种类型,统称为Cone NAT,有一个共同点:只要是从同一个内部地址和端口出来的包,NAT都将它转换成同一个外部地址和端口.但是Symmetric有点不同,具体表现在: 只要是从同一个内部地址和端口出来,且到同一个外部目标地址和端口,则NAT也都将它转换成同一个外部地址和端口.但如果从同一个内部地址和端口出来,是 到另一个外部目标地址和端口,则NAT将使用不同的映射,转换成不同的端口(外部地址只有一个,故不变).而且和Port Restricted Cone一样,只有曾经收到过内部地址发来包的外部地址,才能通过NAT映射后的地址向该内部地址发包. + """ + SYMMETRIC = 5 + """ + 端口分配是随机的,无法确定下一次NAT映射端口. + """ + UNKNOWN = 6 + + +class NatPortMappingScheme(Enum): + UNRECOGNIZED = 0 + PRIVATE_AS_PUBLIC = 1 + CONSISTENT_PORT = 2 + INCREMENTAL = 3 + MIXED = 4 + + +class NatClientIndex(Enum): + GAME_CLIENT = 0 + GAME_SERVER = 1 diff --git a/src/frontends/gamespy/protocols/natneg/aggregations/exceptions.py b/src/frontends/gamespy/protocols/natneg/aggregations/exceptions.py new file mode 100644 index 000000000..7ca37e69e --- /dev/null +++ b/src/frontends/gamespy/protocols/natneg/aggregations/exceptions.py @@ -0,0 +1,5 @@ +from frontends.gamespy.library.exceptions.general import UniSpyException + + +class NatNegException(UniSpyException): + pass diff --git a/src/frontends/gamespy/protocols/natneg/aggregations/natneg_cookie.py b/src/frontends/gamespy/protocols/natneg/aggregations/natneg_cookie.py new file mode 100644 index 000000000..c1c8d9511 --- /dev/null +++ b/src/frontends/gamespy/protocols/natneg/aggregations/natneg_cookie.py @@ -0,0 +1,13 @@ + + +from pydantic import BaseModel + + +class NatNegCookie(BaseModel): + host_ip: str + host_port: int + heartbeat_ip: str + heartbeat_port: int + game_name: str + natneg_message: list + instant_key: int diff --git a/src/frontends/gamespy/protocols/natneg/applications/client.py b/src/frontends/gamespy/protocols/natneg/applications/client.py new file mode 100644 index 000000000..9bcee0430 --- /dev/null +++ b/src/frontends/gamespy/protocols/natneg/applications/client.py @@ -0,0 +1,18 @@ +from frontends.gamespy.library.abstractions.client import ClientBase +from frontends.gamespy.library.log.log_manager import LogWriter +from frontends.gamespy.library.network.udp_handler import UdpConnection +from frontends.gamespy.library.configs import ServerConfig + + +class Client(ClientBase): + client_pool: dict[str, "Client"] = {} + + def __init__(self, connection: UdpConnection, server_config: ServerConfig, logger: LogWriter): + super().__init__(connection, server_config, logger) + self.is_log_raw = True + + def _create_switcher(self, buffer: bytes): + assert isinstance(buffer, bytes) + from frontends.gamespy.protocols.natneg.applications.switcher import Switcher + + return Switcher(self, buffer) diff --git a/src/frontends/gamespy/protocols/natneg/applications/handlers.py b/src/frontends/gamespy/protocols/natneg/applications/handlers.py new file mode 100644 index 000000000..78f1f75b1 --- /dev/null +++ b/src/frontends/gamespy/protocols/natneg/applications/handlers.py @@ -0,0 +1,203 @@ +from frontends.gamespy.protocols.natneg.abstractions.handlers import CmdHandlerBase +from frontends.gamespy.protocols.natneg.aggregations.enums import ConnectPacketStatus, RequestType +from frontends.gamespy.protocols.natneg.applications.client import Client +from frontends.gamespy.protocols.natneg.contracts.requests import ( + AddressCheckRequest, + ConnectAckRequest, + ConnectRequest, + ErtAckRequest, + InitRequest, + NatifyRequest, + ReportRequest, +) +from frontends.gamespy.protocols.natneg.contracts.responses import ( + AddressCheckResponse, + ConnectResponse, + ErcAckResponse, + InitResponse, + NatifyResponse, +) +from frontends.gamespy.protocols.natneg.contracts.results import ( + AddressCheckResult, + ConnectResult, + ErtAckResult, + InitResult, + NatifyResult, + ReportResult, +) + + +class AddressCheckHandler(CmdHandlerBase): + _request: AddressCheckRequest + _result: AddressCheckResult + _response: AddressCheckResponse + + def __init__(self, client: Client, request: AddressCheckRequest) -> None: + assert isinstance(client, Client) + assert isinstance(request, AddressCheckRequest) + super().__init__(client, request) + self._is_uploading = False + + def _response_construct(self) -> None: + """ + address check did not require restapi backend, \n + just send the remote ip back to the client + """ + self._result = AddressCheckResult( + public_ip_addr=self._client.connection.remote_ip, + public_port=self._client.connection.remote_port, + version=self._request.version, + cookie=self._request.cookie, + client_index=self._request.client_index, + use_game_port=self._request.use_game_port, + port_type=self._request.port_type + ) + self._result.public_ip_addr = self._client.connection.remote_ip + self._result.public_port = self._client.connection.remote_port + self._response = AddressCheckResponse(self._result) + + +class ConnectAckHandler(CmdHandlerBase): + _request: ConnectAckRequest + + def __init__(self, client: Client, request: ConnectAckRequest) -> None: + assert isinstance(request, ConnectAckRequest) + super().__init__(client, request) + self._is_uploading = False + + def _response_construct(self) -> None: + self._client.log_info( + f"client: {self._client.connection.remote_ip} index:{self._request.client_index} is received the connect packet.") + + +class ConnectHandler(CmdHandlerBase): + _request: ConnectRequest + _result: ConnectResult + _response: ConnectResponse + + def __init__(self, client: Client, request: ConnectRequest) -> None: + assert isinstance(request, ConnectRequest) + super().__init__(client, request) + + def _response_construct(self) -> None: + if not self._result.is_both_client_ready: + self._client.log_warn( + f"init cache is not enough for cookie: {self._request.cookie}") + return + super()._response_construct() + + +class ErtAckHandler(CmdHandlerBase): + _request: ErtAckRequest + _response: ErcAckResponse + + def __init__(self, client: Client, request: ErtAckRequest) -> None: + assert isinstance(request, ErtAckRequest) + super().__init__(client, request) + + def _data_operate(self) -> None: + """ + Natneg require fast response, so we do not wait for upload data. + """ + self._result = ErtAckResult( + public_ip_addr=self._client.connection.remote_ip, + public_port=self._client.connection.remote_port, + version=self._request.version, + cookie=self._request.cookie, + client_index=self._request.client_index, + use_game_port=self._request.use_game_port, + port_type=self._request.port_type + ) + + +class InitHandler(CmdHandlerBase): + """ + In init process, we need response the initresponse first to make client not timeout + """ + + _request: InitRequest + _client: Client + _result: InitResult + # _response: InitResponse + + def __init__(self, client: Client, request: InitRequest) -> None: + assert isinstance(request, InitRequest) + super().__init__(client, request) + + def _response_construct(self): + """ + Natneg require fast response, so we do not wait for upload data. + """ + self._result = InitResult( + public_ip_addr=self._client.connection.remote_ip, + public_port=self._client.connection.remote_port, + version=self._request.version, + cookie=self._request.cookie, + client_index=self._request.client_index, + use_game_port=self._request.use_game_port, + port_type=self._request.port_type + ) + + self._response = InitResponse(self._result) + + def handle(self) -> None: + try: + # we first log this class + self._log_current_class() + # then we handle it + self._request_check() + self._response_construct() + # first send the response + if self._response is None: + return + self._response_send() + # then send to backends + self._data_operate() + self._invoke_connect() + except Exception as ex: + self._handle_exception(ex) + + def _invoke_connect(self) -> None: + connect_raw = ConnectRequest.build( + version=self._request.version, + command_name=RequestType.CONNECT, + cookie=self._request.cookie, + port_type=self._request.port_type, + client_index=self._request.client_index, + use_game_port=self._request.use_game_port + ) + request = ConnectRequest(connect_raw) + handler = ConnectHandler(self._client, request) + handler.handle() + + +class NatifyHandler(CmdHandlerBase): + _request: NatifyRequest + + def __init__(self, client: Client, request: NatifyRequest) -> None: + assert isinstance(request, NatifyRequest) + super().__init__(client, request) + self._is_uploading = False + + def _response_construct(self): + """ + Natneg require fast response, so we do not wait for upload data. + """ + self._result = NatifyResult( + public_ip_addr=self._client.connection.remote_ip, + public_port=self._client.connection.remote_port, + version=self._request.version, + cookie=self._request.cookie, + client_index=self._request.client_index, + use_game_port=self._request.use_game_port, + port_type=self._request.port_type + ) + self._response = NatifyResponse(self._result) + + +class ReportHandler(CmdHandlerBase): + _request: ReportRequest + + def __init__(self, client: Client, request: ReportRequest) -> None: + assert isinstance(request, ReportRequest) + super().__init__(client, request) diff --git a/src/frontends/gamespy/protocols/natneg/applications/server_launcher.py b/src/frontends/gamespy/protocols/natneg/applications/server_launcher.py new file mode 100644 index 000000000..a9b2bf440 --- /dev/null +++ b/src/frontends/gamespy/protocols/natneg/applications/server_launcher.py @@ -0,0 +1,21 @@ +from frontends.gamespy.library.abstractions.server_launcher import ServicesFactory, ServiceBase +from frontends.gamespy.library.network.udp_handler import UdpServer +from frontends.gamespy.protocols.natneg.applications.client import Client + + +class Service(ServiceBase): + server: UdpServer + + def __init__(self) -> None: + super().__init__( + config_name="NatNegotiation", + client_cls=Client, + network_server_cls=UdpServer, + ) + + +if __name__ == "__main__": + from frontends.gamespy.library.extentions.debug_helper import DebugHelper + nn = Service() + helper = DebugHelper("./frontends/", ServicesFactory([nn])) + helper.start() diff --git a/src/frontends/gamespy/protocols/natneg/applications/switcher.py b/src/frontends/gamespy/protocols/natneg/applications/switcher.py new file mode 100644 index 000000000..ff463a65f --- /dev/null +++ b/src/frontends/gamespy/protocols/natneg/applications/switcher.py @@ -0,0 +1,72 @@ + +from frontends.gamespy.library.abstractions.switcher import SwitcherBase +from frontends.gamespy.library.exceptions.general import UniSpyException +from frontends.gamespy.protocols.natneg.abstractions.handlers import CmdHandlerBase +from frontends.gamespy.protocols.natneg.applications.client import Client +from frontends.gamespy.protocols.natneg.contracts.requests import ( + AddressCheckRequest, + ConnectAckRequest, + ConnectRequest, + ErtAckRequest, + InitRequest, + NatifyRequest, + ReportRequest, +) +from frontends.gamespy.protocols.natneg.aggregations.enums import RequestType +from frontends.gamespy.protocols.natneg.applications.handlers import ( + AddressCheckHandler, + ConnectAckHandler, + ConnectHandler, + ErtAckHandler, + InitHandler, + NatifyHandler, + ReportHandler, +) + + +class Switcher(SwitcherBase): + _raw_request: bytes + _client: Client + + def __init__(self, client: Client, raw_request: bytes) -> None: + super().__init__(client, raw_request) + assert issubclass(type(client), Client) + assert isinstance(raw_request, bytes) + + def _process_raw_request(self) -> None: + if len(self._raw_request) < 8: + self._client.log_debug("incoming buffer length is not valid") + return + name = self._raw_request[7] + if name not in RequestType: + self._client.log_debug(f"Request: {name} is not a valid request.") + return + self._requests.append((RequestType(name), self._raw_request)) + + def _create_cmd_handlers( + self, name: RequestType, raw_request: bytes + ) -> CmdHandlerBase | None: + assert isinstance(name, RequestType) + assert isinstance(raw_request, bytes) + match name: + case RequestType.NATIFY_REQUEST: + return NatifyHandler(self._client, NatifyRequest(raw_request)) + case RequestType.INIT: + return InitHandler(self._client, InitRequest(raw_request)) + # case RequestType. + case RequestType.ERT_ACK: + return ErtAckHandler(self._client, ErtAckRequest(raw_request)) + case RequestType.CONNECT: + return ConnectHandler(self._client, ConnectRequest(raw_request)) + case RequestType.CONNECT_ACK: + return ConnectAckHandler(self._client, ConnectAckRequest(raw_request)) + case RequestType.ADDRESS_CHECK: + return AddressCheckHandler( + self._client, AddressCheckRequest(raw_request) + ) + case RequestType.REPORT: + return ReportHandler(self._client, ReportRequest(raw_request)) + case RequestType.PRE_INIT: + return None + case _: + return None diff --git a/src/frontends/gamespy/protocols/natneg/contracts/requests.py b/src/frontends/gamespy/protocols/natneg/contracts/requests.py new file mode 100644 index 000000000..f923c3018 --- /dev/null +++ b/src/frontends/gamespy/protocols/natneg/contracts/requests.py @@ -0,0 +1,136 @@ +from socket import inet_ntoa +import socket +import struct + + +# from frontends.gamespy.library.extentions.string_extentions import IPEndPoint +from frontends.gamespy.protocols.natneg.abstractions.contracts import ( + MAGIC_DATA, + CommonRequestBase, + RequestBase, +) +from frontends.gamespy.protocols.natneg.aggregations.enums import ( + NatClientIndex, + NatPortMappingScheme, + NatPortType, + NatType, + PreInitState, + RequestType, +) + + +class AddressCheckRequest(CommonRequestBase): + pass + + +class PingRequest(RequestBase): + def parse(self) -> None: + self.version = int(self.raw_request[6]) + self.command_name = RequestType(self.raw_request[7]) + self.cookie = int.from_bytes( + self.raw_request[8:12]) + self.ip = socket.inet_ntoa(self.raw_request[12:16]) + self.port = int.from_bytes(self.raw_request[16:18]) + # port here is not in little endian + self.got_your_data = bool(self.raw_request[18]) + self.is_finished = bool(self.raw_request[19]) + + +class ConnectAckRequest(RequestBase): + client_index: NatClientIndex + + def parse(self) -> None: + if len(self.raw_request) < 12: + return + + self.version = int(self.raw_request[6]) + self.command_name = RequestType(self.raw_request[7]) + self.cookie = int.from_bytes( + self.raw_request[8:12]) + self.client_index = NatClientIndex(self.raw_request[13]) + + +class ConnectRequest(CommonRequestBase): + """ + Server will send this request to client to let them connect to each other + """ + + client_index: NatClientIndex + + @staticmethod + def build(version: int, command_name: RequestType, cookie: int, port_type: NatPortType, client_index: NatClientIndex, use_game_port: bool) -> bytes: + data = bytes() + data += MAGIC_DATA + data += version.to_bytes(1) + data += command_name.value.to_bytes(1) + data += cookie.to_bytes(4) + data += port_type.value.to_bytes(1) + data += client_index.value.to_bytes(1) + data += use_game_port.to_bytes(1) + return data + + +class ErtAckRequest(CommonRequestBase): + pass + + +class InitRequest(CommonRequestBase): + game_name: str | None + private_ip: str + private_port: int + + def __init__(self, raw_request: bytes | None = None): + super().__init__(raw_request) + self.game_name = "unknown" + + def parse(self) -> None: + super().parse() + ip_bytes = self.raw_request[15:19] + port_bytes = self.raw_request[19:21][::-1] + port = struct.unpack("H", port_bytes)[0] + ip_address_str = inet_ntoa(ip_bytes) + self.private_ip = ip_address_str + self.private_port = port + + if len(self.raw_request) > 21 and self.raw_request[-1] == 0: + game_name_bytes = self.raw_request[21:-1] + game_name = game_name_bytes.decode("ascii").replace("\x00", "") + if len(game_name) != 0: + self.game_name = game_name + + +class NatifyRequest(CommonRequestBase): + pass + + +class PreInitRequest(RequestBase): + state: PreInitState + target_cookie: int + + def parse(self) -> None: + super().parse() + self.state = PreInitState(self.raw_request[12]) + self.target_cookie = int.from_bytes(self.raw_request[13:17]) + + +class ReportRequest(CommonRequestBase): + is_nat_success: bool + game_name: str + nat_type: NatType + mapping_scheme: NatPortMappingScheme + + def parse(self): + super().parse() + if len(self.raw_request) < 12: + return + self.version = self.raw_request[6] + self.command_name = RequestType(self.raw_request[7]) + self.cookie = int.from_bytes(self.raw_request[8:12], byteorder="big") + self.port_type = NatPortType(self.raw_request[12]) + self.client_index = NatClientIndex(self.raw_request[13]) + self.is_nat_success = False if self.raw_request[14] == 0 else True + self.nat_type = NatType(self.raw_request[15]) + self.mapping_scheme = NatPortMappingScheme(self.raw_request[17]) + + end_index = self.raw_request[23:].index(0) + self.game_name = self.raw_request[23: 23 + end_index].decode("ascii") diff --git a/src/frontends/gamespy/protocols/natneg/contracts/responses.py b/src/frontends/gamespy/protocols/natneg/contracts/responses.py new file mode 100644 index 000000000..49f913fac --- /dev/null +++ b/src/frontends/gamespy/protocols/natneg/contracts/responses.py @@ -0,0 +1,64 @@ +import socket +from frontends.gamespy.protocols.natneg.abstractions.contracts import ( + CommonResponseBase, + ResponseBase, +) +from frontends.gamespy.protocols.natneg.contracts.results import ( + AddressCheckResult, + ConnectResult, + ErtAckResult, + InitResult, + NatifyResult, +) + + +class InitResponse(CommonResponseBase): + _result: InitResult + + def __init__(self, result: InitResult) -> None: + assert isinstance(result, InitResult) + super().__init__(result) + + +class ErcAckResponse(InitResponse): + _result: ErtAckResult + + def __init__(self, result: ErtAckResult) -> None: + assert isinstance(result, ErtAckResult) + self._result = result + + +class NatifyResponse(CommonResponseBase): + _result: NatifyResult + + def __init__(self, result: NatifyResult) -> None: + assert isinstance(result, NatifyResult) + super().__init__(result) + + +class AddressCheckResponse(CommonResponseBase): + _result: AddressCheckResult + + def __init__( + self, result: AddressCheckResult + ) -> None: + assert isinstance(result, AddressCheckResult) + super().__init__(result) + + +class ConnectResponse(ResponseBase): + _result: ConnectResult + + def build(self) -> None: + assert self._result.ip is not None + assert self._result.port is not None + assert self._result.status is not None + super().build() + data = bytearray() + data.extend(self.sending_buffer) + data.extend(socket.inet_aton(self._result.ip)) + data.extend(self._result.port.to_bytes(2)) + # got your data + data.append(1) + data.append(self._result.status.value) + self.sending_buffer = bytes(data) diff --git a/src/frontends/gamespy/protocols/natneg/contracts/results.py b/src/frontends/gamespy/protocols/natneg/contracts/results.py new file mode 100644 index 000000000..f486c20f5 --- /dev/null +++ b/src/frontends/gamespy/protocols/natneg/contracts/results.py @@ -0,0 +1,42 @@ +from frontends.gamespy.protocols.natneg.abstractions.contracts import CommonResultBase, ResultBase +from frontends.gamespy.protocols.natneg.aggregations.enums import ( + ConnectPacketStatus, + PreInitState, + ResponseType, +) + + +class AddressCheckResult(CommonResultBase): + packet_type: ResponseType = ResponseType.ADDRESS_REPLY + + +class ConnectResult(ResultBase): + is_both_client_ready: bool + status: ConnectPacketStatus | None + ip: str | None + port: int | None + packet_type: ResponseType = ResponseType.CONNECT + + +class InitResult(CommonResultBase): + packet_type: ResponseType = ResponseType.INIT_ACK + + +class ErtAckResult(InitResult): + packet_type: ResponseType = ResponseType.ERT_ACK + + +class NatifyResult(CommonResultBase): + packet_type: ResponseType = ResponseType.ERT_TEST + + +class PreInitResult(ResultBase): + client_index: int + state: PreInitState + client_id: int + packet_type: ResponseType = ResponseType.PRE_INIT_ACK + state = PreInitState.READY + + +class ReportResult(ResultBase): + packet_type: ResponseType = ResponseType.REPORT_ACK diff --git a/src/frontends/gamespy/protocols/presence_connection_manager/__init__.py b/src/frontends/gamespy/protocols/presence_connection_manager/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/gamespy/protocols/presence_connection_manager/abstractions/contracts.py b/src/frontends/gamespy/protocols/presence_connection_manager/abstractions/contracts.py new file mode 100644 index 000000000..54c000d1d --- /dev/null +++ b/src/frontends/gamespy/protocols/presence_connection_manager/abstractions/contracts.py @@ -0,0 +1,53 @@ + +from frontends.gamespy.library.extentions.gamespy_utils import convert_to_key_value +from frontends.gamespy.protocols.presence_search_player.aggregates.exceptions import ( + GPParseException, +) +from typing import Dict, Optional +import frontends.gamespy.library.abstractions.contracts as lib + + +def normalize_request(message: str): + if "login" in message: + message = message.replace("\\-", "\\") + pos = message.index("\\", message.index("\\") + 1) + if message[pos: pos + 2] != "\\\\": + message = message[:pos] + "\\" + message[pos:] + return message + + +class RequestBase(lib.RequestBase): + command_name: str + operation_id: int + raw_request: str + _request_dict: Dict[str, str] + + def __init__(self, raw_request: str) -> None: + assert isinstance(raw_request, str) + super().__init__(raw_request) + + def parse(self): + super().parse() + self._request_dict = convert_to_key_value(self.raw_request) + self.command_name = list(self._request_dict.keys())[0] + + if "id" in self._request_dict: + try: + self.operation_id = int(self._request_dict["id"]) + except Exception: + raise GPParseException("namespaceid is invalid.") + + +class ResultBase(lib.ResultBase): + operation_id: int + pass + + +class ResponseBase(lib.ResponseBase): + _request: RequestBase + _result: ResultBase + sending_buffer: str + + def __init__(self, result: ResultBase) -> None: + assert issubclass(type(result), ResultBase) + super().__init__(result) diff --git a/src/frontends/gamespy/protocols/presence_connection_manager/abstractions/handlers.py b/src/frontends/gamespy/protocols/presence_connection_manager/abstractions/handlers.py new file mode 100644 index 000000000..0ad72f4ac --- /dev/null +++ b/src/frontends/gamespy/protocols/presence_connection_manager/abstractions/handlers.py @@ -0,0 +1,34 @@ + +from frontends.gamespy.protocols.presence_connection_manager.applications.client import Client +from frontends.gamespy.protocols.presence_connection_manager.aggregates.enums import LoginStatus +from frontends.gamespy.protocols.presence_search_player.aggregates.exceptions import GPException + +from frontends.gamespy.protocols.presence_connection_manager.abstractions.contracts import ( + RequestBase, + ResultBase, +) +import frontends.gamespy.library.abstractions.handler as lib + + +class CmdHandlerBase(lib.CmdHandlerBase): + _client: Client + _request: RequestBase + _result: ResultBase + + def __init__(self, client: Client, request: RequestBase) -> None: + assert isinstance(client, Client) + assert issubclass(type(request), RequestBase) + super().__init__(client, request) + + def _handle_exception(self, ex) -> None: + if ex is GPException: + self._client.send(ex) + super()._handle_exception(ex) + + +class LoginedHandlerBase(CmdHandlerBase): + + def _request_check(self) -> None: + if self._client.info.login_status != LoginStatus.COMPLETED: + raise GPException("please login first.") + super()._request_check() diff --git a/src/frontends/gamespy/protocols/presence_connection_manager/aggregates/enums.py b/src/frontends/gamespy/protocols/presence_connection_manager/aggregates/enums.py new file mode 100644 index 000000000..bd1706ae7 --- /dev/null +++ b/src/frontends/gamespy/protocols/presence_connection_manager/aggregates/enums.py @@ -0,0 +1,267 @@ +from enum import Enum, IntEnum, IntFlag + + +class BuddyMessageType(IntEnum): + # response + BM_MESSAGE = 1 + BM_REQUEST = 2 + BM_REPLY = 3 # only used on the backend + BM_AUTH = 4 + BM_UTM = 5 + BM_REVOKE = 6 # remote buddy removed from local list + BM_STATUS = 100 + BM_INVITE = 101 + BM_PING = 102 + + # request + BM_PONG = 103 + BM_KEYS_REQUEST = 104 + BM_KEYS_REPLY = 105 + BM_FILE_SEND_REQUEST = 200 + BM_FILE_SEND_REPLY = 201 + BM_FILE_BEGIN = 202 + BM_FILE_END = 203 + BM_FILE_DATA = 204 + BM_FILE_SKIP = 205 + BM_FILE_TRANSFER_THROTTLE = 206 + BM_FILE_TRANSFER_CANCEL = 207 + BM_FILE_TRANSFER_KEEP_ALIVE = 208 + + +class DisconnectReason(IntEnum): + NORMAL_LOGOUT = 0 + KEEP_ALIVE_FAILED = 1 + LOGIN_TIMED_OUT = 2 + INVALID_USERNAME = 3 + INVALID_PASSWORD = 4 + INVALID_LOGIN_QUERY = 5 + CREATE_FAILED_USERNAME_EXISTS = 6 + CREATE_FAILED_DATABASE_ERROR = 7 + GENERAL_ERROR = 8 + DISCONNECTED = 9 + FORCED_LOGOUT = 10 + NEW_LOGIN_DETECTED = 11 + FORCED_SERVER_SHUTDOWN = 12 + CLIENT_CHALLENGE_ALREADY_SENT = 13 + PLAYER_IS_BANNED = 14 + INVALID_PLAYER = 15 + PLAYER_IS_NOT_ACTIVATED = 16 + + +class FireWallType(IntEnum): + NO_FIREWALL = 0 + FIREWALL = 1 + + +class GenderType(IntEnum): + MALE = 0 + FEMALE = 1 + PAT = 2 + + +class GPStatusCode(IntEnum): + OFFLINE = 0 + ONLINE = 1 + PLAYING = 2 + STAGING = 3 + CHATTING = 4 + AWAY = 5 + + +class LoginStatus(IntEnum): + CONNECTED = 0 + PROCESSING = 1 + COMPLETED = 2 + DISCONNECTED = 3 + + +class LoginType(IntEnum): + NICK_EMAIL = 0 + UNIQUENICK_NAMESPACE_ID = 1 + AUTH_TOKEN = 2 + + +class QuietModeType(IntFlag): + SILENCE_NONE = 0x00000000 + SILENCE_MESSAGE = 0x00000001 + SILENCE_UTMS = 0x00000002 + SILENCE_LIST = 0x00000004 + SILENCE_ALL = 0xFFFFFFFF + + +class SdkRevisionType(IntEnum): + UNKNOWN = 0 + GPINEW_AUTH_NOTIFICATION = 1 + GPINEW_REVOKE_NOTIFICATION = 1 << 2 + GPINEW_STATUS_NOTIFICATION = 1 << 3 + GPINEW_LIST_RETRIEVAL_ON_LOGIN = 1 << 4 + GPIREMOTE_AUTH_IDS_NOTIFICATION = 1 << 5 + GPINEW_CD_KEY_REGISTRATION = 1 << 6 + + +class GPBasic(IntEnum): + # Global States + INFO_CACHING = 0x0100 + SIMULATION = 0x0101 + INFO_CACHING_BUDDY_AND_BLOCK_ONLY = 0x0102 + + # Blocking + BLOCKING = 1 + NON_BLOCKING = 0 + + # Firewall + FIREWALL = 1 + NO_FIREWALL = 0 + + # Check Cache + CHECK_CACHE = 1 + DONT_CHECK_CACHE = 0 + + # Is Valid Email + EMAIL_VALID = 1 + EMAIL_INVALID = 0 + + # Fatal Error + FATAL = 1 + NON_FATAL = 0 + + # Sex + MALE = 0x0500 + FEMALE = 0x0501 + PAT = 0x0502 + + # Profile Search + MORE = 0x0600 + DONE = 0x0601 + + # Set Info + NICK = 0x0700 + UNIQUENICK = 0x0701 + EMAIL = 0x0702 + PASSWORD = 0x0703 + FIRST_NAME = 0x0704 + LAST_NAME = 0x0705 + ICQ_UIN = 0x0706 + HOME_PAGE = 0x0707 + ZIP_CODE = 0x0708 + COUNTRY_CODE = 0x0709 + BIRTHDAY = 0x070A + SEX = 0x070B + CPU_BRAND = 0x070C + CPU_SPEED = 0x070D + MEMORY = 0x070E + VIDEO_CARD1_STRING = 0x070F + VIDEO_CARD1_RAM = 0x0710 + VIDEO_CARD2_STRING = 0x0711 + VIDEO_CARD2_RAM = 0x0712 + CONNECTION_ID = 0x0713 + CONNECTION_SPEED = 0x0714 + HAS_NETWORK = 0x0715 + OS_STRING = 0x0716 + AIM_NAME = 0x0717 + PIC = 0x0718 + OCCUPATION_ID = 0x0719 + INDUSTRY_ID = 0x071A + INCOME_ID = 0x071B + MARRIED_ID = 0x071C + CHILD_COUNT = 0x071D + INTEREST1 = 0x071E + + # New Profile + REPLACE = 1 + DONT_REPLACE = 0 + + # Is Connected + CONNECTED = 1 + NOT_CONNECTED = 0 + + # Public mask + MASK_NONE = 0x00000000 + MASK_HOMEPAGE = 0x00000001 + MASK_ZIPCODE = 0x00000002 + MASK_COUNTRYCODE = 0x00000004 + MASK_BIRTHDAY = 0x00000008 + MASK_SEX = 0x00000010 + MASK_EMAIL = 0x00000020 + MASK_ALL = 0xFFFFFFFF + + # Session flags + SESS_IS_CLOSED = 0x00000001 + SESS_IS_OPEN = 0x00000002 + SESS_HAS_PASSWORD = 0x00000004 + SESS_IS_BEHIND_NAT = 0x00000008 + SESS_IS_RANKED = 0x00000010 + + # CPU Brand ID + INTEL = 1 + AMD = 2 + CYRIX = 3 + MOTOROLA = 4 + ALPHA = 5 + + # Connection ID + MODEM = 1 + ISDN = 2 + CABLE_MODEM = 3 + DSL = 4 + SATELLITE = 5 + ETHERNET = 6 + WIRELESS = 7 + + # Transfer callback type + TRANSFER_SEND_REQUEST = 0x800 + TRANSFER_ACCEPTED = 0x801 + TRANSFER_REJECTED = 0x802 + TRANSFER_NOT_ACCEPTING = 0x803 + TRANSFER_NO_CONNECTION = 0x804 + TRANSFER_DONE = 0x805 + TRANSFER_CANCELLED = 0x806 + TRANSFER_LOST_CONNECTION = 0x807 + TRANSFER_ERROR = 0x808 + TRANSFER_THROTTLE = 0x809 + FILE_BEGIN = 0x80A + FILE_PROGRESS = 0x80B + FILE_END = 0x80C + + +class GPPartnerId(IntEnum): + GAMESPY = 0 + IGN = 10 + + +class PublicMasks(IntEnum): + NONE = 0x00000000 + HOMEPAGE = 0x00000001 + ZIP_CODE = 0x00000002 + COUNTRY_CODE = 0x00000004 + BIRTHDAY = 0x00000008 + SEX = 0x00000010 + EMAIL = 0x00000020 + ALL = 0xFFFFFFFF + + +class RequestType(Enum): + KA = "ka" + LOGIN = "login" + LOGOUT = "logout" + NEWUSER = "newuser" + ADDBLOCK = "addblock" + GETPROFILE = "getprofile" + NEWPROFILE = "newprofile" + REGISTERCDKEY = "registercdkey" + REGISTERNICK = "registernick" + UPDATEPRO = "updatepro" + STATUS = "status" + STATUSINFO = "statusinfo" + INVITETO = "inviteto" + + +class FriendRequestStatus(IntEnum): + PENDING = 0 + ACCEPTED = 1 + REJECTED = 2 + + +if __name__ == "__main__": + + pass \ No newline at end of file diff --git a/src/frontends/gamespy/protocols/presence_connection_manager/aggregates/login_challenge.py b/src/frontends/gamespy/protocols/presence_connection_manager/aggregates/login_challenge.py new file mode 100644 index 000000000..09bf8ab1d --- /dev/null +++ b/src/frontends/gamespy/protocols/presence_connection_manager/aggregates/login_challenge.py @@ -0,0 +1,33 @@ +import hashlib + +from frontends.gamespy.protocols.presence_connection_manager.aggregates.enums import GPPartnerId, LoginType + +SERVER_CHALLENGE = "0000000000" + + +class LoginChallengeProof: + + def __init__( + self, userData: str, loginType: LoginType, partnerID: int, challenge1: str, challenge2: str, passwordHash: str + ): + self.userData = userData + self.loginType = loginType + self.partnerID = partnerID + self.challenge1 = challenge1 + self.challenge2 = challenge2 + self.passwordHash = passwordHash + + def generate_proof(self): + tempUserData = self.userData + + if self.partnerID is not None: + if ( + self.partnerID != GPPartnerId.GAMESPY.value + and self.loginType != LoginType.AUTH_TOKEN + ): + tempUserData = f"{self.partnerID}@{self.userData}" + + responseString = f"{self.passwordHash} { + ' ' * 48}{tempUserData}{self.challenge1}{self.challenge2}{self.passwordHash}" + hashString = hashlib.md5(responseString.encode()).hexdigest() + return hashString diff --git a/src/frontends/gamespy/protocols/presence_connection_manager/aggregates/sdk_revision.py b/src/frontends/gamespy/protocols/presence_connection_manager/aggregates/sdk_revision.py new file mode 100644 index 000000000..018c50ed0 --- /dev/null +++ b/src/frontends/gamespy/protocols/presence_connection_manager/aggregates/sdk_revision.py @@ -0,0 +1,59 @@ +from frontends.gamespy.protocols.presence_connection_manager.aggregates.enums import SdkRevisionType + + +class SdkRevision: + def __init__(self, sdk_type: SdkRevisionType): + assert isinstance(sdk_type, SdkRevisionType) + self.sdk_type = sdk_type + + @property + def is_sdk_revision_valid(self): + return False if self.sdk_type == 0 else True + + @property + def is_support_gpi_new_auth_notification(self): + return ( + True + if (self.sdk_type ^ SdkRevisionType.GPINEW_AUTH_NOTIFICATION) != 0 + else False + ) + + @property + def is_support_gpi_new_revoke_notification(self): + return ( + True + if (self.sdk_type ^ SdkRevisionType.GPINEW_REVOKE_NOTIFICATION) != 0 + else False + ) + + @property + def is_support_gpi_new_status_notification(self): + return ( + True + if (self.sdk_type ^ SdkRevisionType.GPINEW_STATUS_NOTIFICATION) != 0 + else False + ) + + @property + def is_support_gpi_new_list_retreval_on_login(self): + return ( + True + if (self.sdk_type ^ SdkRevisionType.GPINEW_LIST_RETRIEVAL_ON_LOGIN) != 0 + else False + ) + + @property + def is_support_gpi_remote_auth_ids_notification(self): + return ( + True + if (self.sdk_type ^ SdkRevisionType.GPIREMOTE_AUTH_IDS_NOTIFICATION) != 0 + else False + ) + + @property + def is_support_gpi_new_cdkey_registration(self): + return ( + True + if (self.sdk_type ^ SdkRevisionType.GPINEW_CD_KEY_REGISTRATION) != 0 + else False + ) diff --git a/src/frontends/gamespy/protocols/presence_connection_manager/aggregates/user_status.py b/src/frontends/gamespy/protocols/presence_connection_manager/aggregates/user_status.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/gamespy/protocols/presence_connection_manager/applications/client.py b/src/frontends/gamespy/protocols/presence_connection_manager/applications/client.py new file mode 100644 index 000000000..cc6dbd4ba --- /dev/null +++ b/src/frontends/gamespy/protocols/presence_connection_manager/applications/client.py @@ -0,0 +1,59 @@ +from frontends.gamespy.library.abstractions.client import ClientBase, ClientInfoBase + +from frontends.gamespy.library.abstractions.switcher import SwitcherBase +from frontends.gamespy.library.log.log_manager import LogWriter +from frontends.gamespy.library.network.tcp_handler import TcpConnection +from frontends.gamespy.library.configs import ServerConfig +from frontends.gamespy.protocols.presence_connection_manager.aggregates.login_challenge import ( + SERVER_CHALLENGE, +) +from frontends.gamespy.protocols.presence_connection_manager.aggregates.enums import LoginStatus, SdkRevisionType + +LOGIN_TICKET = "0000000000000000000000__" +SESSION_KEY = 1111 + + +class ClientInfo(ClientInfoBase): + user_id: int + profile_id: int + sub_profile_id: int + login_status: LoginStatus + namespace_id: int + sdk_revision: list[SdkRevisionType] + + def __init__(self) -> None: + super().__init__() + self.login_status = LoginStatus.CONNECTED + + +class Client(ClientBase): + info: ClientInfo + client_pool: dict[str, "Client"] = {} + connection: TcpConnection + + def __init__( + self, + connection: TcpConnection, + server_config: ServerConfig, + logger: LogWriter, + ): + super().__init__(connection, server_config, logger) + self.info = ClientInfo() + + def on_connected(self) -> None: + super().on_connected() + if self.info.login_status != LoginStatus.CONNECTED: + self.connection.disconnect() + self.log_warn( + "The server challenge has already been sent. Cannot send another login challenge." + ) + self.info.login_status = LoginStatus.PROCESSING + buffer = f"\\lc\\1\\challenge\\{SERVER_CHALLENGE}\\id\\1\\final\\".encode( + "ascii" + ) + self.log_network_sending(buffer) + self.connection.send(buffer) + + def _create_switcher(self, buffer: bytes) -> SwitcherBase: + from frontends.gamespy.protocols.presence_connection_manager.applications.switcher import Switcher + return Switcher(self, buffer.decode()) diff --git a/src/frontends/gamespy/protocols/presence_connection_manager/applications/handlers.py b/src/frontends/gamespy/protocols/presence_connection_manager/applications/handlers.py new file mode 100644 index 000000000..06689a2cf --- /dev/null +++ b/src/frontends/gamespy/protocols/presence_connection_manager/applications/handlers.py @@ -0,0 +1,310 @@ +from typing import final + +from frontends.gamespy.protocols.presence_connection_manager.aggregates.enums import ( + SdkRevisionType, +) +from frontends.gamespy.protocols.presence_connection_manager.contracts.requests import ( + AddBlockRequest, + AddBuddyRequest, + GetProfileRequest, + NewProfileRequest, + NewUserRequest, + RegisterCDKeyRequest, + RegisterNickRequest, + UpdateProfileRequest, + DelBuddyRequest, + StatusInfoRequest, + StatusRequest, + KeepAliveRequest, + LoginRequest, + LogoutRequest, +) +from frontends.gamespy.protocols.presence_connection_manager.contracts.results import ( + BlockListResult, + BuddyListResult, + NewUserResult, + RegisterNickResult, + StatusInfoResult, + StatusResult, + GetProfileResult, + NewProfileResult, + LoginResult, +) +from frontends.gamespy.protocols.presence_connection_manager.contracts.responses import ( + BlockListResponse, + BuddyListResponse, + NewUserResponse, + StatusInfoResponse, + GetProfileResponse, + NewProfileResponse, + RegisterNickResponse, + KeepAliveResponse, + LoginResponse, +) + +from frontends.gamespy.protocols.presence_connection_manager.applications.client import ( + Client, +) +from frontends.gamespy.protocols.presence_connection_manager.abstractions.handlers import ( + CmdHandlerBase, + LoginedHandlerBase, +) +from frontends.gamespy.protocols.presence_connection_manager.abstractions.contracts import ( + RequestBase, +) +from typing import TYPE_CHECKING + + +if TYPE_CHECKING: + from frontends.gamespy.protocols.presence_connection_manager.applications.client import ( + Client, + ) + +# region General + + +@final +class KeepAliveHandler(CmdHandlerBase): + _request: KeepAliveRequest + + def __init__(self, client: Client, request: KeepAliveRequest) -> None: + assert isinstance(request, KeepAliveRequest) + super().__init__(client, request) + + def _data_operate(self) -> None: + # we set ip and data to request + self._request.client_ip = self._client.connection.remote_ip + self._request.client_port = self._client.connection.remote_port + super()._data_operate() + + def _response_construct(self) -> None: + self._response = KeepAliveResponse() + + +@final +class LoginHandler(CmdHandlerBase): + _request: LoginRequest + _result: LoginResult + _response: LoginResponse + + def __init__(self, client: Client, request: LoginRequest) -> None: + assert isinstance(request, LoginRequest) + super().__init__(client, request) + + def _response_send(self) -> None: + super()._response_send() + handler = SdkRevisionHandler(self._client, self._request) + handler.handle() + + +@final +class LogoutHandler(LoginedHandlerBase): + _request: LogoutRequest + + def __init__(self, client: Client, request: LogoutRequest) -> None: + assert isinstance(request, LogoutRequest) + super().__init__(client, request) + + +@final +# todo create new handler +class NewUserHandler(CmdHandlerBase): + _request: NewUserRequest + _result: NewUserResult + _response: NewUserResponse + # todo create seperate request and result + + def __init__(self, client: Client, request: NewUserRequest) -> None: + assert isinstance(request, NewUserRequest) + super().__init__(client, request) + + +@final +class SdkRevisionHandler(CmdHandlerBase): + _request: LoginRequest + + def __init__(self, client: Client, request: LoginRequest) -> None: + assert isinstance(request, LoginRequest) + super().__init__(client, request) + self._is_fetching = False + self._is_uploading = False + + def _response_construct(self) -> None: + self._client.info.sdk_revision = self._request.sdk_revision_type + if SdkRevisionType.GPINEW_LIST_RETRIEVAL_ON_LOGIN in self._client.info.sdk_revision: + BuddyListHandler(self._client).handle() + BlockListHandler(self._client).handle() + request = StatusInfoRequest() + request.profile_id = self._client.info.profile_id + request.namespace_id = int(self._client.info.namespace_id) + StatusInfoHandler(self._client, request).handle() + # todo: add other revision operations + + +# region Buddy + + +@final +class AddBuddyHandler(CmdHandlerBase): + def __init__(self, client: Client, request: AddBuddyRequest) -> None: + assert isinstance(request, AddBuddyRequest) + super().__init__(client, request) + self._is_fetching = False + + +@final +class BlockListHandler(CmdHandlerBase): + _result: BlockListResult + _response: BlockListResponse + + def __init__(self, client: Client) -> None: + assert isinstance(client, Client) + raise NotImplementedError() + + +@final +class BuddyListHandler(LoginedHandlerBase): + _result: BuddyListResult + _response: BuddyListResponse + + def __init__(self, client): + self._client = client + assert isinstance(client, Client) + raise NotImplementedError() + + +@final +class BuddyStatusInfoHandler(CmdHandlerBase): + """ + This is what the message should look like. Its broken up for easy viewing. + + \\bsi\\state\\profile\\bip\\bport\\hostip\\hprivip\\qport\\hport\\sessflags\\rstatus\\gameType\\gameVnt\\gameMn\\product\\qmodeflags\ + """ + + def __init__(self, client: Client, request: RequestBase) -> None: + raise NotImplementedError() + super().__init__(client, request) + + +@final +class DelBuddyHandler(LoginedHandlerBase): + _request: DelBuddyRequest + + def __init__(self, client: Client, request: DelBuddyRequest) -> None: + assert isinstance(request, DelBuddyRequest) + super().__init__(client, request) + self._is_uploading = False + + +@final +class InviteToHandler(LoginedHandlerBase): + def __init__(self, client: Client, request: RequestBase) -> None: + raise NotImplementedError() + super().__init__(client, request) + + pass + + +@final +class StatusHandler(CmdHandlerBase): + _request: StatusRequest + _result: StatusResult + + def __init__(self, client: Client, request: StatusRequest) -> None: + assert isinstance(request, StatusRequest) + super().__init__(client, request) + self._is_fetching = False + + +@final +class StatusInfoHandler(LoginedHandlerBase): + _request: StatusInfoRequest + _result: StatusInfoResult + _response: StatusInfoResponse + # TODO: check if this implement is correct + + def __init__(self, client: Client, request: StatusInfoRequest) -> None: + assert isinstance(request, StatusInfoRequest) + super().__init__(client, request) + + def _response_send(self) -> None: + # todo: check if response is needed + super()._response_send() + + +# region Profile + + +@final +class AddBlockHandler(CmdHandlerBase): + _request: AddBlockRequest + + def __init__(self, client: Client, request: AddBlockRequest) -> None: + assert isinstance(request, AddBlockRequest) + super().__init__(client, request) + + +@final +class GetProfileHandler(CmdHandlerBase): + _request: GetProfileRequest + _result: GetProfileResult + _response: GetProfileResponse + + def __init__(self, client: Client, request: GetProfileRequest) -> None: + assert isinstance(request, GetProfileRequest) + super().__init__(client, request) + + +@final +class NewProfileHandler(CmdHandlerBase): + _request: NewProfileRequest + _result: NewProfileResult + _response: NewProfileResponse + + def __init__(self, client: Client, request: NewProfileRequest) -> None: + assert isinstance(request, NewProfileRequest) + super().__init__(client, request) + + +@final +class RegisterCDKeyHandler(CmdHandlerBase): + _request: RegisterCDKeyRequest + + def __init__(self, client: Client, request: RegisterCDKeyRequest) -> None: + assert isinstance(request, RegisterCDKeyRequest) + super().__init__(client, request) + + +@final +class RegisterNickHandler(CmdHandlerBase): + _request: RegisterNickRequest + _result: RegisterNickResult + _response: RegisterNickResponse + + def __init__(self, client: Client, request: RegisterNickRequest) -> None: + assert isinstance(request, RegisterNickRequest) + super().__init__(client, request) + + +@final +class RemoveBlockHandler(CmdHandlerBase): + def __init__(self, client: Client, request: RequestBase) -> None: + super().__init__(client, request) + raise NotImplementedError() + + +@final +class UpdateProfileHandler(CmdHandlerBase): + _request: UpdateProfileRequest + + def __init__(self, client: Client, request: UpdateProfileRequest) -> None: + assert isinstance(request, UpdateProfileRequest) + super().__init__(client, request) + raise NotImplementedError() + + +@final +class UpdateUserInfoHandler(CmdHandlerBase): + def __init__(self, client: Client, request: RequestBase) -> None: + super().__init__(client, request) + raise NotImplementedError() diff --git a/src/frontends/gamespy/protocols/presence_connection_manager/applications/server_launcher.py b/src/frontends/gamespy/protocols/presence_connection_manager/applications/server_launcher.py new file mode 100644 index 000000000..4dc4cd3ea --- /dev/null +++ b/src/frontends/gamespy/protocols/presence_connection_manager/applications/server_launcher.py @@ -0,0 +1,21 @@ +from frontends.gamespy.library.abstractions.server_launcher import ServicesFactory, ServiceBase +from frontends.gamespy.library.network.tcp_handler import TcpServer +from frontends.gamespy.protocols.presence_connection_manager.applications.client import ( + Client, +) + + +class Service(ServiceBase): + def __init__(self) -> None: + super().__init__( + config_name="PresenceConnectionManager", + client_cls=Client, + network_server_cls=TcpServer, + ) + + +if __name__ == "__main__": + from frontends.gamespy.library.extentions.debug_helper import DebugHelper + pcm = Service() + helper = DebugHelper("./frontends/", ServicesFactory([pcm])) + helper.start() diff --git a/src/frontends/gamespy/protocols/presence_connection_manager/applications/switcher.py b/src/frontends/gamespy/protocols/presence_connection_manager/applications/switcher.py new file mode 100644 index 000000000..447e4cb6e --- /dev/null +++ b/src/frontends/gamespy/protocols/presence_connection_manager/applications/switcher.py @@ -0,0 +1,68 @@ +from frontends.gamespy.library.abstractions.switcher import SwitcherBase +from frontends.gamespy.protocols.presence_connection_manager.aggregates.enums import RequestType +from frontends.gamespy.protocols.presence_connection_manager.contracts.requests import KeepAliveRequest, LoginRequest, LogoutRequest, StatusInfoRequest, StatusRequest, AddBlockRequest, GetProfileRequest, NewProfileRequest, RegisterCDKeyRequest, NewUserRequest, RegisterNickRequest, UpdateProfileRequest +from frontends.gamespy.protocols.presence_connection_manager.applications.handlers import AddBlockHandler, GetProfileHandler, KeepAliveHandler, LoginHandler, LogoutHandler, NewProfileHandler, NewUserHandler, RegisterCDKeyHandler, RegisterNickHandler, StatusHandler, StatusInfoHandler, UpdateProfileHandler +from frontends.gamespy.protocols.presence_search_player.aggregates.exceptions import GPParseException + +from frontends.gamespy.protocols.presence_connection_manager.abstractions.handlers import CmdHandlerBase +from typing import TYPE_CHECKING, Optional, cast + +from frontends.gamespy.protocols.presence_connection_manager.applications.client import Client + + +class Switcher(SwitcherBase): + _raw_request: str + + def __init__(self, client: Client, raw_request: str) -> None: + assert isinstance(client, Client) + assert isinstance(raw_request, str) + super().__init__(client, raw_request) + + def _process_raw_request(self) -> None: + if self._raw_request[0] != "\\": + raise GPParseException("Request format is invalid") + raw_requests = [ + r+"\\final\\" for r in self._raw_request.split("\\final\\") if r] + for raw_request in raw_requests: + name = raw_request.strip("\\").split("\\")[0] + if name not in RequestType: + self._client.log_debug( + f"Request: {name} is not a valid request.") + continue + self._requests.append((RequestType(name), raw_request)) + + def _create_cmd_handlers(self, name: RequestType, raw_request: str) -> CmdHandlerBase | None: + assert isinstance(name, RequestType) + assert isinstance(raw_request, str) + if TYPE_CHECKING: + self._client = cast(Client, self._client) + match name: + case RequestType.KA: + return KeepAliveHandler(self._client, KeepAliveRequest(raw_request)) + case RequestType.LOGIN: + return LoginHandler(self._client, LoginRequest(raw_request)) + case RequestType.LOGOUT: + return LogoutHandler(self._client, LogoutRequest(raw_request)) + case RequestType.NEWUSER: + return NewUserHandler(self._client, NewUserRequest(raw_request)) + case RequestType.ADDBLOCK: + return AddBlockHandler(self._client, AddBlockRequest(raw_request)) + case RequestType.GETPROFILE: + return GetProfileHandler(self._client, GetProfileRequest(raw_request)) + case RequestType.NEWPROFILE: + return NewProfileHandler(self._client, NewProfileRequest(raw_request)) + case RequestType.REGISTERCDKEY: + return RegisterCDKeyHandler(self._client, RegisterCDKeyRequest(raw_request)) + case RequestType.REGISTERNICK: + return RegisterNickHandler(self._client, RegisterNickRequest(raw_request)) + case RequestType.UPDATEPRO: + return UpdateProfileHandler(self._client, UpdateProfileRequest(raw_request)) + case RequestType.STATUS: + return StatusHandler(self._client, StatusRequest(raw_request)) + case RequestType.STATUSINFO: + return StatusInfoHandler(self._client, StatusInfoRequest(raw_request)) + case RequestType.INVITETO: + raise NotImplementedError( + "InviteToHandler is not implemented.") + case _: + return None diff --git a/src/frontends/gamespy/protocols/presence_connection_manager/contracts/requests.py b/src/frontends/gamespy/protocols/presence_connection_manager/contracts/requests.py new file mode 100644 index 000000000..ccb794e67 --- /dev/null +++ b/src/frontends/gamespy/protocols/presence_connection_manager/contracts/requests.py @@ -0,0 +1,625 @@ +from typing import final +from frontends.gamespy.library.extentions.gamespy_utils import convert_to_key_value +from frontends.gamespy.protocols.presence_connection_manager.abstractions.contracts import ( + RequestBase, +) +from frontends.gamespy.protocols.presence_connection_manager.aggregates.enums import ( + GPStatusCode, +) +from frontends.gamespy.protocols.presence_search_player.aggregates.exceptions import ( + GPException, + GPParseException, +) +from frontends.gamespy.library.extentions.gamespy_utils import is_email_format_correct +from frontends.gamespy.library.extentions.password_encoder import process_password +from frontends.gamespy.protocols.presence_connection_manager.aggregates.enums import ( + LoginType, + QuietModeType, + SdkRevisionType, +) + +# region General +EXTRA_INFO_DICT: dict[str, type] = { + "location": str, + "firstname": str, + "lastname": str, + "publicmask": int, + "latitude": float, + "longitude": float, + "aim": str, + "picture": int, + "occupationid": int, + "incomeid": int, + "industryid": int, + "marriedid": int, + "childcount": int, + "interests1": int, + "ownership1": int, + "connectiontype": int, + "sex": int, + "zipcode": str, + "countrycode": str, + "homepage": str, + "birthday": int, + "birthmonth": int, + "birthyear": int, + "icquin": int, + "quietflags": int, + "streetaddr": str, + "streeaddr": str, + "city": str, + "cpubrandid": int, + "cpuspeed": int, + "memory": int, + "videocard1string": str, + "videocard1ram": int, + "videocard2string": str, + "videocard2ram": int, + "subscription": int, + "adminrights": int, +} + + +def validate_extra_infos(info_dict: dict) -> dict: + """ + validate and create a dict of extra info + """ + assert isinstance(info_dict, dict) + extra_infos = {} + for key, value in info_dict.items(): + if key in EXTRA_INFO_DICT and key not in extra_infos: + if not isinstance(value, EXTRA_INFO_DICT[key]): + converted_value = value + else: + try: + value_type = EXTRA_INFO_DICT[key] + converted_value = value_type(value) + except Exception as e: + raise GPException(f"value conversion failed: {e}") + extra_infos[key] = converted_value + return extra_infos + + +@final +class KeepAliveRequest(RequestBase): + client_ip: str + client_port: int + pass + + +@final +class LoginRequest(RequestBase): + sdk_mapping: list[SdkRevisionType] + user_challenge: str + response: str + unique_nick: str + user_data: str + namespace_id: int + auth_token: str + nick: str + email: str + product_id: int + type: LoginType + sdk_revision_type: list[SdkRevisionType] + game_port: int + user_id: int + profile_id: int + partner_id: int + """ + partner id default is 0 + """ + game_name: str + quiet_mode_flags: int + firewall: bool + + def __init__(self, raw_request: str) -> None: + super().__init__(raw_request) + self.sdk_revision_type = [] + self.sdk_mapping = [ + SdkRevisionType.GPINEW_AUTH_NOTIFICATION, + SdkRevisionType.GPINEW_REVOKE_NOTIFICATION, + SdkRevisionType.GPINEW_STATUS_NOTIFICATION, + SdkRevisionType.GPINEW_LIST_RETRIEVAL_ON_LOGIN, + SdkRevisionType.GPIREMOTE_AUTH_IDS_NOTIFICATION, + SdkRevisionType.GPINEW_CD_KEY_REGISTRATION, + ] + + def parse(self): + super().parse() + + if "challenge" not in self._request_dict: + raise GPParseException("challenge is missing") + + if "response" not in self._request_dict: + raise GPParseException("response is missing") + + self.user_challenge = self._request_dict["challenge"] + self.response = self._request_dict["response"] + + if "uniquenick" in self._request_dict and "namespaceid" in self._request_dict: + namespace_id = int(self._request_dict["namespaceid"]) + self.type = LoginType.UNIQUENICK_NAMESPACE_ID + self.unique_nick = self._request_dict["uniquenick"] + self.user_data = self.unique_nick + self.namespace_id = namespace_id + elif "authtoken" in self._request_dict: + self.type = LoginType.AUTH_TOKEN + self.auth_token = self._request_dict["authtoken"] + self.user_data = self.auth_token + elif "user" in self._request_dict: + self.type = LoginType.NICK_EMAIL + self.user_data = self._request_dict["user"] + pos = self.user_data.index("@") + if pos == -1 or pos < 1 or (pos + 1) >= len(self.user_data): + raise GPParseException("user format is incorrect") + self.nick = self.user_data[:pos] + self.email = self.user_data[pos + 1:] + if "namespaceid" in self._request_dict: + namespace_id = int(self._request_dict["namespaceid"]) + self.namespace_id = namespace_id + else: + raise GPParseException("Unknown login method detected.") + + self.parse_other_data() + + def parse_other_data(self): + if "userid" in self._request_dict: + user_id = int(self._request_dict["userid"]) + self.user_id = user_id + + if "profileid" in self._request_dict: + profile_id = int(self._request_dict["profileid"]) + self.profile_id = profile_id + + if "partnerid" in self._request_dict: + partner_id = int(self._request_dict["partnerid"]) + self.partner_id = partner_id + else: + self.partner_id = 0 + + if "sdkrevision" in self._request_dict: + sdk_revision_type = int(self._request_dict["sdkrevision"]) + for item in self.sdk_mapping: + if item & sdk_revision_type: + self.sdk_revision_type.append(item) + + if "gamename" in self._request_dict: + self.game_name = self._request_dict["gamename"] + + if "port" in self._request_dict: + game_port = int(self._request_dict["port"]) + self.game_port = game_port + + if "productid" in self._request_dict: + product_id = int(self._request_dict["productid"]) + self.product_id = product_id + + if "firewall" in self._request_dict: + self.firewall = bool(self._request_dict["firewall"]) + + if "quiet" in self._request_dict: + quiet = int(self._request_dict["quiet"]) + self.quiet_mode_flags = QuietModeType(quiet) + + +@final +class LogoutRequest(RequestBase): + pass + + +@final +class NewUserRequest(RequestBase): + product_id: int + game_port: int + cd_key: str + has_game_name: bool + has_product_id: bool + has_cdkey: bool + has_partner_id: bool + has_game_port: bool + nick: str + email: str + password: str + partner_id: int + game_name: str + uniquenick: str + + def parse(self): + super().parse() + self.password = process_password(self._request_dict) + + if "nick" not in self._request_dict: + raise GPParseException("nickname is missing.") + if "email" not in self._request_dict: + raise GPParseException("email is missing.") + if not is_email_format_correct(self._request_dict["email"]): + raise GPParseException("email format is incorrect.") + self.nick = self._request_dict["nick"] + self.email = self._request_dict["email"] + + if "uniquenick" in self._request_dict and "namespaceid" in self._request_dict: + if "namespaceid" in self._request_dict: + try: + self.namespace_id = int(self._request_dict["namespaceid"]) + except ValueError: + raise GPParseException("namespaceid is incorrect.") + + self.uniquenick = self._request_dict["uniquenick"] + self.parse_other_info() + + def parse_other_info(self): + if "partnerid" in self._request_dict: + try: + self.partner_id = int(self._request_dict["partnerid"]) + self.has_partner_id_flag = True + except ValueError: + raise GPParseException("partnerid is incorrect.") + else: + self.partner_id = 0 # set default partner id to 0 means gamespy + + if "productid" in self._request_dict: + try: + self.product_id = int(self._request_dict["productid"]) + self.has_product_id_flag = True + except ValueError: + raise GPParseException("productid is incorrect.") + + if "gamename" in self._request_dict: + self.has_game_name_flag = True + self.game_name = self._request_dict["gamename"] + + if "port" in self._request_dict: + try: + self.game_port = int(self._request_dict["port"]) + self.has_game_port_flag = True + except ValueError: + raise GPParseException("port is incorrect.") + + if "cdkey" in self._request_dict: + self.has_cd_key_enc_flag = True + self.cd_key = self._request_dict["cdkey"] + + +# region Buddy + + +class BuddyListRequest(RequestBase): + profile_id: int + namespace_id: int + + def __init__(self, profile_id: int, namespace_id: int) -> None: + assert isinstance(profile_id, int) + assert isinstance(namespace_id, int) + self.profile_id = profile_id + self.namespace_id = namespace_id + + def parse(self): + pass + + +class BlockListRequest(RequestBase): + profile_id: int + namespace_id: int + + def __init__(self, profile_id: int, namespace_id: int) -> None: + assert isinstance(profile_id, int) + assert isinstance(namespace_id, int) + self.profile_id = profile_id + self.namespace_id = namespace_id + + def parse(self): + pass + + +@final +class AddBuddyRequest(RequestBase): + friend_profile_id: int + reason: str + + def parse(self): + super().parse() + if ( + ("sesskey" not in self._request_dict) + or ("newprofileid" not in self._request_dict) + or ("reason" not in self._request_dict) + ): + raise GPParseException("addbuddy request is invalid.") + try: + self.friend_profile_id = int(self._request_dict["newprofileid"]) + except Exception: + raise GPParseException("newprofileid format is incorrect.") + + self.reason = self._request_dict["reason"] + + +@final +class DelBuddyRequest(RequestBase): + friend_profile_id: int + + def parse(self): + super().parse() + if "delprofileid" not in self._request_dict: + raise GPParseException("delprofileid is missing.") + + try: + self.friend_profile_id = int(self._request_dict["delprofileid"]) + except Exception: + raise GPParseException("delprofileid format is incorrect.") + + +@final +class InviteToRequest(RequestBase): + product_id: int + profile_id: int + session_key: str + """the invite target profile id""" + + def parse(self): + super().parse() + if "productid" not in self._request_dict: + raise GPParseException("productid is missing.") + + if "sesskey" not in self._request_dict: + raise GPParseException("sesskey is missing.") + + try: + self.product_id = int(self._request_dict["productid"]) + except ValueError: + raise GPParseException("productid format is incorrect.") + + try: + self.profile_id = int(self._request_dict["profileid"]) + except ValueError: + raise GPParseException("profileid format is incorrect.") + + self.session_key = self._request_dict["sesskey"] + + +@final +class StatusInfoRequest(RequestBase): + namespace_id: int + profile_id: int + status_state: str + buddy_ip: str + host_ip: str + host_private_ip: str + query_report_port: int + host_port: int + session_flags: str + rich_status: str + game_type: str + game_variant: str + game_map_name: str + quiet_mode_flags: str + + def __init__(self, raw_request: str | None = None) -> None: + if raw_request is not None: + self.raw_request = raw_request + + def parse(self): + super().parse() + + if ( + "state" not in self._request_dict + or "hostip" not in self._request_dict + or "hprivip" not in self._request_dict + or "qport" not in self._request_dict + or "hport" not in self._request_dict + or "sessflags" not in self._request_dict + or "rechstatus" not in self._request_dict + or "gametype" not in self._request_dict + or "gamevariant" not in self._request_dict + or "gamemapname" not in self._request_dict + ): + raise GPParseException("StatusInfo request is invalid.") + + self.status_state = self._request_dict["state"] + self.host_ip = self._request_dict["hostip"] + self.host_private_ip = self._request_dict["hprivip"] + + try: + self.query_report_port = int(self._request_dict["qport"]) + self.host_port = int(self._request_dict["hport"]) + self.session_flags = self._request_dict["sessflags"] + except ValueError: + raise GPParseException( + "qport, hport, or sessflags format is incorrect.") + + if "namespace_id" in self._request_dict: + self.namespace_id = int(self._request_dict["namespaceid"]) + else: + self.namespace_id = 0 + + self.rich_status = self._request_dict["rechstatus"] + self.game_type = self._request_dict["gametype"] + self.game_variant = self._request_dict["gamevariant"] + self.game_map_name = self._request_dict["gamemapname"] + + +@final +class StatusRequest(RequestBase): + current_status: GPStatusCode + location_string: str + status_string: str + session_key: str + + def parse(self): + self._request_dict = convert_to_key_value(self.raw_request) + self.command_name = list(self._request_dict.keys())[0] + + if "status" not in self._request_dict: + raise GPParseException("status is missing.") + + if "statstring" not in self._request_dict: + raise GPParseException("statstring is missing.") + + if "locstring" not in self._request_dict: + raise GPParseException("locstring is missing.") + if "sesskey" not in self._request_dict: + raise GPParseException("session key is missing.") + self.session_key = self._request_dict["sesskey"] + self.location_string = self._request_dict["locstring"] + self.status_string = self._request_dict["statstring"] + try: + status_code = int(self._request_dict["status"]) + self.current_status = GPStatusCode(status_code) + except ValueError: + raise GPParseException("status format is incorrect.") + + +# region Profile + + +@final +class AddBlockRequest(RequestBase): + taget_id: int + + def parse(self): + super().parse() + + if "profileid" not in self._request_dict: + raise GPParseException("profileid is missing") + + try: + self.taget_id = int(self._request_dict["profileid"]) + except ValueError: + raise GPParseException("profileid format is incorrect") + + +@final +class GetProfileRequest(RequestBase): + profile_id: int + session_key: str + + def parse(self): + super().parse() + + if "profileid" not in self._request_dict: + raise GPParseException("profileid is missing") + + try: + self.profile_id = int(self._request_dict["profileid"]) + except ValueError: + raise GPParseException("profileid format is incorrect") + + if "sesskey" not in self._request_dict: + raise GPParseException("sesskey is missing") + + self.session_key = self._request_dict["sesskey"] + + +@final +class NewProfileRequest(RequestBase): + is_replace_nick_name: bool + session_key: str + new_nick: str + old_nick: str + + def parse(self): + super().parse() + + if "sesskey" not in self._request_dict: + raise GPParseException("sesskey is missing") + + self.session_key = self._request_dict["sesskey"] + + if "replace" in self._request_dict: + if "oldnick" not in self._request_dict and "nick" not in self._request_dict: + raise GPParseException("oldnick or nick is missing.") + + if "oldnick" in self._request_dict: + self.old_nick = self._request_dict["oldnick"] + if "nick" in self._request_dict: + self.new_nick = self._request_dict["nick"] + + self.is_replace_nick_name = True + else: + if "nick" not in self._request_dict: + raise GPParseException("nick is missing.") + + self.new_nick = self._request_dict["nick"] + self.is_replace_nick_name = False + + +@final +class RegisterCDKeyRequest(RequestBase): + session_key: str + cdkey_enc: str + + def parse(self): + super().parse() + + if "sesskey" not in self._request_dict: + raise GPParseException("sesskey is missing") + + self.session_key = self._request_dict["sesskey"] + + if "cdkeyenc" not in self._request_dict: + raise GPParseException("cdkeyenc is missing") + + self.cdkey_enc = self._request_dict["cdkeyenc"] + + +@final +class RegisterNickRequest(RequestBase): + unique_nick: str + session_key: str + partner_id: int + + def parse(self): + super().parse() + + if "sesskey" not in self._request_dict: + raise GPParseException("sesskey is missing") + + self.session_key = self._request_dict["sesskey"] + + if "uniquenick" not in self._request_dict: + raise GPParseException("uniquenick is missing") + + self.unique_nick = self._request_dict["uniquenick"] + + if "partnerid" in self._request_dict: + try: + self.partner_id = int(self._request_dict["partnerid"]) + except ValueError: + raise GPParseException("partnerid is missing") + + +@final +class UpdateProfileRequest(RequestBase): + session_key: str + partner_id: int + nick: str + uniquenick: str + extra_infos: dict + + def parse(self): + super().parse() + + if "sesskey" not in self._request_dict: + raise GPParseException("sesskey is missing") + self.session_key = self._request_dict["sesskey"] + + if "partnerid" in self._request_dict: + try: + self.partner_id = int(self._request_dict["partnerid"]) + except ValueError: + raise GPParseException("partnerid is incorrect") + + if "nick" in self._request_dict: + self.nick = self._request_dict["nick"] + + if "uniquenick" in self._request_dict: + self.uniquenick = self._request_dict["uniquenick"] + + self.extra_info = validate_extra_infos(self._request_dict) + + +@final +class UpdateUserInfoRequest(RequestBase): + extra_infos: dict[str, str] + + def parse(self): + super().parse() + self.extra_infos = validate_extra_infos(self._request_dict) diff --git a/src/frontends/gamespy/protocols/presence_connection_manager/contracts/responses.py b/src/frontends/gamespy/protocols/presence_connection_manager/contracts/responses.py new file mode 100644 index 000000000..ad8530b6c --- /dev/null +++ b/src/frontends/gamespy/protocols/presence_connection_manager/contracts/responses.py @@ -0,0 +1,226 @@ +from frontends.gamespy.protocols.presence_connection_manager.abstractions.contracts import ( + RequestBase, + ResponseBase, +) +from frontends.gamespy.protocols.presence_connection_manager.aggregates.login_challenge import ( + SERVER_CHALLENGE, + LoginChallengeProof, +) +from frontends.gamespy.protocols.presence_connection_manager.applications.client import ( + LOGIN_TICKET, + SESSION_KEY, +) +from frontends.gamespy.protocols.presence_connection_manager.contracts.requests import ( + KeepAliveRequest, + LoginRequest, + NewUserRequest, + AddBuddyRequest, + StatusInfoRequest, + GetProfileRequest, + NewProfileRequest, + RegisterNickRequest, +) + +from frontends.gamespy.library.extentions.gamespy_ramdoms import ( + StringType, + generate_random_string, +) + +from frontends.gamespy.protocols.presence_connection_manager.contracts.results import ( + GetProfileResult, + NewProfileResult, + AddBuddyResult, + BlockListResult, + BuddyListResult, + RegisterNickResult, + StatusInfoResult, + LoginResult, + NewUserResult, +) + + +# region General + + +class KeepAliveResponse(ResponseBase): + def __init__(self) -> None: + pass + + def build(self) -> None: + self.sending_buffer = "\\ka\\final\\" + + +class LoginResponse(ResponseBase): + _result: LoginResult + _request: LoginRequest + + def __init__(self, result: LoginResult): + super().__init__(result) + + assert isinstance(result, LoginResult) + + def build(self): + response_proof = LoginChallengeProof( + self._result.user_data, + self._result.type, + self._result.partner_id, + self._result.user_challenge, + SERVER_CHALLENGE, + self._result.data.password_hash, + ).generate_proof() + self.sending_buffer = f"\\lc\\2\\sesskey\\{SESSION_KEY}\\proof\\{ + response_proof + }\\userid\\{self._result.data.user_id}\\profileid\\{ + self._result.data.profile_id + }" + + if self._result.data.unique_nick is not None: + self.sending_buffer += "\\uniquenick\\" + self._result.data.unique_nick + + self.sending_buffer += f"\\lt\\{LOGIN_TICKET}" + self.sending_buffer += f"\\id\\{self._result.operation_id}\\final\\" + + +class NewUserResponse(ResponseBase): + _request: NewUserRequest + _result: NewUserResult + + def __init__(self, result: NewUserResult) -> None: + super().__init__(result) + + assert isinstance(result, NewUserResult) + + def build(self): + # fmt: on + self.sending_buffer = f"\\nur\\userid\\{self._result.user_id}\\profileid\\{self._result.profile_id}\\id\\{self._result.operation_id}\\final\\" # fmt: off + + +# region Buddy + + +class AddBuddyResponse(ResponseBase): + def __init__(self, result: AddBuddyResult) -> None: + assert issubclass(type(result), AddBuddyResult) + super().__init__( result) + + def build(self) -> None: + # return super().build() + raise NotImplementedError() + # \bm\\f\\date\ + # GPI_BM_MESSAGE: \msg\\ + # GPI_BM_UTM:\msg\\ + # GPI_BM_REQUEST:\msg\|signed|\ + # GPI_BM_AUTH: + # GPI_BM_REVOKE: + # GPI_BM_STATUS:\msg\|s|\ or \msg\|ss||ls||ip||p||qm| + # GPI_BM_INVITE:\msg\|p||l| + # GPI_BM_PING:\msg\\ + + +class BlockListResponse(ResponseBase): + _result: BlockListResult + + def __init__(self, result: BlockListResult): + assert isinstance(result, BlockListResult) + self._result = result + + def build(self): + # \blk\< num in list >\list\< profileid list - comma delimited >\final\ + self.sending_buffer = f"\\blk\\{len(self._result.profile_ids)}\\list\\" + self.sending_buffer += ",".join(str(pid) for pid in self._result.profile_ids) + self.sending_buffer += "\\final\\" + + +class BuddyListResponse(ResponseBase): + _result: BuddyListResult + + def __init__(self, result: BuddyListResult): + super().__init__(result) + + def build(self): + # \bdy\< num in list >\list\< profileid list - comma delimited >\final\ + self.sending_buffer = f"\\bdy\\{len(self._result.profile_ids)}\\list\\" + self.sending_buffer += ",".join(str(pid) for pid in self._result.profile_ids) + self.sending_buffer += "\\final\\" + + +class StatusInfoResponse(ResponseBase): + _result: StatusInfoResult + + def __init__(self, result: StatusInfoResult): + + assert isinstance(result, StatusInfoResult) + super().__init__(result) + + def build(self): + # \bsi\\state\\profile\\bip\\bport\\hostip\\hprivip\\qport\\hport\\sessflags\\rstatus\\gameType\\gameVnt\\gameMn\\product\\qmodeflags\ + self.sending_buffer = ( + f"\\bsi\\state\\{self._result.status_state}\\" + f"profile\\{self._result.profile_id}\\bip\\{self._result.buddy_ip}\\" + f"hostIp\\{self._result.host_ip}\\hprivIp\\{self._result.host_private_ip}\\" + f"qport\\{self._result.query_report_port}\\hport\\{self._result.host_port}\\" + f"sessflags\\{self._result.session_flags}\\rstatus\\{self._result.rich_status}\\" + f"gameType\\{self._result.game_type}\\gameVnt\\{self._result.game_variant}\\" + f"gameMn\\{self._result.game_map_name}\\product\\{self._result.product_id}\\" + f"qmodeflags\\{self._result.quiet_mode_flags}\\final\\" + ) + + +# region Profile + + +class GetProfileResponse(ResponseBase): + _result: GetProfileResult + _request: GetProfileRequest + + def __init__(self, result: GetProfileResult): + + assert isinstance(result, GetProfileResult) + super().__init__(result) + + def build(self): + self.sending_buffer = ( + f"\\pi\\profileid\\{self._result.user_profile.profile_id}" + + f"\\nick\\{self._result.user_profile.nick}" + + f"\\uniquenick\\{self._result.user_profile.unique_nick}" + + f"\\email\\{self._result.user_profile.email}" + ) + for key, value in self._result.user_profile.extra_infos.items(): + self.sending_buffer += f"\\{key}\\{value}" + + self.sending_buffer += ( + f"\\sig\\+{generate_random_string(10, StringType.HEX)}" + + f"\\id\\{self._result.operation_id}\\final\\" + ) + + +class NewProfileResponse(ResponseBase): + _request: NewProfileRequest + _result: NewProfileResult + + def __init__(self, result: NewProfileResult): + + assert isinstance(result, NewProfileResult) + super().__init__(result) + + def build(self): + # fmt: off + self.sending_buffer = f"\\npr\\\\profileid\\{self.sending_buffer}\\id\\{self._result.operation_id}\\final\\" + # fmt: on + + +class RegisterCDKeyResposne(ResponseBase): + def __init__(self) -> None: + pass + + def build(self): + self.sending_buffer = "\\rc\\\\final\\" + + +class RegisterNickResponse(ResponseBase): + _result: RegisterNickResult + + def build(self) -> None: + # fmt: off + self.sending_buffer = f"\\rn\\\\id\\{self._result.operation_id}\\final\\" + # fmt: on diff --git a/src/frontends/gamespy/protocols/presence_connection_manager/contracts/results.py b/src/frontends/gamespy/protocols/presence_connection_manager/contracts/results.py new file mode 100644 index 000000000..623340731 --- /dev/null +++ b/src/frontends/gamespy/protocols/presence_connection_manager/contracts/results.py @@ -0,0 +1,94 @@ +from pydantic import BaseModel +from frontends.gamespy.protocols.presence_connection_manager.abstractions.contracts import ResultBase +from frontends.gamespy.protocols.presence_connection_manager.aggregates.enums import GPStatusCode, LoginType + +# region General + + +class LoginData(BaseModel): + user_id: int + profile_id: int + sub_profile_id: int + nick: str + email: str + unique_nick: str + password_hash: str + email_verified_flag: bool + banned_flag: bool + namespace_id: int + + +class LoginResult(ResultBase): + data: LoginData + user_data: str + type: LoginType + partner_id: int + user_challenge: str + + +class NewUserResult(ResultBase): + user_id: int + profile_id: int + + +# region Buddy + + +class AddBuddyResult(ResultBase): + pass + + +class BlockListResult(ResultBase): + profile_ids: list[int] + operation_id: int + + +class BuddyListResult(ResultBase): + profile_ids: list[int] + + +class StatusInfoResult(ResultBase): + profile_id: int + product_id: int + status_state: str + buddy_ip: str + host_ip: str + host_private_ip: str + query_report_port: int + host_port: int + session_flags: str + rich_status: str + game_type: str + game_variant: str + game_map_name: str + quiet_mode_flags: str + + +class StatusResult(ResultBase): + status_string: str + location_string: str + current_status: GPStatusCode + +# class NewUserResult() + + +# region Profile + +class GetProfileData(BaseModel): + nick: str + profile_id: int + unique_nick: str + email: str + extra_infos: dict + + +class GetProfileResult(ResultBase): + user_profile: GetProfileData + + +class NewProfileResult(ResultBase): + profile_id: int + + +class RegisterNickResult(ResultBase): + pass diff --git a/src/frontends/gamespy/protocols/presence_search_player/__init__.py b/src/frontends/gamespy/protocols/presence_search_player/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/gamespy/protocols/presence_search_player/abstractions/contracts.py b/src/frontends/gamespy/protocols/presence_search_player/abstractions/contracts.py new file mode 100644 index 000000000..13932b6b9 --- /dev/null +++ b/src/frontends/gamespy/protocols/presence_search_player/abstractions/contracts.py @@ -0,0 +1,44 @@ +from typing import Dict +import frontends.gamespy.library.abstractions.contracts as lib +from frontends.gamespy.library.extentions.gamespy_utils import convert_to_key_value +from frontends.gamespy.protocols.presence_search_player.aggregates.exceptions import ( + GPParseException, +) + + +class RequestBase(lib.RequestBase): + _request_dict: dict[str, str] + raw_request: str + command_name: str + operation_id: int + namespace_id: int + + def __init__(self, raw_request: str) -> None: + assert isinstance(raw_request, str) + super().__init__(raw_request) + self.operation_id = 0 + self.namespace_id = 0 + + def parse(self) -> None: + self._request_dict = convert_to_key_value(self.raw_request) + self.command_name = list(self._request_dict.keys())[0] + if "id" in self._request_dict.keys(): + try: + self.operation_id = int(self._request_dict["id"]) + except ValueError: + raise GPParseException("operation id is invalid.") + + if "namespaceid" in self._request_dict: + try: + self.namespace_id = int(self._request_dict["namespaceid"]) + except ValueError: + raise GPParseException("namespaceid is incorrect.") + + +class ResultBase(lib.ResultBase): + pass + + +class ResponseBase(lib.ResponseBase): + _result: ResultBase + _request: RequestBase diff --git a/src/frontends/gamespy/protocols/presence_search_player/abstractions/handler.py b/src/frontends/gamespy/protocols/presence_search_player/abstractions/handler.py new file mode 100644 index 000000000..84b5c5688 --- /dev/null +++ b/src/frontends/gamespy/protocols/presence_search_player/abstractions/handler.py @@ -0,0 +1,16 @@ +from frontends.gamespy.library.abstractions.handler import CmdHandlerBase as CHB +from frontends.gamespy.protocols.presence_search_player.abstractions.contracts import RequestBase +from frontends.gamespy.protocols.presence_search_player.applications.client import Client +from frontends.gamespy.protocols.presence_search_player.aggregates.exceptions import GPException + + +class CmdHandlerBase(CHB): + def __init__(self, client: Client, request: RequestBase) -> None: + assert issubclass(type(request), RequestBase) + assert isinstance(client, Client) + super().__init__(client, request) + + def _handle_exception(self, ex) -> None: + if ex is GPException: + self._client.send(ex) + super()._handle_exception(ex) diff --git a/src/frontends/gamespy/protocols/presence_search_player/aggregates/enums.py b/src/frontends/gamespy/protocols/presence_search_player/aggregates/enums.py new file mode 100644 index 000000000..573c51d28 --- /dev/null +++ b/src/frontends/gamespy/protocols/presence_search_player/aggregates/enums.py @@ -0,0 +1,139 @@ +from enum import Enum, IntEnum + + +class SearchType(IntEnum): + NICK_SEARCH = 0 + NICK_EMAIL_SEARCH = 1 + UNIQUENICK_NAMESPACEID_SEARCH = 2 + EMAIL_SEARCH = 3 + +# region Error code + + +class GPErrorCode(IntEnum): + # General. + GENERAL = 0x0000 + PARSE = 0x0001 + NOT_LOGGED_IN = 0x0002 + BAD_SESSION_KEY = 0x0003 + DATABASE_ERROR = 0x0004 + NETWORK = 0x0005 + FORCED_DISCONNECT = 0x0006 + CONNECTION_CLOSE = 0x0007 + UDP_LAYER = 0x0008 + + # Login. + LOGIN = 0x0100 + LOGIN_TIME_OUT = 0x0101 + LOGIN_BAD_NICK = 0x0102 + LOGIN_BAD_EMAIL = 0x0103 + LOGIN_BAD_PASSWORD = 0x0104 + LOGIN_BAD_PROFILE = 0x0105 + LOGIN_PROFILE_DELETED = 0x0106 + LOGIN_CONNECTION_FAILED = 0x0107 + LOGIN_SERVER_AUTH_FAILED = 0x0108 + LOGIN_BAD_UNIQUENICK = 0x0109 + LOGIN_BAD_PRE_AUTH = 0x010A + LOGIN_BAD_LOGIN_TICKET = 0x010B + LOGIN_TICKET_EXPIRED = 0x010C + + # Newuser. + NEW_USER = 0x0200 + NEW_USER_BAD_NICK = 0x0201 + NEW_USER_BAD_PASSWORDS = 0x0202 + NEW_USER_UNIQUENICK_INVALID = 0x0203 + NEW_USER_UNIQUENICK_IN_USE = 0x0204 + + # Updateui. + UPDATE_UI = 0x0300 + UPDATE_UI_BAD_EMAIL = 0x0301 + + # Newprofile. + NEW_PROFILE = 0x0400 + NEW_PROFILE_BAD_NICK = 0x0401 + NEW_PROFILE_BAD_OLD_NICK = 0x0402 + + # Updatepro. + UPDATE_PRO = 0x0500 + UPDATE_PRO_BAD_NICK = 0x0501 + + # Addbuddy. + ADD_BUDDY = 0x0600 + ADD_BUDDY_BAD_FORM = 0x0601 + ADD_BUDDY_BAD_NEW = 0x0602 + ADD_BUDDY_ALREADY_BUDDY = 0x0603 + + # Authadd. + AUTH_ADD = 0x0700 + AUTH_ADD_BAD_FORM = 0x0701 + AUTH_ADD_BAD_SIG = 0x0702 + + # Status. + STATUS = 0x0800 + + # Bm. + BM = 0x0900 + BM_NOT_BUDDY = 0x0901 + BM_EXT_INFO_NOT_SUPPORTED = 0x0902 + BM_BUDDY_OFFLINE = 0x0903 + + # Getprofile. + GET_PROFILE = 0x0A00 + GET_PROFILE_BAD_PROFILE = 0x0A01 + + # Delbuddy. + DEL_BUDDY = 0x0B00 + DEL_BUDDY_NOT_BUDDY = 0x0B01 + + # Delprofile. + DEL_PROFILE = 0x0C00 + DEL_PROFILE_LAST_PROFILE = 0x0C01 + + # Search. + SEARCH = 0x0D00 + SEARCH_CONNECTION_FAILED = 0x0D01 + SEARCH_TIME_OUT = 0x0D02 + + # Check. + CHECK = 0x0E00 + CHECK_BAD_MAIL = 0x0E01 + CHECK_BAD_NICK = 0x0E02 + CHECK_BAD_PASSWORD = 0x0E03 + + # Revoke. + REVOKE = 0x0F00 + REVOKE_NOT_BUDDY = 0x0F01 + + # Registeruniquenick. + REGISTER_UNIQUENICK = 0x1000 + REGISTER_UNIQUENICK_TAKEN = 0x1001 + REGISTER_UNIQUENICK_RESERVED = 0x1002 + REGISTER_UNIQUENICK_BAD_NAMESPACE = 0x1003 + + # Register UniSpy.Server.CDkey. + REGISTER_CDKEY = 0x1100 + REGISTER_CDKEY_BAD_KEY = 0x1101 + REGISTER_CDKEY_ALREADY_SET = 0x1102 + REGISTER_CDKEY_ALREADY_TAKEN = 0x1103 + + # AddBlock. + ADD_BLOCK = 0x1200 + ADD_BLOCK_ALREADY_BLOCKED = 0x1201 + + # RemoveBlock. + REMOVE_BLOCK = 0x1300 + REMOVE_BLOCK_NOT_BLOCKED = 0x1301 + + + +class RequestType(Enum): + CHECK = "check" + NEWUSER = "newuser" + NICKS = "nicks" + OTHERS = "others" + OTHERSLIST = "otherslist" + PMATCH = "pmatch" + SEARCH = "search" + SEARCHUNIQUE = "searchunique" + UNIQUESearch = "uniquesearch" + VALID = "valid" \ No newline at end of file diff --git a/src/frontends/gamespy/protocols/presence_search_player/aggregates/exceptions.py b/src/frontends/gamespy/protocols/presence_search_player/aggregates/exceptions.py new file mode 100644 index 000000000..f0e8c9782 --- /dev/null +++ b/src/frontends/gamespy/protocols/presence_search_player/aggregates/exceptions.py @@ -0,0 +1,434 @@ +from frontends.gamespy.library.exceptions.general import UniSpyException +from frontends.gamespy.protocols.presence_search_player.aggregates.enums import GPErrorCode +from frontends.gamespy.library.abstractions.contracts import ResponseBase + + +class GPException(UniSpyException, ResponseBase): + error_code: GPErrorCode + sending_buffer: str + + def __init__( + self, + message: str = "General error.", + error_code=GPErrorCode.GENERAL, + ) -> None: + UniSpyException.__init__(self, message) + self.error_code = error_code + + def build(self) -> None: + self.sending_buffer = f"\\error\\\\err\\{int(self.error_code)}\\fatal\\\\errmsg\\{ + self.message}\\final\\" + + +class GPParseException(GPException): + def __init__( + self, + message: str = "Request parsing error.", + error_code=GPErrorCode.PARSE, + ) -> None: + super().__init__(message, error_code) + + +class GPUdpLayerException(GPException): + def __init__( + self, + message: str = "Unknown UDP layer error.", + error_code=GPErrorCode.UDP_LAYER, + ) -> None: + super().__init__(message, error_code) + + +class GPNotLoginException(GPException): + def __init__( + self, + message: str = "You are not logged in, please login first.", + error_code=GPErrorCode.NOT_LOGGED_IN, + ) -> None: + super().__init__(message, error_code) + + +class GPNetworkException(GPException): + def __init__( + self, + message: str = "Unknown network error.", + error_code=GPErrorCode.NETWORK, + ) -> None: + super().__init__(message, error_code) + + +class GPForceDisconnectException(GPException): + def __init__( + self, + message: str = "Client is forced to disconnect.", + error_code=GPErrorCode.FORCED_DISCONNECT, + ) -> None: + super().__init__(message, error_code) + + +class GPDatabaseException(GPException): + def __init__( + self, + message: str = "Database error.", + error_code=GPErrorCode.DATABASE_ERROR, + ) -> None: + super().__init__(message, error_code) + + +class GPConnectionCloseException(GPException): + def __init__( + self, + message: str = "Client connection accidently closed.", + error_code=GPErrorCode.CONNECTION_CLOSE, + ) -> None: + super().__init__(message, error_code) + + +class GPBadSessionKeyException(GPException): + def __init__( + self, + message: str = "Session key is invalid.", + error_code=GPErrorCode.BAD_SESSION_KEY, + ) -> None: + super().__init__(message, error_code) + + +class GPAddBuddyException(GPException): + def __init__( + self, + message: str = "Unknown error occur at add buddy.", + error_code=GPErrorCode.ADD_BUDDY, + ) -> None: + super().__init__(message, error_code) + + +class GPAddBuddyAlreadyException(GPAddBuddyException): + def __init__( + self, + message: str = "The buddy you are adding is already in your buddy list.", + error_code=GPErrorCode.ADD_BUDDY_ALREADY_BUDDY, + ) -> None: + super().__init__(message, error_code) + + +class GPAddBuddyBadFormatException(GPAddBuddyException): + def __init__( + self, + message: str = "Add buddy format invalid.", + error_code=GPErrorCode.ADD_BUDDY_BAD_FORM, + ) -> None: + super().__init__(message, error_code) + + +class GPAddBuddyBadNewException(GPAddBuddyException): + def __init__( + self, + message: str = "The buddy name provided is invalid.", + error_code=GPErrorCode.ADD_BUDDY_BAD_NEW, + ) -> None: + super().__init__(message, error_code) + + +class AuthAddException(GPException): + def __init__( + self, + message: str = "The adding of authentication failed.", + error_code=GPErrorCode.AUTH_ADD, + ) -> None: + super().__init__(message, error_code) + + +class AuthAddBadFormatException(AuthAddException): + def __init__( + self, + message: str = "The authentication is in bad form.", + error_code=GPErrorCode.AUTH_ADD_BAD_FORM, + ) -> None: + super().__init__(message, error_code) + + +class AuthAddBadSigException(AuthAddException): + def __init__( + self, + message: str = "The signature in authentication is invalid.", + error_code=GPErrorCode.AUTH_ADD_BAD_SIG, + ) -> None: + super().__init__(message, error_code) + + +class GPBuddyMsgException(GPException): + def __init__( + self, + message: str = "Unknown error occur when processing buddy message.", + error_code=GPErrorCode.BM, + ) -> None: + super().__init__(message, error_code) + + +class GPBuddyMsgExtInfoNotSupportedException(GPBuddyMsgException): + def __init__( + self, + message: str = "Buddy message is not supported.", + error_code=GPErrorCode.BM_EXT_INFO_NOT_SUPPORTED, + ) -> None: + super().__init__(message, error_code) + + +class GPBuddyMsgNotBuddyException(GPBuddyMsgException): + def __init__( + self, + message: str = "The message receiver is not your buddy.", + error_code=GPErrorCode.BM_NOT_BUDDY, + ) -> None: + super().__init__(message, error_code) + + +class CheckException(GPException): + def __init__( + self, + message: str = "There was an error checking the user account.", + error_code=GPErrorCode.CHECK, + ) -> None: + super().__init__(message, error_code) + + def build(self) -> None: + self.sending_buffer = f"\\cur\\{int(self.error_code)}\\final\\" + + +class GPLoginException(GPException): + def __init__( + self, + message: str = "Unknown login error.", + error_code=GPErrorCode.LOGIN, + ) -> None: + super().__init__(message, error_code) + + +class GPLoginBadEmailException(GPLoginException): + def __init__( + self, + message: str = "Email provided is invalid.", + error_code=GPErrorCode.LOGIN_BAD_EMAIL, + ) -> None: + super().__init__(message, error_code) + + +class GPLoginBadLoginTicketException(GPLoginException): + def __init__( + self, + message: str = "The login ticket is invalid.", + error_code=GPErrorCode.LOGIN_TICKET_EXPIRED, + ) -> None: + super().__init__(message, error_code) + + +class GPLoginBadNickException(GPLoginException): + def __init__( + self, + message: str = "Nickname is in valid.", + error_code=GPErrorCode.LOGIN_BAD_NICK, + ) -> None: + super().__init__(message, error_code) + + +class GPLoginBadPasswordException(GPLoginException): + def __init__( + self, + message: str = "Password provided is invalid.", + error_code=GPErrorCode.LOGIN_BAD_PASSWORD, + ) -> None: + super().__init__(message, error_code) + + +class GPLoginBadPreAuthException(GPLoginException): + def __init__( + self, + message: str = "Login pre-authentication failed.", + error_code=GPErrorCode.LOGIN_BAD_PRE_AUTH, + ) -> None: + super().__init__(message, error_code) + + +class GPLoginBadProfileException(GPLoginException): + def __init__( + self, + message: str = "User profile is damaged.", + error_code=GPErrorCode.LOGIN_BAD_PROFILE, + ) -> None: + super().__init__(message, error_code) + + +class GPLoginBadUniquenickException(GPLoginException): + def __init__( + self, + message: str = "The uniquenick provided is invalid.", + error_code=GPErrorCode.LOGIN_BAD_UNIQUENICK, + ) -> None: + super().__init__(message, error_code) + + +class GPLoginConnectionFailedException(GPLoginException): + def __init__( + self, + message: str = "Login connection failed.", + error_code=GPErrorCode.LOGIN_CONNECTION_FAILED, + ) -> None: + super().__init__(message, error_code) + + +class GPLoginProfileDeletedException(GPLoginException): + def __init__( + self, + message: str = "Login connection failed.", + error_code=GPErrorCode.LOGIN_PROFILE_DELETED, + ) -> None: + super().__init__(message, error_code) + + +class GPLoginServerAuthFailedException(GPLoginException): + def __init__( + self, + message: str = "Login server authentication failed.", + error_code=GPErrorCode.LOGIN_SERVER_AUTH_FAILED, + ) -> None: + super().__init__(message, error_code) + + +class GPLoginTicketExpiredException(GPLoginException): + def __init__( + self, + message: str = "The login ticket have expired.", + error_code=GPErrorCode.LOGIN_TICKET_EXPIRED, + ) -> None: + super().__init__(message, error_code) + + +class GPLoginTimeOutException(GPLoginException): + def __init__( + self, + message: str = "Login timeout.", + error_code=GPErrorCode.LOGIN_TIME_OUT, + ) -> None: + super().__init__(message, error_code) + + +class GPNewProfileException(GPException): + def __init__( + self, + message: str = "An unknown error occur when creating new profile.", + error_code=GPErrorCode.NEW_PROFILE, + ) -> None: + super().__init__(message, error_code) + + +class GPNewProfileBadNickException(GPNewProfileException): + def __init__( + self, + message: str = "Nickname is invalid at creating new profile.", + error_code=GPErrorCode.NEW_PROFILE_BAD_NICK, + ) -> None: + super().__init__(message, error_code) + + +class GPNewProfileBadOldNickException(GPNewProfileException): + def __init__( + self, + message: str = "There is an already exist nickname.", + error_code=GPErrorCode.NEW_PROFILE_BAD_OLD_NICK, + ) -> None: + super().__init__(message, error_code) + + +class GPNewUserException(GPException): + def __init__( + self, + message: str = "There was an unknown error creating user account.", + error_code=GPErrorCode.NEW_USER, + ) -> None: + super().__init__(message, error_code) + + +class GPNewUserBadNickException(GPException): + def __init__( + self, + message: str = "The nickname provided is invalid.", + error_code=GPErrorCode.NEW_USER_BAD_NICK, + ) -> None: + super().__init__(message, error_code) + + +class GPNewUserBadPasswordException(GPException): + def __init__( + self, + message: str = "Password is invalid.", + error_code=GPErrorCode.NEW_USER_BAD_PASSWORDS, + ) -> None: + super().__init__(message, error_code) + + +class GPNewUserUniquenickInUseException(GPException): + def __init__( + self, + message: str = "Uniquenick is in use.", + error_code=GPErrorCode.NEW_USER_UNIQUENICK_IN_USE, + ) -> None: + super().__init__(message, error_code) + + +class GPNewUserUniquenickInvalidException(GPException): + def __init__( + self, + message: str = "Uniquenick is invalid.", + error_code=GPErrorCode.NEW_USER_UNIQUENICK_INVALID, + ) -> None: + super().__init__(message, error_code) + + +class GPStatusException(GPException): + def __init__( + self, + message: str = "Unknown error happen when processing player status.", + error_code=GPErrorCode.STATUS, + ) -> None: + super().__init__(message, error_code) + + +class GPUpdateProfileException(GPException): + def __init__( + self, + message: str = "Update profile unknown error.", + error_code=GPErrorCode.UPDATE_PRO, + ) -> None: + super().__init__(message, error_code) + + +class GPUpdateProBadNickException(GPUpdateProfileException): + def __init__( + self, + message: str = "Nickname is invalid for updating profile.", + error_code=GPErrorCode.UPDATE_PRO_BAD_NICK, + ) -> None: + super().__init__(message, error_code) + + +class GPUpdateUIException(GPException): + def __init__( + self, + message: str = "Update user info unknown error.", + error_code=GPErrorCode.UPDATE_UI, + ) -> None: + super().__init__(message, error_code) + + +class GPUpdateUIBadEmailException(GPException): + def __init__( + self, + message: str = "Email is invalid.", + error_code=GPErrorCode.UPDATE_UI_BAD_EMAIL, + ) -> None: + super().__init__(message, error_code) + + +MAPPING = { + "GPException": GPException, + +} diff --git a/src/frontends/gamespy/protocols/presence_search_player/applications/client.py b/src/frontends/gamespy/protocols/presence_search_player/applications/client.py new file mode 100644 index 000000000..1e48f0830 --- /dev/null +++ b/src/frontends/gamespy/protocols/presence_search_player/applications/client.py @@ -0,0 +1,18 @@ +from frontends.gamespy.library.abstractions.client import ClientBase + +from frontends.gamespy.library.abstractions.switcher import SwitcherBase +from frontends.gamespy.library.log.log_manager import LogWriter +from frontends.gamespy.library.network.tcp_handler import TcpConnection +from frontends.gamespy.library.configs import ServerConfig + + +class Client(ClientBase): + client_pool: dict[str, "Client"] = {} + + def __init__(self, connection: TcpConnection, server_config: ServerConfig, logger: LogWriter): + super().__init__(connection, server_config, logger) + + def _create_switcher(self, buffer: bytes) -> SwitcherBase: + from frontends.gamespy.protocols.presence_search_player.applications.switcher import Switcher + temp_buffer = buffer.decode() + return Switcher(self, temp_buffer) diff --git a/src/frontends/gamespy/protocols/presence_search_player/applications/handlers.py b/src/frontends/gamespy/protocols/presence_search_player/applications/handlers.py new file mode 100644 index 000000000..a5b8c2a13 --- /dev/null +++ b/src/frontends/gamespy/protocols/presence_search_player/applications/handlers.py @@ -0,0 +1,116 @@ + +from typing import final +from frontends.gamespy.protocols.presence_search_player.contracts.requests import CheckRequest, NewUserRequest, NicksRequest, OthersListRequest, OthersRequest, SearchRequest, SearchUniqueRequest, UniqueSearchRequest, ValidRequest + +from frontends.gamespy.protocols.presence_search_player.contracts.responses import CheckResponse, NewUserResponse, NicksResponse, OthersListResponse, OthersResponse, SearchResponse, SearchUniqueResponse, UniqueSearchResponse, ValidResponse +from frontends.gamespy.protocols.presence_search_player.contracts.results import CheckResult, NewUserResult, NicksResult, OthersListResult, OthersResult, SearchResult, SearchUniqueResult, UniqueSearchResult, ValidResult + +from frontends.gamespy.protocols.presence_search_player.abstractions.handler import CmdHandlerBase +from frontends.gamespy.protocols.presence_search_player.applications.client import Client + + +@final +class CheckHandler(CmdHandlerBase): + _request: CheckRequest + _result: CheckResult + _response: CheckResponse + + def __init__(self, client: Client, request: CheckRequest) -> None: + assert isinstance(request, CheckRequest) + super().__init__(client, request) + + +@final +class NewUserHandler(CmdHandlerBase): + _request: NewUserRequest + _result: NewUserResult + _response: NewUserResponse + + def __init__(self, client: Client, request: NewUserRequest) -> None: + assert isinstance(request, NewUserRequest) + super().__init__(client, request) + + +@final +class NicksHandler(CmdHandlerBase): + _request: NicksRequest + _result: NicksResult + _response: NicksResponse + + def __init__(self, client: Client, request: NicksRequest) -> None: + assert isinstance(request, NicksRequest) + super().__init__(client, request) + + +@final +class OthersHandler(CmdHandlerBase): + _request: OthersRequest + _result: OthersResult + _response: OthersResponse + + def __init__(self, client: Client, request: OthersRequest) -> None: + assert isinstance(request, OthersRequest) + super().__init__(client, request) + + +@final +class OthersListHandler(CmdHandlerBase): + _result: OthersListResult + _response: OthersListResponse + + def __init__(self, client: Client, request: OthersListRequest) -> None: + assert isinstance(request, OthersListRequest) + super().__init__(client, request) + + +@final +class SearchHandler(CmdHandlerBase): + """ + last one we search with email this may get few profile so we can not return GPErrorCode + SearchWithEmail(client,dict ); + \\search\\\\sesskey\\0\\profileid\\0\\namespaceid\\1\\partnerid\\0\\nick\\mycrysis\\uniquenick\\xiaojiuwo\\email\\koujiangheng@live.cn\\gamename\\gmtest\\final\\ + \\bsrdone\\more\\\\final\\ + string sendingbuffer = + "\\\\bsr\\\\1\\\\nick\\\\mycrysis\\\\uniquenick\\\\1\\\\namespaceid\\\\0\\\\firstname\\\\jiangheng\\\\lastname\\\\kou\\\\email\\\\koujiangheng@live.cn\\\\bsrdone\\\\0\\\\final\\\\"; + client.Stream.SendAsync(sendingbuffer); + \\more\\\\final\\ + \\search\\sesskey\\0\\profileid\\0\\namespaceid\\0\\nick\\gbr359_jordips\\gamename\\gbrome\\final\\ + """ + _result: SearchResult + _response: SearchResponse + + def __init__(self, client: Client, request: SearchRequest) -> None: + assert isinstance(request, SearchRequest) + super().__init__(client, request) + + +@final +class SearchUniqueHandler(CmdHandlerBase): + _result: SearchUniqueResult + _response: SearchUniqueResponse + + def __init__(self, client: Client, request: SearchUniqueRequest) -> None: + assert isinstance(request, SearchUniqueRequest) + super().__init__(client, request) + + +@final +class UniqueSearchHandler(CmdHandlerBase): + _request: UniqueSearchRequest + _result: UniqueSearchResult + _response: UniqueSearchResponse + + def __init__(self, client: Client, request: UniqueSearchRequest) -> None: + assert isinstance(request, UniqueSearchRequest) + super().__init__(client, request) + + +@final +class ValidHandler(CmdHandlerBase): + _result: ValidResult + _request: ValidRequest + _response: ValidResponse + + def __init__(self, client: Client, request: ValidRequest) -> None: + assert isinstance(request, ValidRequest) + super().__init__(client, request) diff --git a/src/frontends/gamespy/protocols/presence_search_player/applications/server_launcher.py b/src/frontends/gamespy/protocols/presence_search_player/applications/server_launcher.py new file mode 100644 index 000000000..8acdf0155 --- /dev/null +++ b/src/frontends/gamespy/protocols/presence_search_player/applications/server_launcher.py @@ -0,0 +1,21 @@ +from frontends.gamespy.library.abstractions.server_launcher import ServicesFactory, ServiceBase +from frontends.gamespy.library.network.tcp_handler import TcpServer +from frontends.gamespy.protocols.presence_search_player.applications.client import ( + Client, +) + + +class Service(ServiceBase): + def __init__(self) -> None: + super().__init__( + config_name="PresenceSearchPlayer", + client_cls=Client, + network_server_cls=TcpServer + ) + + +if __name__ == "__main__": + from frontends.gamespy.library.extentions.debug_helper import DebugHelper + psp = Service() + helper = DebugHelper("./frontends/", ServicesFactory([psp])) + helper.start() diff --git a/src/frontends/gamespy/protocols/presence_search_player/applications/switcher.py b/src/frontends/gamespy/protocols/presence_search_player/applications/switcher.py new file mode 100644 index 000000000..9ea3cab57 --- /dev/null +++ b/src/frontends/gamespy/protocols/presence_search_player/applications/switcher.py @@ -0,0 +1,64 @@ +from typing import TYPE_CHECKING, Optional, cast +from frontends.gamespy.library.abstractions.switcher import SwitcherBase +from frontends.gamespy.protocols.presence_search_player.aggregates.enums import RequestType +from frontends.gamespy.protocols.presence_search_player.contracts.requests import CheckRequest, NewUserRequest, NicksRequest, OthersListRequest, OthersRequest, SearchRequest, SearchUniqueRequest, UniqueSearchRequest, ValidRequest + +from frontends.gamespy.protocols.presence_search_player.applications.handlers import CheckHandler, NewUserHandler, NicksHandler, OthersHandler, OthersListHandler, SearchHandler, SearchUniqueHandler, UniqueSearchHandler, ValidHandler + +from frontends.gamespy.protocols.presence_search_player.abstractions.handler import CmdHandlerBase + +from frontends.gamespy.protocols.presence_search_player.applications.client import Client + + +class Switcher(SwitcherBase): + _raw_request: str + + def __init__(self, client: Client, raw_request: str): + assert isinstance(client, Client) + assert isinstance(raw_request, str) + super().__init__(client, raw_request) + + def _process_raw_request(self): + if self._raw_request[0] != "\\": + self._client.log_info("Invalid request received!") + return + raw_requests = [ + r+"\\final\\" for r in self._raw_request.split("\\final\\") if r] + for raw_request in raw_requests: + name = raw_request.strip("\\").split("\\", 1)[0] + if name not in RequestType: + self._client.log_debug( + f"Request: {name} is not a valid request.") + continue + self._requests.append((RequestType(name), raw_request)) + + def _create_cmd_handlers(self, name: RequestType, raw_request: str) -> CmdHandlerBase | None: + assert isinstance(name, RequestType) + if TYPE_CHECKING: + self._client = cast(Client, self._client) + + match name: + case RequestType.CHECK: + return CheckHandler(self._client, CheckRequest(raw_request)) + case RequestType.NEWUSER: + return NewUserHandler(self._client, NewUserRequest(raw_request)) + case RequestType.NICKS: + return NicksHandler(self._client, NicksRequest(raw_request)) + case RequestType.OTHERS: + return OthersHandler(self._client, OthersRequest(raw_request)) + case RequestType.OTHERSLIST: + return OthersListHandler(self._client, OthersListRequest(raw_request)) + case RequestType.PMATCH: + # Uncomment the line below when PMatchHandler is implemented + # return PMatchHandler(self._client, PMatchRequest(raw_request)) + raise NotImplementedError("PMatchHandler is not implemented.") + case RequestType.SEARCH: + return SearchHandler(self._client, SearchRequest(raw_request)) + case RequestType.SEARCHUNIQUE: + return SearchUniqueHandler(self._client, SearchUniqueRequest(raw_request)) + case RequestType.UNIQUESearch: + return UniqueSearchHandler(self._client, UniqueSearchRequest(raw_request)) + case RequestType.VALID: + return ValidHandler(self._client, ValidRequest(raw_request)) + case _: + return None diff --git a/src/frontends/gamespy/protocols/presence_search_player/contracts/requests.py b/src/frontends/gamespy/protocols/presence_search_player/contracts/requests.py new file mode 100644 index 000000000..4b9ba84f2 --- /dev/null +++ b/src/frontends/gamespy/protocols/presence_search_player/contracts/requests.py @@ -0,0 +1,317 @@ +from frontends.gamespy.library.extentions.gamespy_utils import is_email_format_correct +from frontends.gamespy.library.extentions.password_encoder import process_password +from frontends.gamespy.protocols.presence_search_player.abstractions.contracts import ( + RequestBase, +) +from frontends.gamespy.protocols.presence_search_player.aggregates.enums import ( + SearchType, +) +from frontends.gamespy.protocols.presence_search_player.aggregates.exceptions import ( + GPParseException, +) + + +class CheckRequest(RequestBase): + # \check\\nick\\email\\partnerid\0\passenc\\gamename\gmtest\final\ + nick: str + password: str + email: str + partner_id: int + + def parse(self): + super().parse() + self.password = process_password(self._request_dict) + if "nick" not in self._request_dict or "email" not in self._request_dict: + raise GPParseException("check request is incompelete.") + + if not is_email_format_correct(self._request_dict["email"]): + raise GPParseException(" email format is incorrect.") + + self.nick = self._request_dict["nick"] + self.email = self._request_dict["email"] + + if "partner_id" in self._request_dict.keys(): + try: + self.partner_id = int(self._request_dict["partner_id"]) + except Exception: + raise GPParseException( + "no partner id found, check whether need implement the default partnerid" + ) + else: + self.partner_id = 1 + + +class NewUserRequest(RequestBase): + product_id: int + game_port: int + cd_key: str + nick: str + email: str + password: str + partner_id: int + game_name: str + uniquenick: str + + def parse(self): + super().parse() + self.password = process_password(self._request_dict) + + if "nick" not in self._request_dict: + raise GPParseException("nickname is missing.") + if "email" not in self._request_dict: + raise GPParseException("email is missing.") + if not is_email_format_correct(self._request_dict["email"]): + raise GPParseException("email format is incorrect.") + self.nick = self._request_dict["nick"] + self.email = self._request_dict["email"] + + if "uniquenick" in self._request_dict and "namespaceid" in self._request_dict: + if "namespaceid" in self._request_dict: + try: + self.namespace_id = int(self._request_dict["namespaceid"]) + except ValueError: + raise GPParseException("namespaceid is incorrect.") + + self.uniquenick = self._request_dict["uniquenick"] + self.parse_other_info() + + def parse_other_info(self): + if "partnerid" in self._request_dict: + try: + self.partner_id = int(self._request_dict["partnerid"]) + except ValueError: + raise GPParseException("partnerid is incorrect.") + else: + self.partner_id = 0 + if "productid" in self._request_dict: + try: + self.product_id = int(self._request_dict["productid"]) + except ValueError: + raise GPParseException("productid is incorrect.") + else: + # we give default product id here + self.product_id = 0 + + if "gamename" in self._request_dict: + self.game_name = self._request_dict["gamename"] + + if "port" in self._request_dict: + try: + self.game_port = int(self._request_dict["port"]) + except ValueError: + raise GPParseException("port is incorrect.") + + if "cdkey" in self._request_dict: + self.cd_key = self._request_dict["cdkey"] + + +class NicksRequest(RequestBase): + password: str + email: str + is_require_uniquenicks: bool + + def parse(self): + super().parse() + self.is_require_uniquenicks = True + self.password = process_password(self._request_dict) + if "email" not in self._request_dict.keys(): + raise GPParseException("email is missing.") + + self.email = self._request_dict["email"] + + if "pass" in self._request_dict.keys(): + self.is_require_uniquenicks = False + + +class OthersListRequest(RequestBase): + profile_ids: list[int] = [] + namespace_id: int = 0 + + def parse(self) -> None: + super().parse() + if "opids" not in self._request_dict or "namespaceid" not in self._request_dict: + raise GPParseException("opids or namespaceid is missing.") + + try: + self.profile_ids = [ + int(opid) for opid in self._request_dict["opids"].strip("|").split("|") + ] + except: + raise GPParseException("opids is incorrect") + + +class OthersRequest(RequestBase): + profile_id: int + game_name: str + + def parse(self): + super().parse() + + if "gamename" not in self._request_dict: + raise GPParseException("gamename is missing.") + + self.game_name = self._request_dict["gamename"] + + if ( + "profileid" not in self._request_dict + or "namespaceid" not in self._request_dict + ): + raise GPParseException("profileid or namespaceid is missing.") + + if "profileid" not in self._request_dict: + raise GPParseException("profileid is incorrect.") + + try: + self.profile_id = int(self._request_dict["profileid"]) + except ValueError: + raise GPParseException("profileid is incorrect.") + + +class SearchRequest(RequestBase): + skip_num: int + request_type: SearchType + game_name: str + profile_id: int + partner_id: int + email: str + nick: str + uniquenick: str + session_key: str + firstname: str + lastname: str + icquin: str + + def __init__(self, raw_request: str) -> None: + super().__init__(raw_request) + self.skip_num = 0 + self.partner_id = 0 + + def parse(self) -> None: + super().parse() + + if ( + "profileid" not in self._request_dict + and "nick" not in self._request_dict + and "email" not in self._request_dict + and "namespaceid" not in self._request_dict + and "gamename" not in self._request_dict + and "sesskey" not in self._request_dict + ): + raise GPParseException("Search request is incomplete.") + + self.session_key = self._request_dict["sesskey"] + + if "firstname" in self._request_dict: + self.firstname = self._request_dict["firstname"] + + if "lastname" in self._request_dict: + self.lastname = self._request_dict["lastname"] + + if "icquin" in self._request_dict: + self.icquin = self._request_dict["icquin"] + + if "gamename" in self._request_dict: + self.game_name = self._request_dict["gamename"] + + if "profileid" in self._request_dict: + try: + self.profile_id = int(self._request_dict["profileid"]) + except ValueError: + raise GPParseException("profileid is incorrect.") + + if "partnerid" in self._request_dict: + try: + self.partner_id = int(self._request_dict["partnerid"]) + except ValueError: + raise GPParseException("partnerid is incorrect.") + + if "skip" in self._request_dict: + try: + self.skip_num = int(self._request_dict["skip"]) + except ValueError: + raise GPParseException("skip number is incorrect.") + + if "uniquenick" in self._request_dict and "namespaceid" in self._request_dict: + self.request_type = SearchType.UNIQUENICK_NAMESPACEID_SEARCH + self.uniquenick = self._request_dict["uniquenick"] + elif "nick" in self._request_dict and "email" in self._request_dict: + self.request_type = SearchType.NICK_EMAIL_SEARCH + self.nick = self._request_dict["nick"] + self.email = self._request_dict["email"] + elif "nick" in self._request_dict: + self.request_type = SearchType.NICK_SEARCH + self.nick = self._request_dict["nick"] + elif "email" in self._request_dict: + self.request_type = SearchType.EMAIL_SEARCH + self.email = self._request_dict["email"] + else: + raise GPParseException("unknown search type.") + + +class SearchUniqueRequest(RequestBase): + uniquenick: str + namespace_ids: list[int] + + def parse(self): + super().parse() + self.namespace_ids = [] + if ( + "uniquenick" not in self._request_dict + or "namespaces" not in self._request_dict + ): + raise GPParseException("searchunique request is incomplete.") + + try: + self.uniquenick = self._request_dict["uniquenick"] + except KeyError: + raise GPParseException("uniquenick is missing.") + + try: + self.namespace_ids = [ + int(namespace_id) + for namespace_id in self._request_dict["namespaces"] + .lstrip(",") + .split(",") + ] + except ValueError: + raise GPParseException("namespaces is incorrect.") + + +class UniqueSearchRequest(RequestBase): + preferred_nick: str + game_name: str + + def parse(self): + super().parse() + + if "preferrednick" not in self._request_dict: + raise GPParseException("preferrednick is missing.") + + self.preferred_nick = self._request_dict["preferrednick"] + + if "gamename" not in self._request_dict: + raise GPParseException("gamename is missing.") + + self.game_name = self._request_dict["gamename"] + + if "namespaceid" not in self._request_dict: + raise GPParseException("namespaceid is missing.") + + try: + self.namespace_id = int(self._request_dict["namespaceid"]) + except ValueError: + raise GPParseException("namespaceid is incorrect.") + + +class ValidRequest(RequestBase): + email: str + + def parse(self): + super().parse() + + if "email" not in self._request_dict or not is_email_format_correct( + self._request_dict["email"] + ): + raise GPParseException("valid request is incomplete.") + + self.email = self._request_dict["email"] diff --git a/src/frontends/gamespy/protocols/presence_search_player/contracts/responses.py b/src/frontends/gamespy/protocols/presence_search_player/contracts/responses.py new file mode 100644 index 000000000..32a5ab57f --- /dev/null +++ b/src/frontends/gamespy/protocols/presence_search_player/contracts/responses.py @@ -0,0 +1,171 @@ +from frontends.gamespy.protocols.presence_search_player.abstractions.contracts import ( + ResponseBase, +) +from frontends.gamespy.protocols.presence_search_player.contracts.requests import ( + CheckRequest, + NewUserRequest, + NicksRequest, + UniqueSearchRequest, + ValidRequest, +) +from frontends.gamespy.protocols.presence_search_player.contracts.results import ( + CheckResult, + NewUserResult, + NicksResult, + OthersListResult, + OthersResult, + SearchResult, + SearchUniqueResult, + UniqueSearchResult, + ValidResult, +) + + +class CheckResponse(ResponseBase): + _result: CheckResult + + def __init__(self, result: CheckResult) -> None: + assert isinstance(result, CheckResult) + super().__init__(result) + + def build(self): + if self._result.profile_id is None: + self.sending_buffer = "\\cur\\1\\final\\" + else: + self.sending_buffer = f"\\cur\\0\\pid\\{self._result.profile_id}\\final\\" + + +class NewUserResponse(ResponseBase): + _result: NewUserResult + + def __init__(self, result: NewUserResult) -> None: + assert isinstance(result, NewUserResult) + super().__init__(result) + + def build(self): + self.sending_buffer = f"\\nur\\\\pid\\{self._result.profile_id}\\final\\" + + +class NicksResponse(ResponseBase): + + _result: NicksResult + + def __init__(self, result: NicksResult) -> None: + assert isinstance(result, NicksResult) + super().__init__(result) + + def build(self): + self.sending_buffer = "\\nr\\" + for info in self._result.data: + self.sending_buffer += f"\\nick\\{info.nick}" + if self._result.is_require_uniquenicks: + self.sending_buffer += f"\\uniquenick\\{info.uniquenick}" + self.sending_buffer += "\\ndone\\final\\" + + +class OthersListResponse(ResponseBase): + _result: OthersListResult + + def __init__(self, result: OthersListResult) -> None: + assert isinstance(result, OthersListResult) + self._result = result + + def build(self): + self.sending_buffer = "\\otherslist\\" + for info in self._result.data: + self.sending_buffer += f"\\o\\{info.profile_id}" + self.sending_buffer += f"\\uniquenick\\{info.unique_nick}" + self.sending_buffer += "oldone" + + +class OthersResponse(ResponseBase): + _result: OthersResult + + def __init__(self, result: OthersResult) -> None: + assert isinstance(result, OthersResult) + self._result = result + + def build(self): + self.sending_buffer = "\\others\\" + for info in self._result.data: + self.sending_buffer += f"\\o\\{info.profile_id}" + self.sending_buffer += f"\\nick\\{info.nick}" + self.sending_buffer += f"\\uniquenick\\{info.uniquenick}" + self.sending_buffer += f"\\first\\{info.firstname}" + self.sending_buffer += f"\\last\\{info.lastname}" + self.sending_buffer += f"\\email\\{info.email}" + self.sending_buffer += "\\odone\\final\\" + + +class SearchResponse(ResponseBase): + _result: SearchResult + + def __init__(self, result: SearchResult) -> None: + assert isinstance(result, SearchResult) + self._result = result + + def build(self): + self.sending_buffer = "\\bsr\\" + for info in self._result.data: + self.sending_buffer += str(info.profile_id) + self.sending_buffer += f"\\nick\\{info.nick}" + self.sending_buffer += f"\\uniquenick\\{info.uniquenick}" + self.sending_buffer += f"\\namespaceid\\{info.namespace_id}" + self.sending_buffer += f"\\firstname\\{info.firstname}" + self.sending_buffer += f"\\lastname\\{info.lastname}" + self.sending_buffer += f"\\email\\{info.email}" + self.sending_buffer += "\\bsrdone\\\\more\\0\\final\\" + + +class SearchUniqueResponse(ResponseBase): + _result: SearchUniqueResult + + def __init__(self, result: SearchUniqueResult) -> None: + assert isinstance(result, SearchUniqueResult) + self._result = result + + def build(self): + self.sending_buffer = "\\bsr\\" + for info in self._result.data: + self.sending_buffer += str(info.profile_id) + self.sending_buffer += f"\\nick\\{info.nick}" + self.sending_buffer += f"\\uniquenick\\{info.uniquenick}" + self.sending_buffer += f"\\namespaceid\\{info.namespace_id}" + self.sending_buffer += f"\\firstname\\{info.firstname}" + self.sending_buffer += f"\\lastname\\{info.lastname}" + self.sending_buffer += f"\\email\\{info.email}" + self.sending_buffer += "\\bsrdone\\\\more\\0\\final\\" + + +class ValidResponse(ResponseBase): + + _result: ValidResult + + def __init__(self, result: ValidResult) -> None: + assert isinstance(result, ValidResult) + super().__init__(result) + + def build(self): + if self._result.is_account_valid: + self.sendingbuffer = "\\vr\\1\\final\\" + else: + self.sendingbuffer = "\\vr\\0\\final\\" + + +class UniqueSearchResponse(ResponseBase): + + _result: UniqueSearchResult + + def __init__( + self, result: UniqueSearchResult + ) -> None: + assert isinstance(result, UniqueSearchResult) + super().__init__(result) + + def build(self): + if self._result.is_uniquenick_exist: + self.sending_buffer = "\\us\\1\\nick\\Choose another name\\usdone\\final\\" + else: + self.sending_buffer = ( + f"\\us\\1\\nick\\{self._result.preferred_nick}\\usdone\\final\\" + ) diff --git a/src/frontends/gamespy/protocols/presence_search_player/contracts/results.py b/src/frontends/gamespy/protocols/presence_search_player/contracts/results.py new file mode 100644 index 000000000..8295db1fb --- /dev/null +++ b/src/frontends/gamespy/protocols/presence_search_player/contracts/results.py @@ -0,0 +1,87 @@ +from pydantic import BaseModel + +from frontends.gamespy.protocols.presence_search_player.abstractions.contracts import ResultBase + + +class CheckResult(ResultBase): + profile_id: int + + +class NewUserResult(ResultBase): + user_id: int + profile_id: int + + +class NickResultData(BaseModel): + nick: str + uniquenick: str + + +class NicksResult(ResultBase): + data: list[NickResultData] + """ [ + (nick1, uniquenick1), + (nick2, uniquenick2), + (nick3, uniquenick3), + ... + ] + """ + is_require_uniquenicks: bool = False + + +class OthersListData(BaseModel): + profile_id: int + unique_nick: str + + +class OthersListResult(ResultBase): + data: list[OthersListData] = [] + """ + [ + (prifileid1,uniquenick1), + (prifileid2,uniquenick2), + (prifileid3,uniquenick3), + ... + ] + """ + + +class OthersResultData(BaseModel): + profile_id: int + nick: str + uniquenick: str + lastname: str + firstname: str + user_id: int + email: str + + +class OthersResult(ResultBase): + data: list[OthersResultData] = [] + + +class SearchResultData(BaseModel): + profile_id: int + nick: str + uniquenick: str + email: str + firstname: str + lastname: str + namespace_id: int + + +class SearchResult(ResultBase): + data: list[SearchResultData] + + +class SearchUniqueResult(ResultBase): + data: list[SearchResultData] + + +class UniqueSearchResult(ResultBase): + is_uniquenick_exist: bool + preferred_nick: str + + +class ValidResult(ResultBase): + is_account_valid: bool = False diff --git a/src/frontends/gamespy/protocols/query_report/__init__.py b/src/frontends/gamespy/protocols/query_report/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/gamespy/protocols/query_report/aggregates/enums.py b/src/frontends/gamespy/protocols/query_report/aggregates/enums.py new file mode 100644 index 000000000..dc8b14a3f --- /dev/null +++ b/src/frontends/gamespy/protocols/query_report/aggregates/enums.py @@ -0,0 +1,13 @@ +from enum import Enum + + +class GameServerStatus(Enum): + NORMAL = 0 + UPDATE = 1 + SHUTDOWN = 2 + PLAYING = 3 + + +class ProtocolVersion(Enum): + V1 = 1 + V2 = 2 diff --git a/src/frontends/gamespy/protocols/query_report/aggregates/exceptions.py b/src/frontends/gamespy/protocols/query_report/aggregates/exceptions.py new file mode 100644 index 000000000..14d7ba343 --- /dev/null +++ b/src/frontends/gamespy/protocols/query_report/aggregates/exceptions.py @@ -0,0 +1,5 @@ +from frontends.gamespy.library.exceptions.general import UniSpyException + + +class QRException(UniSpyException): + pass diff --git a/src/frontends/gamespy/protocols/query_report/aggregates/game_server_info.py b/src/frontends/gamespy/protocols/query_report/aggregates/game_server_info.py new file mode 100644 index 000000000..1a4b5ee7e --- /dev/null +++ b/src/frontends/gamespy/protocols/query_report/aggregates/game_server_info.py @@ -0,0 +1,29 @@ +from datetime import datetime +from uuid import UUID + +from pydantic import BaseModel + +from frontends.gamespy.library.extentions.bytes_extentions import ip_to_4_bytes +from frontends.gamespy.protocols.query_report.aggregates.enums import GameServerStatus + +NESSESARY_KEYS: list[str] = ["gamename", "hostname", "hostport"] + + +class GameServerInfo(BaseModel): + server_id: UUID + host_ip_address: str + instant_key: str + game_name: str + query_report_port: int + + update_time: datetime + status: GameServerStatus + data:dict[str,str] + + @property + def query_report_port_bytes(self) -> bytes: + return self.query_report_port.to_bytes(2) + + @property + def host_ip_address_bytes(self) -> bytes: + return ip_to_4_bytes(self.host_ip_address) diff --git a/src/frontends/gamespy/protocols/query_report/aggregates/natneg_channel.py b/src/frontends/gamespy/protocols/query_report/aggregates/natneg_channel.py new file mode 100644 index 000000000..6c4351f6f --- /dev/null +++ b/src/frontends/gamespy/protocols/query_report/aggregates/natneg_channel.py @@ -0,0 +1,41 @@ +from typing import TYPE_CHECKING +from frontends.gamespy.library.abstractions.brocker import BrockerBase +from frontends.gamespy.library.configs import CONFIG +from frontends.gamespy.library.log.log_manager import GLOBAL_LOGGER +from frontends.gamespy.library.network.websocket_brocker import WebSocketBrocker +from frontends.gamespy.protocols.query_report.v2.applications.handlers import ClientMessageHandler +from frontends.gamespy.protocols.query_report.v2.contracts.requests import ClientMessageRequest +from types import MappingProxyType + +if TYPE_CHECKING: + from frontends.gamespy.protocols.query_report.applications.client import Client + + +class NatNegChannel: + """ + todo send data to the ip endpoint when receive data, not find client from pool to save memory + """ + broker: BrockerBase + pool: MappingProxyType[str, "Client"] + + def __init__(self, broker_cls: type[BrockerBase] = WebSocketBrocker) -> None: + self.broker = broker_cls( + "natneg", f"{CONFIG.backend.url}/QueryReport/Channel", self.recieve_message) + self.pool = MappingProxyType(Client.pool) + + def recieve_message(self, request: bytes): + message = ClientMessageRequest(request) + message.parse() + client = None + if message.target_ip_endpoint in self.pool: + client = self.pool[message.target_ip_endpoint] + + if client is None: + GLOBAL_LOGGER.warn(f"Client:{message.target_ip_address}:{ + message.target_port} not found, we ignore natneg message from SB: {message.server_browser_sender_id}") + return + + GLOBAL_LOGGER.info(f"Get client message from server browser: { + message.server_browser_sender_id} [{message.natneg_message}]") + handler = ClientMessageHandler(client, message) + handler.handle() diff --git a/src/frontends/gamespy/protocols/query_report/aggregates/peer_room_info.py b/src/frontends/gamespy/protocols/query_report/aggregates/peer_room_info.py new file mode 100644 index 000000000..6811cf9ba --- /dev/null +++ b/src/frontends/gamespy/protocols/query_report/aggregates/peer_room_info.py @@ -0,0 +1,23 @@ +from pydantic import BaseModel, Field + + +class PeerRoomInfo(BaseModel): + game_name: str + group_id: int = Field(..., alias='groupid') + room_name: str = Field(alias="hostname") + number_of_waiting: int = Field(default=0, alias="numwaiting") + max_waiting: int = Field(default=200, alias='maxwaiting') + number_of_servers: int = Field(default=0, alias="numservers") + number_of_players: int = Field(default=0, alias="numplayers") + max_players: int = Field(default=200, alias="maxplayers") + password: str = Field(default="", alias="password") + number_of_games: int = Field(default=0, alias="numgames") + number_of_playing: int = Field(default=0, alias="numplaying") + + def get_gamespy_dict(self) -> dict: + """ + return a immutable dict + """ + data = self.model_dump(mode="json") + del data["game_name"] + return data diff --git a/src/frontends/gamespy/protocols/query_report/applications/client.py b/src/frontends/gamespy/protocols/query_report/applications/client.py new file mode 100644 index 000000000..3000e26ab --- /dev/null +++ b/src/frontends/gamespy/protocols/query_report/applications/client.py @@ -0,0 +1,57 @@ +from frontends.gamespy.library.abstractions.client import ClientBase +from frontends.gamespy.library.abstractions.connections import ConnectionBase +from frontends.gamespy.library.configs import CONFIG, ServerConfig +from frontends.gamespy.library.log.log_manager import LogWriter +from frontends.gamespy.library.network.websocket_brocker import WebSocketBrocker + +# import servers.query_report.v1 + + +class Client(ClientBase): + pool: dict[str, "Client"] + is_log_raw: bool + """ + v1 protocol request is send with different packet, the \\final\\ tells whether request is finished + """ + + def __init__(self, connection: ConnectionBase, server_config: ServerConfig, logger: LogWriter): + super().__init__(connection, server_config, logger) + self.is_log_raw = True + + def _create_switcher(self, buffer: bytes): + from frontends.gamespy.protocols.query_report.v2.applications.switcher import Switcher as V2Switcher + from frontends.gamespy.protocols.query_report.v1.applications.switcher import Switcher as V1Switcher + assert isinstance(buffer, bytes) + # !! qr v1 doesn't actually need encryption because encryption isn't part of the main communication process. + if buffer[0] == ord("\\"): + return V1Switcher(self, buffer.decode()) + else: + return V2Switcher(self, buffer) + + def start_brocker(self): + self.brocker = WebSocketBrocker( + name=self.server_config.server_name, + url=f"{CONFIG.backend.url.replace('http', 'ws')}/GameSpy/Chat/ws", + call_back_func=self._process_brocker_message, + ) + self.brocker.subscribe() + + def stop_brocker(self): + assert self.brocker is not None + self.brocker.unsubscribe() + + def _process_brocker_message(self, message: str): + from frontends.gamespy.protocols.query_report.v2.contracts.requests import ClientMessageRequest + from frontends.gamespy.protocols.query_report.v2.applications.handlers import ClientMessageHandler + + # responsible for receive message and send out + # TODO: check whether exception here will cause brocker stop + try: + assert isinstance(message, str) + # deserialize str to object + request = ClientMessageRequest() + handler = ClientMessageHandler(self, request) + handler.handle() + except Exception as e: + # todo change to log and handle exception here + print(e) diff --git a/src/frontends/gamespy/protocols/query_report/applications/server_launcher.py b/src/frontends/gamespy/protocols/query_report/applications/server_launcher.py new file mode 100644 index 000000000..b99f3b9d5 --- /dev/null +++ b/src/frontends/gamespy/protocols/query_report/applications/server_launcher.py @@ -0,0 +1,21 @@ +from frontends.gamespy.library.abstractions.server_launcher import ServicesFactory, ServiceBase +from frontends.gamespy.library.network.udp_handler import UdpServer +from frontends.gamespy.protocols.query_report.applications.client import Client + + +class Service(ServiceBase): + natneg_channel: object + + def __init__(self) -> None: + super().__init__( + config_name="QueryReport", + client_cls=Client, + network_server_cls=UdpServer + ) + + +if __name__ == "__main__": + from frontends.gamespy.library.extentions.debug_helper import DebugHelper + qr = Service() + helper = DebugHelper("./frontends/", ServicesFactory([qr])) + helper.start() diff --git a/src/frontends/gamespy/protocols/query_report/v1/__init__.py b/src/frontends/gamespy/protocols/query_report/v1/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/gamespy/protocols/query_report/v1/abstractions/__init__.py b/src/frontends/gamespy/protocols/query_report/v1/abstractions/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/gamespy/protocols/query_report/v1/abstractions/contracts.py b/src/frontends/gamespy/protocols/query_report/v1/abstractions/contracts.py new file mode 100644 index 000000000..433d4ab28 --- /dev/null +++ b/src/frontends/gamespy/protocols/query_report/v1/abstractions/contracts.py @@ -0,0 +1,32 @@ +from enum import Enum +import frontends.gamespy.library.abstractions.contracts as lib + +from frontends.gamespy.library.extentions.gamespy_utils import convert_to_key_value + + +class RequestBase(lib.RequestBase): + raw_request: str + _request_dict: dict[str, str] + + def __init__(self, raw_request: str) -> None: + assert isinstance(raw_request, str) + super().__init__(raw_request) + self._request_dict = {} + + def parse(self) -> None: + self._request_dict = convert_to_key_value(self.raw_request) + if 'final' in self._request_dict: + del self._request_dict['final'] + self.command_name = list(self._request_dict.keys())[0] + + +class ResultBase(lib.ResultBase): + pass + + +class ResponseBase(lib.ResponseBase): + sending_buffer: str + + def __init__(self, result: ResultBase) -> None: + assert issubclass(type(result), ResultBase) + super().__init__(result) diff --git a/src/frontends/gamespy/protocols/query_report/v1/abstractions/handlers.py b/src/frontends/gamespy/protocols/query_report/v1/abstractions/handlers.py new file mode 100644 index 000000000..dae695ee1 --- /dev/null +++ b/src/frontends/gamespy/protocols/query_report/v1/abstractions/handlers.py @@ -0,0 +1,10 @@ +import frontends.gamespy.library.abstractions.handler as lib +from frontends.gamespy.protocols.query_report.v1.abstractions.contracts import RequestBase +from frontends.gamespy.protocols.query_report.applications.client import Client + + +class CmdHandlerBase(lib.CmdHandlerBase): + def __init__(self, client: Client, request: RequestBase) -> None: + assert issubclass(type(request), RequestBase) + assert isinstance(client, Client) + super().__init__(client, request) diff --git a/src/frontends/gamespy/protocols/query_report/v1/aggregates/enums.py b/src/frontends/gamespy/protocols/query_report/v1/aggregates/enums.py new file mode 100644 index 000000000..550cff4c5 --- /dev/null +++ b/src/frontends/gamespy/protocols/query_report/v1/aggregates/enums.py @@ -0,0 +1,12 @@ +from enum import Enum + + +class RequestType(Enum): + HEARTBEAT = "heartbeat" + HEARTBEAT_ACK = "gamename" + + +class ServerStatus(Enum): + START = 0 + CHANGED = 1 + SHUTDOWN = 2 diff --git a/src/frontends/gamespy/protocols/query_report/v1/applications/handlers.py b/src/frontends/gamespy/protocols/query_report/v1/applications/handlers.py new file mode 100644 index 000000000..a37aeb9ae --- /dev/null +++ b/src/frontends/gamespy/protocols/query_report/v1/applications/handlers.py @@ -0,0 +1,31 @@ +from frontends.gamespy.protocols.query_report.applications.client import Client +from frontends.gamespy.protocols.query_report.v1.abstractions.contracts import RequestBase +from frontends.gamespy.protocols.query_report.v1.abstractions.handlers import CmdHandlerBase +from frontends.gamespy.protocols.query_report.v1.contracts.requests import LegacyHeartbeatRequest, HeartbeatPreRequest +from frontends.gamespy.protocols.query_report.v1.contracts.responses import HeartbeatPreResponse +from frontends.gamespy.protocols.query_report.v1.contracts.results import HeartbeatPreResult + + +class HeartbeatPreHandler(CmdHandlerBase): + _request: HeartbeatPreRequest + _result: HeartbeatPreResult + _response: HeartbeatPreResponse + + def __init__(self, client: Client, request: RequestBase) -> None: + super().__init__(client, request) + self._is_fetching = False + self._is_uploading = False + + def _response_construct(self) -> None: + self._result = HeartbeatPreResult( + status=self._request.status, + game_name=self._request.game_name) + self._response = HeartbeatPreResponse(self._result) + + +class LegacyHeartbeatHandler(CmdHandlerBase): + _request: LegacyHeartbeatRequest + + def __init__(self, client: Client, request: RequestBase) -> None: + super().__init__(client, request) + self._is_fetching = False diff --git a/src/frontends/gamespy/protocols/query_report/v1/applications/switcher.py b/src/frontends/gamespy/protocols/query_report/v1/applications/switcher.py new file mode 100644 index 000000000..29910cfd3 --- /dev/null +++ b/src/frontends/gamespy/protocols/query_report/v1/applications/switcher.py @@ -0,0 +1,31 @@ + +from frontends.gamespy.library.abstractions.handler import CmdHandlerBase +from frontends.gamespy.library.abstractions.switcher import SwitcherBase +from frontends.gamespy.protocols.query_report.aggregates.exceptions import QRException +from frontends.gamespy.protocols.query_report.applications.client import Client +from frontends.gamespy.protocols.query_report.v1.aggregates.enums import RequestType +from frontends.gamespy.protocols.query_report.v1.applications.handlers import HeartbeatPreHandler, LegacyHeartbeatHandler +from frontends.gamespy.protocols.query_report.v1.contracts.requests import HeartbeatPreRequest, LegacyHeartbeatRequest + + +class Switcher(SwitcherBase): + _raw_request: str + _client: Client + + def _process_raw_request(self) -> None: + if len(self._raw_request) < 4: + raise QRException("Invalid request length") + if self._raw_request[0] != "\\": + raise QRException("Invalid queryreport v1 request") + name = self._raw_request.strip("\\").split("\\")[0] + if name not in RequestType: + self._client.log_debug( + f"Request: {name} is not a valid request.") + self._requests.append((RequestType(name), self._raw_request)) + + def _create_cmd_handlers(self, name: RequestType, raw_request: str) -> CmdHandlerBase | None: + match(name): + case RequestType.HEARTBEAT: + return HeartbeatPreHandler(self._client, HeartbeatPreRequest(raw_request)) + case RequestType.HEARTBEAT_ACK: + return LegacyHeartbeatHandler(self._client, LegacyHeartbeatRequest(raw_request)) diff --git a/src/frontends/gamespy/protocols/query_report/v1/contracts/requests.py b/src/frontends/gamespy/protocols/query_report/v1/contracts/requests.py new file mode 100644 index 000000000..b065e2b8b --- /dev/null +++ b/src/frontends/gamespy/protocols/query_report/v1/contracts/requests.py @@ -0,0 +1,66 @@ +from frontends.gamespy.protocols.query_report.aggregates.exceptions import QRException +from frontends.gamespy.protocols.query_report.aggregates.game_server_info import NESSESARY_KEYS +from frontends.gamespy.protocols.query_report.v1.abstractions.contracts import RequestBase +from frontends.gamespy.protocols.query_report.v1.aggregates.enums import ServerStatus + + +class HeartbeatPreRequest(RequestBase): + """ + heartbeat do not have final command + \\heartbeat\\26900\\gamename\\gmtest + """ + game_port: int + game_name: str + status: ServerStatus + + def parse(self) -> None: + super().parse() + if 'gamename' not in self._request_dict: + raise QRException("gamename is missing") + self.game_name = self._request_dict['gamename'] + if 'heartbeat' not in self._request_dict: + raise QRException("game port is missing") + self.game_port = int(self._request_dict['heartbeat']) + + if 'statechanged' in self._request_dict: + self.status = ServerStatus(int(self._request_dict['statechanged'])) + else: + self.status = ServerStatus.START + + +class LegacyHeartbeatRequest(RequestBase): + """ + heartbeat ack request is start with gamename: + \\gamename\\gmtest\\gamever\\2.00\\location\\1\\hostname\\GameMaster Arena Server\\hostport\\25000\\mapname\\gmtmap1\\gametype\\arena\\numplayers\\4\\maxplayers\\32\\gamemode\\openplaying\\timelimit\\40\\fraglimit\\0\\teamplay\\1\\rankedserver\\1\\player_0\\Joe Player\\frags_0\\25\\deaths_0\\6\\skill_0\\272\\ping_0\\119\\team_0\\\\player_1\\L33t 0n3\\frags_1\\12\\deaths_1\\24\\skill_1\\136\\ping_1\\98\\team_1\\\\player_2\\Raptor\\frags_2\\11\\deaths_2\\26\\skill_2\\44\\ping_2\\445\\team_2\\Blue\\player_3\\Gr81\\frags_3\\23\\deaths_3\\18\\skill_3\\173\\ping_3\\129\\team_3\\Red\\final\\\\queryid\\2.1 + """ + query_id: str + data: dict[str, str] + game_name: str + group_id: int | None + + def parse(self) -> None: + super().parse() + if "queryid" not in self._request_dict: + raise QRException("queryid is missing") + self.query_id = self._request_dict['queryid'] + for key in NESSESARY_KEYS: + if key not in self._request_dict: + raise QRException(f"key:<{key}> is missing") + # currently we put basic, info, rules, players, teams into data + self.data = self._request_dict.copy() + self.game_name = self.data['gamename'] + if "groupid" in self.data: + self.group_id = int(self.data["groupid"]) + else: + self.group_id = None + +if __name__ == "__main__": + heartbeat = '\\heartbeat\\26900\\gamename\\gmtest' + basic = '\\gamename\\gmtest\\gamever\\2.00\\location\\1\\queryid\\2.1' + info = '\\hostname\\GameMaster Arena Server\\hostport\\25000\\mapname\\gmtmap1\\gametype\\arena\\numplayers\\5\\maxplayers\\32\\gamemode\\openplaying\\queryid\\2.2' + rules = '\\timelimit\\40\\fraglimit\\0\\teamplay\\1\\rankedserver\\1\\queryid\\2.3' + players = '\\player_0\\Joe Player\\frags_0\\3\\deaths_0\\6\\skill_0\\225\\ping_0\\137\\team_0\\Blue\\player_1\\L33t 0n3\\frags_1\\26\\deaths_1\\18\\skill_1\\829\\ping_1\\247\\team_1\\\\player_2\\Raptor\\frags_2\\30\\deaths_2\\17\\skill_2\\888\\ping_2\\233\\team_2\\Red\\player_3\\Gr81\\frags_3\\23\\deaths_3\\19\\skill_3\\415\\ping_3\\409\\team_3\\\\player_4\\Flubber\\frags_4\\23\\deaths_4\\31\\skill_4\\837\\ping_4\\443\\team_4\\\\final\\\\queryid\\2.4' + + status = "\\gamename\\gmtest\\gamever\\2.00\\location\\1\\hostname\\GameMaster Arena Server\\hostport\\25000\\mapname\\gmtmap1\\gametype\\arena\\numplayers\\4\\maxplayers\\32\\gamemode\\openplaying\\timelimit\\40\\fraglimit\\0\\teamplay\\1\\rankedserver\\1\\player_0\\Joe Player\\frags_0\\25\\deaths_0\\6\\skill_0\\272\\ping_0\\119\\team_0\\\\player_1\\L33t 0n3\\frags_1\\12\\deaths_1\\24\\skill_1\\136\\ping_1\\98\\team_1\\\\player_2\\Raptor\\frags_2\\11\\deaths_2\\26\\skill_2\\44\\ping_2\\445\\team_2\\Blue\\player_3\\Gr81\\frags_3\\23\\deaths_3\\18\\skill_3\\173\\ping_3\\129\\team_3\\Red\\final\\\\queryid\\2.1" + req = LegacyHeartbeatRequest(status) + req.parse() diff --git a/src/frontends/gamespy/protocols/query_report/v1/contracts/responses.py b/src/frontends/gamespy/protocols/query_report/v1/contracts/responses.py new file mode 100644 index 000000000..728160bcb --- /dev/null +++ b/src/frontends/gamespy/protocols/query_report/v1/contracts/responses.py @@ -0,0 +1,10 @@ +from frontends.gamespy.protocols.query_report.v1.abstractions.contracts import ResponseBase +from frontends.gamespy.protocols.query_report.v1.aggregates.enums import ServerStatus +from frontends.gamespy.protocols.query_report.v1.contracts.results import HeartbeatPreResult + + +class HeartbeatPreResponse(ResponseBase): + _result: HeartbeatPreResult + + def build(self) -> None: + self.sending_buffer = "\\status\\" diff --git a/src/frontends/gamespy/protocols/query_report/v1/contracts/results.py b/src/frontends/gamespy/protocols/query_report/v1/contracts/results.py new file mode 100644 index 000000000..28915ed86 --- /dev/null +++ b/src/frontends/gamespy/protocols/query_report/v1/contracts/results.py @@ -0,0 +1,7 @@ +from frontends.gamespy.protocols.query_report.v1.abstractions.contracts import ResultBase +from frontends.gamespy.protocols.query_report.v1.aggregates.enums import ServerStatus + + +class HeartbeatPreResult(ResultBase): + status: ServerStatus + game_name: str diff --git a/src/frontends/gamespy/protocols/query_report/v2/abstractions/contracts.py b/src/frontends/gamespy/protocols/query_report/v2/abstractions/contracts.py new file mode 100644 index 000000000..dbc032c04 --- /dev/null +++ b/src/frontends/gamespy/protocols/query_report/v2/abstractions/contracts.py @@ -0,0 +1,39 @@ +from frontends.gamespy.protocols.query_report.v2.aggregates.enums import PacketType +from frontends.gamespy.protocols.query_report.aggregates.exceptions import QRException +from frontends.gamespy.protocols.query_report.v2.aggregates.enums import RequestType +import frontends.gamespy.library.abstractions.contracts as lib + +MAGIC_DATA = [0xFE, 0xFD] + + +class RequestBase(lib.RequestBase): + instant_key: str + command_name: RequestType + raw_request: bytes + + def __init__(self, raw_request: bytes) -> None: + assert isinstance(raw_request, bytes) + super().__init__(raw_request) + + def parse(self): + if len(self.raw_request) < 3: + raise QRException("request length not valid") + self.command_name = RequestType(self.raw_request[0]) + self.instant_key = str(int.from_bytes(self.raw_request[1:5])) + + +class ResultBase(lib.ResultBase): + packet_type: PacketType + command_name: RequestType + instant_key: str + +class ResponseBase(lib.ResponseBase): + _result: ResultBase + sending_buffer: bytes + + def build(self) -> None: + data = bytearray() + data.extend(MAGIC_DATA) + data.append(self._result.command_name.value) + data.extend(int(self._result.instant_key).to_bytes(4)) + self.sending_buffer = bytes(data) diff --git a/src/frontends/gamespy/protocols/query_report/v2/abstractions/handlers.py b/src/frontends/gamespy/protocols/query_report/v2/abstractions/handlers.py new file mode 100644 index 000000000..ba7bc9eb8 --- /dev/null +++ b/src/frontends/gamespy/protocols/query_report/v2/abstractions/handlers.py @@ -0,0 +1,10 @@ +from frontends.gamespy.library.abstractions.handler import CmdHandlerBase as CHB +from frontends.gamespy.protocols.query_report.v2.abstractions.contracts import RequestBase +from frontends.gamespy.protocols.query_report.applications.client import Client + + +class CmdHandlerBase(CHB): + def __init__(self, client: Client, request: RequestBase) -> None: + assert issubclass(type(request), RequestBase) + assert isinstance(client, Client) + super().__init__(client, request) diff --git a/src/frontends/gamespy/protocols/query_report/v2/aggregates/enums.py b/src/frontends/gamespy/protocols/query_report/v2/aggregates/enums.py new file mode 100644 index 000000000..6cb023ac5 --- /dev/null +++ b/src/frontends/gamespy/protocols/query_report/v2/aggregates/enums.py @@ -0,0 +1,58 @@ +from enum import Enum + + +class RequestType(Enum): + CHALLENGE = 0x01 + HEARTBEAT = 0x03 + CLIENT_MESSAGE = 0x06 + CLIENT_MESSAGE_ACK = 0x07 + ADD_ERROR = 0x04 + ECHO = 0x02 + KEEP_ALIVE = 0x08 + AVALIABLE_CHECK = 0x09 + + +class ResponseType(Enum): + QUERY = 0x00 + ECHO = 0x02 + ADD_ERROR = 0x04 + CLIENT_MESSAGE = 0x06 + REQUIRE_IP_VERIFY = 0x09 + CLIENT_REGISTERED = 0x0A + + +class PacketType(Enum): + QUERY = 0x00 + CHALLENGE = 0x01 + ECHO = 0x02 + ADD_ERROR = 0x04 + CLIENT_MESSAGE = 0x06 + REQUIRE_IP_VERIFY = 0x09 + CLIENT_REGISTERED = 0x0A + HEARTBEAT = 0x03 + ECHO_RESPONSE = 0x05 + CLIENT_MESSAGE_ACK = 0x07 + KEEP_ALIVE = 0x08 + AVALIABLE_CHECK = 0x09 + + +class QRStateChange(Enum): + NORMAL_HEARTBEAT = 0 + GAME_MODE_CHANGE = 1 + SERVER_SHUTDOWN = 2 + CANNOT_RECIEVE_CHALLENGE = 3 + + +class HeartBeatReportType(Enum): + SERVER_TEAM_PLAYER_DATA = 1 + SERVER_PLAYER_DATA = 2 + SERVER_DATA = 3 + + + + +class ServerAvailability(Enum): + AVAILABLE = 0 + WAITING = 1 + PERMANENT_UNAVAILABLE = 2 + TEMPORARILY_UNAVAILABLE = 3 diff --git a/src/frontends/gamespy/protocols/query_report/v2/applications/handlers.py b/src/frontends/gamespy/protocols/query_report/v2/applications/handlers.py new file mode 100644 index 000000000..7655f5942 --- /dev/null +++ b/src/frontends/gamespy/protocols/query_report/v2/applications/handlers.py @@ -0,0 +1,110 @@ +from typing import final +from frontends.gamespy.protocols.query_report.applications.client import Client +from frontends.gamespy.protocols.query_report.v2.abstractions.handlers import ( + CmdHandlerBase, +) +from frontends.gamespy.protocols.query_report.v2.contracts.requests import ( + AvaliableRequest, + ChallengeRequest, + ClientMessageAckRequest, + ClientMessageRequest, + EchoRequest, + HeartbeatRequest, + KeepAliveRequest, +) +from frontends.gamespy.protocols.query_report.v2.contracts.responses import ( + AvailableResponse, + ChallengeResponse, + ClientMessageResponse, + HeartbeatResponse, +) +from frontends.gamespy.protocols.query_report.v2.contracts.results import ( + AvailableResult, + ChallengeResult, + ClientMessageResult, + HeartbeatResult, +) + + +@final +class AvailableHandler(CmdHandlerBase): + _request: AvaliableRequest + + def __init__(self, client: Client, request: AvaliableRequest) -> None: + assert isinstance(request, AvaliableRequest) + super().__init__(client, request) + + + def _response_construct(self): + self._result = AvailableResult( + command_name=self._request.command_name, + instant_key=self._request.instant_key) + self._response = AvailableResponse(self._result) + + +@final +class ChallengeHanler(CmdHandlerBase): + _request: ChallengeRequest + _result: ChallengeResult + + def __init__(self, client: Client, request: ChallengeRequest) -> None: + assert isinstance(request, ChallengeRequest) + super().__init__(client, request) + self._result_cls = ChallengeResult + self._response_cls = ChallengeResponse + + +@final +class ClientMessageAckHandler(CmdHandlerBase): + def __init__(self, client: Client, request: ClientMessageAckRequest) -> None: + assert isinstance(request, ClientMessageAckRequest) + super().__init__(client, request) + + + def _response_construct(self): + self._client.log_info("Get client message ack") + + +@final +class ClientMessageHandler(CmdHandlerBase): + + def __init__(self, client: Client, request: ClientMessageRequest) -> None: + assert isinstance(request, ClientMessageRequest) + super().__init__(client, request) + self._result_cls = ClientMessageResult + self._response_cls = ClientMessageResponse + + +@final +class EchoHandler(CmdHandlerBase): + def __init__(self, client: Client, request: EchoRequest) -> None: + assert isinstance(request, EchoRequest) + super().__init__(client, request) + + +@final +class HeartbeatHandler(CmdHandlerBase): + _request: HeartbeatRequest + + def __init__(self, client: Client, request: HeartbeatRequest) -> None: + assert isinstance(request, HeartbeatRequest) + super().__init__(client, request) + + + def _response_construct(self) -> None: + self._result = HeartbeatResult( + remote_ip=self._client.connection.remote_ip, + remote_port=self._client.connection.remote_port, + instant_key=self._request.instant_key, + command_name=self._request.command_name + ) + self._response = HeartbeatResponse(self._result) + + +@final +class KeepAliveHandler(CmdHandlerBase): + + def __init__(self, client: Client, request: KeepAliveRequest) -> None: + assert isinstance(request, KeepAliveRequest) + super().__init__(client, request) + diff --git a/src/frontends/gamespy/protocols/query_report/v2/applications/switcher.py b/src/frontends/gamespy/protocols/query_report/v2/applications/switcher.py new file mode 100644 index 000000000..9e0bd5235 --- /dev/null +++ b/src/frontends/gamespy/protocols/query_report/v2/applications/switcher.py @@ -0,0 +1,58 @@ +from typing import TYPE_CHECKING, cast +from frontends.gamespy.library.abstractions.switcher import SwitcherBase +from frontends.gamespy.protocols.query_report.aggregates.exceptions import QRException +from frontends.gamespy.protocols.query_report.applications.client import Client +from frontends.gamespy.protocols.query_report.v2.abstractions.handlers import CmdHandlerBase + +from frontends.gamespy.protocols.query_report.v2.contracts.requests import ( + AvaliableRequest, + ChallengeRequest, + ClientMessageAckRequest, + EchoRequest, + HeartbeatRequest, + KeepAliveRequest, +) +from frontends.gamespy.protocols.query_report.v2.aggregates.enums import RequestType +from frontends.gamespy.protocols.query_report.v2.applications.handlers import ( + AvailableHandler, + ChallengeHanler, + ClientMessageAckHandler, + EchoHandler, + HeartbeatHandler, + KeepAliveHandler, +) + + +class Switcher(SwitcherBase): + _raw_request: bytes + + def _process_raw_request(self) -> None: + if len(self._raw_request) < 4: + raise QRException("Invalid request") + name = self._raw_request[0] + if name not in RequestType: + self._client.log_debug( + f"Request: {name} is not a valid request.") + return + raw_request = self._raw_request + self._requests.append((RequestType(name), raw_request)) + + def _create_cmd_handlers(self, name: RequestType, raw_request: bytes) -> CmdHandlerBase | None: + assert isinstance(name, RequestType) + if TYPE_CHECKING: + self._client = cast(Client, self._client) + match name: + case RequestType.HEARTBEAT: + return HeartbeatHandler(self._client, HeartbeatRequest(raw_request)) + case RequestType.CHALLENGE: + return ChallengeHanler(self._client, ChallengeRequest(raw_request)) + case RequestType.AVALIABLE_CHECK: + return AvailableHandler(self._client, AvaliableRequest(raw_request)) + case RequestType.CLIENT_MESSAGE_ACK: + return ClientMessageAckHandler(self._client, ClientMessageAckRequest(raw_request)) + case RequestType.ECHO: + return EchoHandler(self._client, EchoRequest(raw_request)) + case RequestType.KEEP_ALIVE: + return KeepAliveHandler(self._client, KeepAliveRequest(raw_request)) + case _: + return None diff --git a/src/frontends/gamespy/protocols/query_report/v2/contracts/requests.py b/src/frontends/gamespy/protocols/query_report/v2/contracts/requests.py new file mode 100644 index 000000000..bbda10bb5 --- /dev/null +++ b/src/frontends/gamespy/protocols/query_report/v2/contracts/requests.py @@ -0,0 +1,197 @@ + +from uuid import UUID +from frontends.gamespy.library.extentions.encoding import get_string +from frontends.gamespy.protocols.query_report.aggregates.enums import GameServerStatus +from frontends.gamespy.protocols.query_report.aggregates.exceptions import QRException +from frontends.gamespy.protocols.query_report.v2.abstractions.contracts import RequestBase + + +PREFIX = bytes([0x09, 0x00, 0x00, 0x00, 0x00]) +POSTFIX = bytes([0x00]) + + +class AvaliableRequest(RequestBase): + + def parse(self): + super().parse() + + if self.raw_request[:len(PREFIX)] != PREFIX: + raise QRException("Avaliable request prefix is invalid.") + # postfix check + if self.raw_request[len(self.raw_request)-1].to_bytes() != POSTFIX: + raise QRException("Avaliable request postfix is invalid.") + + +class ChallengeRequest(RequestBase): + pass + + +class ClientMessageAckRequest(RequestBase): + pass + + +class ClientMessageRequest(RequestBase): + server_browser_sender_id: UUID + natneg_message: bytes + target_ip_address: str + target_port: int + message_key: int + + @property + def cookie(self) -> int: + return int.from_bytes(self.natneg_message[6:10], "little") + + @property + def target_ip_endpoint(self) -> str: + return f"{self.target_ip_address}:{self.target_port}" + + def __init__(self, raw_request: bytes | None = None) -> None: + if raw_request is not None: + super().__init__(raw_request) + + +class HeartbeatRequest(RequestBase): + data: dict[str, str] + status: GameServerStatus + group_id: int | None + game_name: str + + def parse(self): + super().parse() + player_pos, team_pos = 0, 0 + player_length, team_length = 0, 0 + self.data_partition = get_string(self.raw_request[5:]) + + game_key_val = self.data_partition.split("\x00") + index_gn = game_key_val.index("gamename") + self.game_name = game_key_val[index_gn+1] + + try: + player_pos = self.data_partition.index("player_\0", 0) + except ValueError: + player_pos = -1 + + try: + team_pos = self.data_partition.index("team_t\0", 0) + except ValueError: + team_pos = -1 + + if player_pos != -1 and team_pos != -1: + player_length = team_pos - player_pos + team_length = len(self.data_partition) - team_pos + + server_data_str = self.data_partition[: player_pos - 4] + self.parse_server_data(server_data_str) + + player_data_str = self.data_partition[ + player_pos - 1: player_pos - 1 + player_length - 2 + ] + self.parse_player_data(player_data_str) + + team_data_str = self.data_partition[ + team_pos - 1: team_pos - 1 + team_length + ] + self.parse_team_data(team_data_str) + + elif player_pos != -1: + player_length = len(self.data_partition) - player_pos + + server_data_str = self.data_partition[: player_pos - 4] + self.parse_server_data(server_data_str) + + player_data_str = self.data_partition[player_pos - 1:] + self.parse_player_data(player_data_str) + + elif player_pos == -1 and team_pos == -1: + server_data_str = self.data_partition + self.parse_server_data(server_data_str) + + else: + raise QRException("HeartBeat request is invalid.") + + def parse_server_data(self, server_data_str: str): + self.data = {} + key_value_array = server_data_str.split("\0") + + for i in range(0, len(key_value_array), 2): + if i + 2 > len(key_value_array): + break + + temp_key = key_value_array[i] + temp_value = key_value_array[i + 1] + + if temp_key in self.data: + self.data[temp_key] = temp_value + else: + self.data[temp_key] = temp_value + + if "statechanged" not in self.data: + self.status = GameServerStatus.NORMAL + else: + self.status = GameServerStatus( + int(self.data["statechanged"])) + + if "groupid" in self.data: + self.group_id = int(self.data["groupid"]) + else: + self.group_id = None + + def parse_player_data(self, player_data_str: str): + player_count = int.from_bytes(player_data_str[0].encode()) + player_data_str = player_data_str[1:] + + index_of_key = player_data_str.index("\0\0", 0) + key_str = player_data_str[:index_of_key] + keys = key_str.split("\0") + + values_str = player_data_str[index_of_key + 2:] + values = values_str.split("\0") + + key_value = {} + for player_index in range(player_count): + + for key_index in range(len(keys)): + temp_key = keys[key_index] + str(player_index) + temp_value = values[player_index * len(keys) + key_index] + + if temp_key in key_value: + key_value[temp_key] = temp_value + else: + key_value[temp_key] = temp_value + + for key, value in key_value.items(): + self.data[key] = value + + def parse_team_data(self, team_data_str: str): + team_count = int.from_bytes(team_data_str[0].encode()) + team_data_str = team_data_str[1:] + + end_key_index = team_data_str.index("\0\0", 0) + key_str = team_data_str[:end_key_index] + keys = key_str.split("\0") + + value_str = team_data_str[end_key_index + 2:] + values = value_str.split("\0") + + key_value = {} + for team_index in range(team_count): + + for key_index in range(len(keys)): + temp_key = keys[key_index] + str(team_index) + temp_value = values[team_index * len(keys) + key_index] + + if temp_key in key_value: + key_value[temp_key] = temp_value + else: + key_value[temp_key] = temp_value + + for key, value in key_value.items(): + self.data[key] = value + + +class EchoRequest(RequestBase): + pass + + +class KeepAliveRequest(RequestBase): + pass diff --git a/src/frontends/gamespy/protocols/query_report/v2/contracts/responses.py b/src/frontends/gamespy/protocols/query_report/v2/contracts/responses.py new file mode 100644 index 000000000..f79b06799 --- /dev/null +++ b/src/frontends/gamespy/protocols/query_report/v2/contracts/responses.py @@ -0,0 +1,91 @@ +from frontends.gamespy.library.extentions.encoding import get_bytes +from frontends.gamespy.protocols.query_report.v2.abstractions.contracts import ResponseBase +from frontends.gamespy.protocols.query_report.v2.contracts.requests import ( + AvaliableRequest, + ChallengeRequest, + ClientMessageRequest, + HeartbeatRequest, + KeepAliveRequest +) +from frontends.gamespy.protocols.query_report.v2.contracts.results import ( + AvailableResult, + ChallengeResult, + ClientMessageResult, + HeartbeatResult, +) +from frontends.gamespy.protocols.query_report.v2.aggregates.enums import ServerAvailability +from frontends.gamespy.library.extentions.bytes_extentions import ip_to_4_bytes, port_to_2_bytes + +RESPONSE_PREFIX = bytes([0xFE, 0xFD, 0x09, 0x00, 0x00, 0x00]) + + +class AvailableResponse(ResponseBase): + def __init__(self, result: AvailableResult) -> None: + assert isinstance(result, AvailableResult) + super().__init__(result) + + def build(self): + data = bytearray() + data.extend(RESPONSE_PREFIX) + data.append(ServerAvailability.AVAILABLE.value) + self.sending_buffer = bytes(data) + + +MESSAGE = "UniSpy echo!" + + +class ChallengeResponse(ResponseBase): + def __init__(self, result: ChallengeResult) -> None: + assert isinstance(result, ChallengeResult) + super().__init__( result) + + def build(self) -> None: + super().build() + data = bytearray() + data.extend(self.sending_buffer) + data.extend(get_bytes(MESSAGE)) + self.sending_buffer = bytes(data) + + +class ClientMessageResponse(ResponseBase): + _result: ClientMessageResult + + def __init__(self, result: ClientMessageResult) -> None: + assert isinstance(result, ClientMessageResult) + super().__init__(result) + + def build(self): + super().build() + data = bytearray() + data.extend(self.sending_buffer) + data.extend(self._result.message_key.to_bytes(4, byteorder="little")) + data.extend(self._result.natneg_message) + self.sending_buffer = bytes(data) + + +CHALLENGE = bytes([0x54, 0x54, 0x54, 0x00, 0x00]) +SPLITER = bytes([0x00, 0x00, 0x00, 0x00]) + + +class HeartbeatResponse(ResponseBase): + _result: HeartbeatResult + + def __init__(self, result: HeartbeatResult) -> None: + assert isinstance(result, HeartbeatResult) + super().__init__(result) + + def build(self) -> None: + super().build() + data = bytearray() + data.extend(self.sending_buffer) + data.extend(CHALLENGE) + data.extend(ip_to_4_bytes(self._result.remote_ip)) + data.extend(SPLITER) + data.extend(port_to_2_bytes(self._result.remote_port)) + self.sending_buffer = bytes(data) + + +# class KeepAliveResponse(ResponseBase): +# def __init__(self, result:KeepAliveResponse) -> None: +# assert isinstance(request, KeepAliveRequest) +# super().__init__(request, None) diff --git a/src/frontends/gamespy/protocols/query_report/v2/contracts/results.py b/src/frontends/gamespy/protocols/query_report/v2/contracts/results.py new file mode 100644 index 000000000..229a4d91e --- /dev/null +++ b/src/frontends/gamespy/protocols/query_report/v2/contracts/results.py @@ -0,0 +1,36 @@ +from typing import final +from frontends.gamespy.protocols.query_report.v2.abstractions.contracts import ResultBase +from frontends.gamespy.protocols.query_report.v2.aggregates.enums import PacketType + + +@final +class AvailableResult(ResultBase): + packet_type: PacketType = PacketType.AVALIABLE_CHECK + + +@final +class ChallengeResult(ResultBase): + packet_type: PacketType = PacketType.CHALLENGE + + +@final +class ClientMessageResult(ResultBase): + natneg_message: bytes + message_key: int + packet_type: PacketType = PacketType.CLIENT_MESSAGE + + +@final +class EchoResult(ResultBase): + info: dict + packet_type: PacketType = PacketType.ECHO + + +@final +class HeartbeatResult(ResultBase): + """ + this result is replied in unispy server + """ + packet_type: PacketType = PacketType.HEARTBEAT + remote_ip: str + remote_port: int diff --git a/src/frontends/gamespy/protocols/server_browser/__init__.py b/src/frontends/gamespy/protocols/server_browser/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/gamespy/protocols/server_browser/aggregates/exceptions.py b/src/frontends/gamespy/protocols/server_browser/aggregates/exceptions.py new file mode 100644 index 000000000..2d20e15e9 --- /dev/null +++ b/src/frontends/gamespy/protocols/server_browser/aggregates/exceptions.py @@ -0,0 +1,6 @@ +from frontends.gamespy.library.exceptions.general import UniSpyException + + +class ServerBrowserException(UniSpyException): + def __init__(self, message: str) -> None: + super().__init__(message) diff --git a/src/frontends/gamespy/protocols/server_browser/applications/server_launcher.py b/src/frontends/gamespy/protocols/server_browser/applications/server_launcher.py new file mode 100644 index 000000000..b21f3e846 --- /dev/null +++ b/src/frontends/gamespy/protocols/server_browser/applications/server_launcher.py @@ -0,0 +1,18 @@ +from frontends.gamespy.library.abstractions.server_launcher import ServicesFactory, ServiceBase +from frontends.gamespy.library.network.tcp_handler import TcpServer +from frontends.gamespy.protocols.server_browser.v2.applications.client import Client + + +class Service(ServiceBase): + def __init__(self) -> None: + super().__init__( + config_name="ServerBrowserV2", client_cls=Client, network_server_cls=TcpServer + ) + + +if __name__ == "__main__": + from frontends.gamespy.library.extentions.debug_helper import DebugHelper + sb2 = Service() + # todo: add v1 server here + helper = DebugHelper("./frontends/", ServicesFactory([sb2])) + helper.start() diff --git a/src/frontends/gamespy/protocols/server_browser/v2/abstractions/__init__.py b/src/frontends/gamespy/protocols/server_browser/v2/abstractions/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/gamespy/protocols/server_browser/v2/abstractions/contracts.py b/src/frontends/gamespy/protocols/server_browser/v2/abstractions/contracts.py new file mode 100644 index 000000000..4150106fa --- /dev/null +++ b/src/frontends/gamespy/protocols/server_browser/v2/abstractions/contracts.py @@ -0,0 +1,147 @@ +from socket import inet_ntoa +import frontends.gamespy.library.abstractions.contracts as lib + +from frontends.gamespy.library.extentions.bytes_extentions import ip_to_4_bytes +from frontends.gamespy.library.extentions.encoding import get_bytes +from frontends.gamespy.protocols.query_report.aggregates.game_server_info import ( + GameServerInfo, +) +from frontends.gamespy.protocols.server_browser.v2.aggregations.encryption import ( + SERVER_CHALLENGE, +) +from frontends.gamespy.protocols.server_browser.v2.aggregations.string_flags import ( + STRING_SPLITER, +) +from frontends.gamespy.protocols.server_browser.v2.aggregations.enums import ( + DataKeyType, + GameServerFlags, + RequestType, + ServerListUpdateOption, +) + +QUERY_REPORT_DEFAULT_PORT: int = int(6500) + + +class RequestBase(lib.RequestBase): + request_length: int + raw_request: bytes + command_name: RequestType + + def __init__(self, raw_request: bytes) -> None: + assert isinstance(raw_request, bytes) + super().__init__(raw_request) + + def parse(self) -> None: + self.request_length = int.from_bytes( + self.raw_request[:2], byteorder="little") + self.command_name = RequestType(self.raw_request[2]) + + +class ResultBase(lib.ResultBase): + pass + + +class ResponseBase(lib.ResponseBase): + _result: ResultBase + sending_buffer: bytes + + def __init__(self, result: ResultBase) -> None: + assert issubclass(type(result), ResultBase) + super().__init__(result) + + +class ServerListUpdateOptionRequestBase(RequestBase): + request_version: int + protocol_version: int + encoding_version: int + game_version: int + query_options: int + dev_game_name: str + game_name: str + client_challenge: str + update_option: ServerListUpdateOption + keys: list[str] + filter: str | None + source_ip: str + max_servers: int + + def __init__(self, raw_request: bytes): + assert isinstance(raw_request, bytes) + super().__init__(raw_request) + self.filter = None + + +class ServerListUpdateOptionResultBase(ResultBase): + client_remote_ip: str + flag: GameServerFlags + game_secret_key: str + keys: list[str] + + +class ServerListUpdateOptionResponseBase(ResponseBase): + _result: ServerListUpdateOptionResultBase + _buffer: bytearray + + def __init__( + self, + result: ServerListUpdateOptionResultBase, + ) -> None: + assert issubclass(type(result), ServerListUpdateOptionResultBase) + super().__init__(result) + self._buffer = bytearray() + + def build(self) -> None: + crypt_header = self.build_crypt_header() + self._buffer.extend(crypt_header) + self._buffer.extend( + ip_to_4_bytes(self._result.client_remote_ip)) + self._buffer.extend( + QUERY_REPORT_DEFAULT_PORT.to_bytes(2)) + assert len(self._buffer) == 20 + + def build_crypt_header(self) -> bytearray: + # cryptHeader have 14 bytes, when we encrypt data we need skip the first 14 bytes + crypt_header = bytearray() + crypt_header.append(2 ^ 0xEC) + crypt_header.extend([0, 0]) # message length? + crypt_header.append(len(SERVER_CHALLENGE) ^ 0xEA) + crypt_header.extend(get_bytes(SERVER_CHALLENGE)) + assert len(crypt_header) == 14 + return crypt_header + + def build_server_keys(self) -> None: + # we add the total number of the requested keys + self._buffer.append(len(self._result.keys)) + # then we add the keys + for key in self._result.keys: + self._buffer.append(DataKeyType.STRING) + self._buffer.extend(get_bytes(key)) + self._buffer.append(STRING_SPLITER) + + def build_unique_value(self): + self._buffer.append(0) + + +class AdHocResultBase(ResultBase): + game_server_info: GameServerInfo + + +class AdHocRequestBase(RequestBase): + game_server_public_ip: str + game_server_public_port: int + + def parse(self) -> None: + super().parse() + self.game_server_public_ip = inet_ntoa(self.raw_request[3:7]) + self.game_server_public_port = int.from_bytes( + self.raw_request[7:9], byteorder="big" + ) + + +class AdHocResponseBase(ResponseBase): + _result: AdHocResultBase + _buffer: bytearray + + def __init__(self, result: ResultBase) -> None: + super().__init__(result) + self._buffer = bytearray() diff --git a/src/frontends/gamespy/protocols/server_browser/v2/abstractions/handlers.py b/src/frontends/gamespy/protocols/server_browser/v2/abstractions/handlers.py new file mode 100644 index 000000000..cef5a9f4f --- /dev/null +++ b/src/frontends/gamespy/protocols/server_browser/v2/abstractions/handlers.py @@ -0,0 +1,43 @@ +from frontends.gamespy.library.abstractions.handler import CmdHandlerBase as CMB + +from frontends.gamespy.protocols.server_browser.v2.abstractions.contracts import ( + ServerListUpdateOptionRequestBase, + ServerListUpdateOptionResponseBase, + ServerListUpdateOptionResultBase, +) +from frontends.gamespy.protocols.server_browser.v2.aggregations.encryption import EnctypeX +from frontends.gamespy.protocols.server_browser.v2.applications.client import Client +from frontends.gamespy.protocols.server_browser.v2.abstractions.contracts import ( + RequestBase, + ResultBase, + ResponseBase, +) + + +class CmdHandlerBase(CMB): + _client: Client + _request: RequestBase + _result: ResultBase + _response: ResponseBase + + def __init__(self, client: Client, request: RequestBase) -> None: + assert isinstance(client, Client) + assert issubclass(type(request), RequestBase) + super().__init__(client, request) + + +class ServerListUpdateOptionHandlerBase(CmdHandlerBase): + _request: ServerListUpdateOptionRequestBase + _result: ServerListUpdateOptionResultBase + _response: ServerListUpdateOptionResponseBase + + def _data_operate(self) -> None: + # query game secret key + super()._data_operate() + self._client.info.client_challenge = self._request.client_challenge + self._client.info.game_secret_key = self._result.game_secret_key + # use secret key to construct _client.crypto + self._client.crypto = EnctypeX( + self._client.info.game_secret_key, self._client.info.client_challenge + ) + diff --git a/src/frontends/gamespy/protocols/server_browser/v2/aggregations/encryption.py b/src/frontends/gamespy/protocols/server_browser/v2/aggregations/encryption.py new file mode 100644 index 000000000..e71bbc865 --- /dev/null +++ b/src/frontends/gamespy/protocols/server_browser/v2/aggregations/encryption.py @@ -0,0 +1,158 @@ +from frontends.gamespy.library.abstractions.enctypt_base import Byte, EncryptBase + +SERVER_CHALLENGE = "0000000000" + + +class EncryptionParameters: + register: list[Byte] + index_0: Byte + index_1: Byte + index_2: Byte + index_3: Byte + index_4: Byte + + def __init__(self): + self.register = [Byte(i) for i in range(256)] + self.index_0 = Byte(0) + self.index_1 = Byte(0) + self.index_2 = Byte(0) + self.index_3 = Byte(0) + self.index_4 = Byte(0) + + +def clamp(value: int) -> int: + return value % 256 + + +class EnctypeX(EncryptBase): + _enc_params: EncryptionParameters + _clientChallenge: list[Byte] + _serverChallenge: list[Byte] + _secretKey: list[Byte] + + def __init__(self, secretKey: str, clientChallenge: str): + assert isinstance(secretKey, str) + assert isinstance(clientChallenge, str) + self._enc_params = EncryptionParameters() + self._clientChallenge = Byte.from_bytes( + clientChallenge.encode("ascii")) + self._serverChallenge = Byte.from_bytes( + SERVER_CHALLENGE.encode("ascii")) + self._secretKey = Byte.from_bytes(secretKey.encode("ascii")) + self.init_encryption_algorithm() + + def init_encryption_algorithm(self): + if len(self._clientChallenge) != 8: + raise ValueError("Client challenge length not valid!") + + for i in range(len(self._serverChallenge)): + temp_index_0 = Byte( + i) * self._secretKey[i % len(self._secretKey)] % Byte(8) + temp_index1 = Byte(i % 8) + bitwise_result = self._clientChallenge[temp_index1.value] ^ self._serverChallenge[i] + self._clientChallenge[temp_index_0.value] ^= bitwise_result + + self.init_encryption_parameters() + + def init_encryption_parameters(self): + if len(self._clientChallenge) < 1: + self.non_challenge_mapping_init() + return + + to_swap = Byte(0) + key_position = Byte(0) + random_sum = Byte(0) + for i in range(255, 0, -1): + random_sum, key_position, to_swap = self.index_position_generation( + Byte(i), random_sum, key_position) + swap_temp = self._enc_params.register[i] + self._enc_params.register[i] = self._enc_params.register[to_swap.value] + self._enc_params.register[to_swap.value] = swap_temp + + self._enc_params.index_0 = self._enc_params.register[1] + self._enc_params.index_1 = self._enc_params.register[3] + self._enc_params.index_2 = self._enc_params.register[5] + self._enc_params.index_3 = self._enc_params.register[7] + self._enc_params.index_4 = self._enc_params.register[random_sum.value] + + def non_challenge_mapping_init(self): + self._enc_params.index_0 = Byte(1) + self._enc_params.index_1 = Byte(3) + self._enc_params.index_2 = Byte(5) + self._enc_params.index_3 = Byte(7) + self._enc_params.index_4 = Byte(11) + self._enc_params.register = [Byte(i) for i in range(256, 0, -1)] + + def byte_shift(self, b: Byte) -> Byte: + self._enc_params.index_1 += self._enc_params.register[self._enc_params.index_0.value] + self._enc_params.index_0 += Byte(1) + swap_temp_storage = self._enc_params.register[self._enc_params.index_4.value] + self._enc_params.register[self._enc_params.index_4.value] = self._enc_params.register[ + self._enc_params.index_1.value + ] + self._enc_params.register[self._enc_params.index_1.value] = self._enc_params.register[ + self._enc_params.index_3.value + ] + self._enc_params.register[self._enc_params.index_3.value] = self._enc_params.register[ + self._enc_params.index_0.value + ] + self._enc_params.register[self._enc_params.index_0.value] = swap_temp_storage + self._enc_params.index_2 += self._enc_params.register[swap_temp_storage.value] + + part1 = ( + self._enc_params.register[self._enc_params.index_2.value] + + self._enc_params.register[self._enc_params.index_0.value] + ).value % 256 + part2 = (self._enc_params.register[self._enc_params.index_3.value].value + + self._enc_params.register[self._enc_params.index_4.value].value + + self._enc_params.register[self._enc_params.index_1.value].value) % 256 + part3 = self._enc_params.register[part2].value + self._enc_params.index_4 = Byte( + b.value ^ self._enc_params.register[part1].value + ^ self._enc_params.register[part3].value + ) + self._enc_params.index_3 = b + + return self._enc_params.index_4 + + def index_position_generation(self, limit: Byte, random_sum: Byte, key_position: Byte) -> tuple[Byte, Byte, Byte]: + swap_index, retry_limiter, bit_mask = Byte(0), Byte(0), Byte(1) + if limit == Byte(0): + return random_sum, key_position, Byte(0) + + while bit_mask < limit: + bit_mask = (bit_mask << Byte(1)) + Byte(1) + + while True: + random_sum = ( + self._enc_params.register[random_sum.value] + + self._clientChallenge[key_position.value] + ) + key_position += Byte(1) + + if key_position >= Byte(len(self._clientChallenge)): + key_position = Byte(0) + random_sum += Byte(len(self._clientChallenge)) + + swap_index = bit_mask & random_sum + + if retry_limiter > Byte(11): + swap_index %= limit + retry_limiter += Byte(1) + + if swap_index <= limit: + break + + return random_sum, key_position, swap_index + + def encrypt(self, plain_text: bytes): + # skip first 14 bytes + head_buffer = plain_text[:14] + body_buffer = plain_text[14:] + cipher_body = bytearray(body_buffer) + for i in range(len(body_buffer)): + c = self.byte_shift(Byte(body_buffer[i])) + cipher_body[i] = c.value + cipher_body = bytes(cipher_body) + cipher = head_buffer+cipher_body + return cipher diff --git a/src/frontends/gamespy/protocols/server_browser/v2/aggregations/enums.py b/src/frontends/gamespy/protocols/server_browser/v2/aggregations/enums.py new file mode 100644 index 000000000..013704d85 --- /dev/null +++ b/src/frontends/gamespy/protocols/server_browser/v2/aggregations/enums.py @@ -0,0 +1,73 @@ +from enum import IntEnum + + +class PlayerSearchOptions(IntEnum): + SEARCH_ALL_GAMES = 1 + SEARCH_LEFT_SUBSTRING = 2 + SEARCH_RIGHT_SUBSTRING = 4 + SEARCH_ANY_SUBSTRING = 8 + + +class QueryType(IntEnum): + BASIC = 0 + FULL = 1 + ICMP = 2 + + +class DataKeyType(IntEnum): + STRING = 0 + BYTE = 1 + SHORT = 2 + + +class RequestType(IntEnum): + SERVER_LIST_REQUEST = 0x00 + SERVER_INFO_REQUEST = 0x01 + SEND_MESSAGE_REQUEST = 0x02 + KEEP_ALIVE_REPLY = 0x03 + MAP_LOOP_REQUEST = 0x04 + PLAYER_SEARCH_REQUEST = 0x05 + + +class ResponseType(IntEnum): + PUSH_KEYS_MESSAGE = 1 + PUSH_SERVER_MESSAGE = 2 + KEEP_ALIVE_MESSAGE = 3 + DELETE_SERVER_MESSAGE = 4 + MAP_LOOP_MESSAGE = 5 + PLAYER_SEARCH_MESSAGE = 6 + + +class ProtocolVersion(IntEnum): + LIST_PROTOCOL_VERSION_1 = 0 + LIST_ENCODING_VERSION = 3 + + +class ServerListUpdateOption(IntEnum): + SERVER_MAIN_LIST = 0 + SEND_FIELD_FOR_ALL = 1 + SERVER_FULL_INFO_LIST = 2 + """ + get the full info of a server + """ + P2P_SERVER_MAIN_LIST = 4 + ALTERNATE_SOURCE_IP = 8 + P2P_GROUP_ROOM_LIST = 32 + NO_LIST_CACHE = 64 + LIMIT_RESULT_COUNT = 128 + + +class GameServerFlags(IntEnum): + UNSOLICITED_UDP_FLAG = 1 + PRIVATE_IP_FLAG = 2 + CONNECT_NEGOTIATE_FLAG = 4 + ICMP_IP_FLAG = 8 + NON_STANDARD_PORT_FLAG = 16 + NON_STANDARD_PRIVATE_PORT_FLAG = 32 + HAS_KEYS_FLAG = 64 + HAS_FULL_RULES_FLAG = 128 + + +if __name__ == "__main__": + GameServerFlags.PRIVATE_IP_FLAG.value + pass diff --git a/src/frontends/gamespy/protocols/server_browser/v2/aggregations/exceptions.py b/src/frontends/gamespy/protocols/server_browser/v2/aggregations/exceptions.py new file mode 100644 index 000000000..1ce346c8f --- /dev/null +++ b/src/frontends/gamespy/protocols/server_browser/v2/aggregations/exceptions.py @@ -0,0 +1,5 @@ +from frontends.gamespy.library.exceptions.general import UniSpyException + + +class SBException(UniSpyException): + pass diff --git a/src/frontends/gamespy/protocols/server_browser/v2/aggregations/server_info_builder.py b/src/frontends/gamespy/protocols/server_browser/v2/aggregations/server_info_builder.py new file mode 100644 index 000000000..e02746546 --- /dev/null +++ b/src/frontends/gamespy/protocols/server_browser/v2/aggregations/server_info_builder.py @@ -0,0 +1,85 @@ +from socket import inet_aton + +from frontends.gamespy.protocols.query_report.aggregates.game_server_info import GameServerInfo + +# from backends.protocols.gamespy.query_report.data import get_all_groups +from frontends.gamespy.protocols.server_browser.v2.aggregations.enums import GameServerFlags + +# PEER_GROUP_LIST = get_all_groups() +QUERY_REPORT_DEFAULT_PORT = 6500 + + +def build_server_info_header( + flag: GameServerFlags, server_info: GameServerInfo +) -> bytearray: + header = bytearray() + # add key flag + header.append(flag.value) + # we add server public ip here + header.extend(inet_aton(server_info.host_ip_address)) + # we check host port is standard port or not + check_non_standard_port(header, server_info) + # check if game can directly query information from server + check_unsolicited_udp(header, server_info) + # we check the natneg flag + check_nat_neg_flag(header, server_info) + # now we check if there are private ip + check_private_ip(header, server_info) + # we check private port here + check_non_standard_private_port(header, server_info) + # we check icmp support here + check_icmp_support(header, server_info) + + return header + + +def check_nat_neg_flag(header: bytearray, server_info: GameServerInfo): + if "natneg" in server_info.data: + nat_neg_flag = int(server_info.data["natneg"]) + unsolicited_udp = header[0] & GameServerFlags.UNSOLICITED_UDP_FLAG.value + if nat_neg_flag == 1 and unsolicited_udp == 0: + header[0] ^= GameServerFlags.CONNECT_NEGOTIATE_FLAG.value + + +def check_unsolicited_udp(header: bytearray, server_info: GameServerInfo): + if "allow_unsolicited_udp" in server_info.data: + unsolicited_udp = int(server_info.data["unsolicitedudp"]) + if unsolicited_udp == 1: + header[0] ^= GameServerFlags.UNSOLICITED_UDP_FLAG.value + + +def check_private_ip(header: bytearray, server_info: GameServerInfo): + #!when game create a channel chat, it will use both the public ip and private ip to build the name. + #!known game: Worm3d + # todo + # if server_info.game_name in PEER_GROUP_LIST: + if "localip0" in server_info.data: + header[0] ^= GameServerFlags.PRIVATE_IP_FLAG.value + bytes_address = inet_aton(server_info.data["localip0"]) + header.extend(bytes_address) + + +def check_non_standard_port(header: bytearray, server_info: GameServerInfo): + # !! only dedicated server have different query report port and host port + # !! but peer server have same query report port and host port + # todo we have to check when we need send host port or query report port + if server_info.query_report_port != QUERY_REPORT_DEFAULT_PORT: + header[0] ^= GameServerFlags.NON_STANDARD_PORT_FLAG.value + hton_port = server_info.query_report_port_bytes + header.extend(hton_port) + + +def check_non_standard_private_port(header: bytearray, server_info: GameServerInfo): + if "localport" in server_info.data: + local_port = server_info.data["localport"] + if local_port != "" and local_port != QUERY_REPORT_DEFAULT_PORT: + header[0] ^= GameServerFlags.NON_STANDARD_PRIVATE_PORT_FLAG.value + port = int(local_port).to_bytes(2, byteorder="big") + header.extend(port) + + +def check_icmp_support(header: bytearray, server_info: GameServerInfo): + if "icmp_address" in server_info.data: + header[0] ^= GameServerFlags.ICMP_IP_FLAG.value + bytes_address = inet_aton(server_info.data["icmp_address"]) + header.extend(bytes_address) diff --git a/src/frontends/gamespy/protocols/server_browser/v2/aggregations/string_flags.py b/src/frontends/gamespy/protocols/server_browser/v2/aggregations/string_flags.py new file mode 100644 index 000000000..ce6769f3f --- /dev/null +++ b/src/frontends/gamespy/protocols/server_browser/v2/aggregations/string_flags.py @@ -0,0 +1,4 @@ +SINGLE_SERVER_END_FLAG = 0 +ALL_SERVER_END_FLAG = b"\x00\xFF\xFF\xFF\xFF" +STRING_SPLITER = 0 +NTS_STRING_FLAG = 255 diff --git a/src/frontends/gamespy/protocols/server_browser/v2/applications/client.py b/src/frontends/gamespy/protocols/server_browser/v2/applications/client.py new file mode 100644 index 000000000..08381cc90 --- /dev/null +++ b/src/frontends/gamespy/protocols/server_browser/v2/applications/client.py @@ -0,0 +1,32 @@ +from typing import TYPE_CHECKING +from frontends.gamespy.library.abstractions.client import ClientBase, ClientInfoBase +from frontends.gamespy.library.abstractions.connections import ConnectionBase +from frontends.gamespy.library.abstractions.enctypt_base import EncryptBase +from frontends.gamespy.library.configs import ServerConfig +from frontends.gamespy.library.log.log_manager import LogWriter +from frontends.gamespy.protocols.server_browser.v2.aggregations.encryption import EnctypeX +from frontends.gamespy.protocols.server_browser.v2.aggregations.enums import ServerListUpdateOption +if TYPE_CHECKING: + from frontends.gamespy.library.abstractions.switcher import SwitcherBase + + +class ClientInfo(ClientInfoBase): + game_secret_key: str + client_challenge: str + search_type: ServerListUpdateOption + game_name: str + + +class Client(ClientBase): + is_log_raw: bool + info: ClientInfo + crypto: EnctypeX | None + + def __init__(self, connection: ConnectionBase, server_config: ServerConfig, logger: LogWriter): + super().__init__(connection, server_config, logger) + self.is_log_raw = True + self.info = ClientInfo() + + def _create_switcher(self, buffer: bytes) -> "SwitcherBase": + from frontends.gamespy.protocols.server_browser.v2.applications.switcher import Switcher + return Switcher(self, buffer) diff --git a/src/frontends/gamespy/protocols/server_browser/v2/applications/handlers.py b/src/frontends/gamespy/protocols/server_browser/v2/applications/handlers.py new file mode 100644 index 000000000..a2574f6f3 --- /dev/null +++ b/src/frontends/gamespy/protocols/server_browser/v2/applications/handlers.py @@ -0,0 +1,158 @@ +from concurrent.futures import ProcessPoolExecutor +from typing import TYPE_CHECKING, cast +from frontends.gamespy.protocols.query_report.aggregates.enums import GameServerStatus +from frontends.gamespy.protocols.query_report.aggregates.game_server_info import ( + GameServerInfo, +) + +from frontends.gamespy.protocols.server_browser.v2.abstractions.contracts import ( + RequestBase, +) +from frontends.gamespy.protocols.server_browser.v2.contracts.requests import ( + SendMessageRequest, + ServerInfoRequest, + ServerListRequest, +) +from frontends.gamespy.protocols.server_browser.v2.contracts.responses import ( + DeleteServerInfoResponse, + P2PGroupRoomListResponse, + ServerMainListResponse, + ServerFullInfoListResponse, + UpdateServerInfoResponse, +) +from frontends.gamespy.protocols.server_browser.v2.contracts.results import ( + P2PGroupRoomListResult, + ServerFullInfoListResult, + UpdateServerInfoResult, + ServerMainListResult, +) +from frontends.gamespy.protocols.server_browser.v2.aggregations.enums import ( + # RequestType, + ServerListUpdateOption, +) +from frontends.gamespy.protocols.server_browser.v2.abstractions.handlers import ( + CmdHandlerBase, + ServerListUpdateOptionHandlerBase, +) + +from frontends.gamespy.protocols.server_browser.v2.applications.client import Client + + +def get_clients(game_name: str): + client_list = [] + assert isinstance(game_name, str) + for ip, client in Client.pool.items(): + if TYPE_CHECKING: + client = cast(Client, client) + if client.info.game_name == game_name: + client_list.append(client) + + return client_list + + +class AdHocHandler(CmdHandlerBase): + _message: GameServerInfo + # !fix this + _result: UpdateServerInfoResult + + def __init__(self, message: GameServerInfo) -> None: + self._log_current_class() + self._message = message + + def handle(self) -> None: + result = UpdateServerInfoResult(game_server_info=self._message) + match self._message.status: + case status if ( + status == GameServerStatus.NORMAL + or status == GameServerStatus.UPDATE + or status == GameServerStatus.PLAYING + ): + self.response = UpdateServerInfoResponse(result) + case GameServerStatus.SHUTDOWN: + self.response = DeleteServerInfoResponse(result) + case _: + pass + + clients = get_clients(self._message.game_name) + + with ProcessPoolExecutor() as executor: + executor.map(self.send_message, clients) + + def send_message(self, client: Client): + if ( + client.info.game_name == self._message.game_name + and client.crypto is not None + and ( + client.info.search_type == ServerListUpdateOption.SERVER_MAIN_LIST + or client.info.search_type + == ServerListUpdateOption.P2P_SERVER_MAIN_LIST + ) + ): + client.log_info( + f"Sending AdHoc message {self._message.status} to client") + client.send(self.response) + + +class SendMessageHandler(CmdHandlerBase): + _request: SendMessageRequest + + def __init__(self, client: Client, request: SendMessageRequest) -> None: + assert isinstance(request, SendMessageRequest) + super().__init__(client, request) + # we just need send the message to backend, then backend will send to queryreport frontend, query report frontend will handle for us + + +class UpdateServerInfoHandler(CmdHandlerBase): + _request: ServerInfoRequest + _result: UpdateServerInfoResult + _response: UpdateServerInfoResponse + + def __init__(self, client: Client, request: ServerInfoRequest) -> None: + assert isinstance(request, ServerInfoRequest) + super().__init__(client, request) + + +class ServerMainListHandler(ServerListUpdateOptionHandlerBase): + _request: ServerListRequest + _result: ServerMainListResult + _response: ServerMainListResponse + + def __init__(self, client: Client, request: ServerListRequest) -> None: + assert isinstance(request, ServerListRequest) + super().__init__(client, request) + + +class P2PGroupRoomListHandler(ServerListUpdateOptionHandlerBase): + _request: ServerListRequest + _result: P2PGroupRoomListResult + _response: P2PGroupRoomListResponse + + def __init__(self, client: Client, request: ServerListRequest) -> None: + assert isinstance(request, ServerListRequest) + super().__init__(client, request) + + +class ServerFullInfoListHandler(ServerListUpdateOptionHandlerBase): + """ + In sbctest.c + line 392 ServerBrowserAuxUpdateServer(sb, server, async, fullUpdate); + will get the full info of a server such as: player data, server data, team data + """ + """ + !! below is the source code of sb v2, adhocdata is directly follow the mainlist response + todo check if adhoc data is append after mainlist response + if (slist->state == sl_mainlist) + err = ProcessMainListData(slist); + if (err != sbe_noerror) + return err; + //always need to check this after mainlistdata, in case some extra data has some in (e.g. key list for push) + if (slist->state == sl_connected && slist->inbufferlen > 0) + return ProcessAdHocData(slist); + """ + _request: ServerListRequest + _result: ServerFullInfoListResult + _response: ServerFullInfoListResponse + + def __init__(self, client: Client, request: ServerListRequest) -> None: + assert isinstance(request, ServerListRequest) + super().__init__(client, request) diff --git a/src/frontends/gamespy/protocols/server_browser/v2/applications/switcher.py b/src/frontends/gamespy/protocols/server_browser/v2/applications/switcher.py new file mode 100644 index 000000000..bc9235c3f --- /dev/null +++ b/src/frontends/gamespy/protocols/server_browser/v2/applications/switcher.py @@ -0,0 +1,89 @@ +from typing import TYPE_CHECKING, Optional, cast +from frontends.gamespy.library.abstractions.switcher import SwitcherBase +from frontends.gamespy.protocols.server_browser.aggregates.exceptions import ( + ServerBrowserException, +) +from frontends.gamespy.protocols.server_browser.v2.abstractions.handlers import ( + CmdHandlerBase, +) +from frontends.gamespy.protocols.server_browser.v2.aggregations.enums import ( + RequestType, + ServerListUpdateOption, +) +from frontends.gamespy.protocols.server_browser.v2.aggregations.exceptions import SBException +from frontends.gamespy.protocols.server_browser.v2.applications.client import Client +from frontends.gamespy.protocols.server_browser.v2.applications.handlers import ( + P2PGroupRoomListHandler, + SendMessageHandler, + ServerFullInfoListHandler, + UpdateServerInfoHandler, + ServerMainListHandler, +) +from frontends.gamespy.protocols.server_browser.v2.contracts.requests import ( + SendMessageRequest, + ServerInfoRequest, + ServerListRequest, +) + + +class Switcher(SwitcherBase): + _raw_request: bytes + _client: Client + + def _process_raw_request(self) -> None: + if len(self._raw_request) < 4: + raise SBException("Invalid request") + name = self._raw_request[2] + if name not in RequestType: + self._client.log_debug(f"Request: {name} is not a valid request.") + return + + self._requests.append((RequestType(name), self._raw_request)) + + def _create_cmd_handlers( + self, name: int, raw_request: bytes + ) -> CmdHandlerBase | None: + req = raw_request + if TYPE_CHECKING: + self._client = cast(Client, self._client) + match name: + case RequestType.SERVER_LIST_REQUEST: + handler = self.__check_update_option(req) + return handler + case RequestType.SERVER_INFO_REQUEST: + return UpdateServerInfoHandler(self._client, ServerInfoRequest(req)) + case RequestType.SEND_MESSAGE_REQUEST: + return SendMessageHandler(self._client, SendMessageRequest(req)) + case _: + return None + + def __check_update_option(self, request: bytes) -> CmdHandlerBase: + """ + check update option and create handler + """ + update_option = self.get_update_option(request) + match update_option: + case (ServerListUpdateOption.SERVER_MAIN_LIST + | ServerListUpdateOption.P2P_SERVER_MAIN_LIST + | ServerListUpdateOption.LIMIT_RESULT_COUNT): + return ServerMainListHandler(self._client, ServerListRequest(request)) + case ServerListUpdateOption.P2P_GROUP_ROOM_LIST: + return P2PGroupRoomListHandler(self._client, ServerListRequest(request)) + case ServerListUpdateOption.SERVER_FULL_INFO_LIST: + return ServerFullInfoListHandler(self._client, ServerListRequest(request)) + case _: + raise ServerBrowserException( + "unknown serverlist update option type") + + @staticmethod + def get_update_option(raw_request: bytes) -> ServerListUpdateOption: + # todo check if all game follow this pattern, +2 is calc by sdk server info request + update_option_index = raw_request.find( + b"\x00\x00\x00\x00", 6)+2 + update_option_bytes = raw_request[ + update_option_index: update_option_index + 4 + ] + update_option = ServerListUpdateOption( + int.from_bytes(update_option_bytes, byteorder='big') + ) + return update_option diff --git a/src/frontends/gamespy/protocols/server_browser/v2/contracts/__init__.py b/src/frontends/gamespy/protocols/server_browser/v2/contracts/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/gamespy/protocols/server_browser/v2/contracts/requests.py b/src/frontends/gamespy/protocols/server_browser/v2/contracts/requests.py new file mode 100644 index 000000000..a64648dbc --- /dev/null +++ b/src/frontends/gamespy/protocols/server_browser/v2/contracts/requests.py @@ -0,0 +1,74 @@ +from socket import inet_ntoa + +from frontends.gamespy.protocols.server_browser.v2.abstractions.contracts import ( + AdHocRequestBase, + ServerListUpdateOptionRequestBase, +) +from frontends.gamespy.protocols.server_browser.v2.aggregations.enums import ( + RequestType, + ServerListUpdateOption, +) +from frontends.gamespy.protocols.server_browser.v2.aggregations.exceptions import SBException + + +class ServerListRequest(ServerListUpdateOptionRequestBase): + def parse(self) -> None: + self.command_name = RequestType(self.raw_request[0]) + if self.command_name != RequestType.SERVER_LIST_REQUEST: + raise SBException("raw request is not valid server list request") + self.request_version = int(self.raw_request[2]) + self.protocol_version = int(self.raw_request[3]) + self.encoding_version = int(self.raw_request[4]) + self.game_version = int.from_bytes(self.raw_request[5:9], "little") + + remain_data = self.raw_request[9:] + dev_game_name_index = remain_data.index(0) + self.dev_game_name = remain_data[:dev_game_name_index].decode() + remain_data = remain_data[dev_game_name_index + 1:] + game_name_index = remain_data.index(0) + self.game_name = remain_data[:game_name_index].decode() + remain_data = remain_data[game_name_index + 1:] + self.client_challenge = remain_data[:8].decode() + remain_data = remain_data[8:] + + filter_index = remain_data.index(0) + if filter_index > 0: + self.filter = remain_data[:filter_index].decode() + remain_data = remain_data[filter_index + 1:] + + keys_index = remain_data.index(0) + self.keys = remain_data[1:keys_index].decode().split("\\") + remain_data = remain_data[keys_index + 1:] + + byte_update_options = remain_data[:4] + self.update_option = ServerListUpdateOption( + int.from_bytes(byte_update_options)) + remain_data = remain_data[4:] + + if self.update_option & ServerListUpdateOption.ALTERNATE_SOURCE_IP: + self.source_ip = inet_ntoa(remain_data[:4]) + remain_data = remain_data[4:] + + if self.update_option & ServerListUpdateOption.LIMIT_RESULT_COUNT: + if len(remain_data) != 4: + raise SBException("The max number of server is incorrect.") + self.max_servers = int(remain_data[:4][::-1]) + + +class SendMessageRequest(AdHocRequestBase): + prefix_message: bytes + client_message: bytes + natneg_cookie: int + + def __init__(self, raw_request: bytes | None = None) -> None: + if raw_request is not None: + super().__init__(raw_request) + + def parse(self) -> None: + super().parse() + self.client_message = self.raw_request[9:] + self.natneg_cookie = int.from_bytes(self.client_message[6:10]) + + +class ServerInfoRequest(AdHocRequestBase): + pass diff --git a/src/frontends/gamespy/protocols/server_browser/v2/contracts/responses.py b/src/frontends/gamespy/protocols/server_browser/v2/contracts/responses.py new file mode 100644 index 000000000..8bf144e52 --- /dev/null +++ b/src/frontends/gamespy/protocols/server_browser/v2/contracts/responses.py @@ -0,0 +1,166 @@ +from frontends.gamespy.library.extentions.encoding import get_bytes +from frontends.gamespy.protocols.query_report.aggregates.game_server_info import GameServerInfo +from frontends.gamespy.protocols.query_report.aggregates.peer_room_info import PeerRoomInfo +from frontends.gamespy.protocols.server_browser.v2.abstractions.contracts import ( + AdHocResponseBase, + ServerListUpdateOptionResponseBase, +) +from frontends.gamespy.protocols.server_browser.v2.aggregations.exceptions import SBException +from frontends.gamespy.protocols.server_browser.v2.aggregations.server_info_builder import ( + build_server_info_header, +) +from frontends.gamespy.protocols.server_browser.v2.aggregations.string_flags import ALL_SERVER_END_FLAG, NTS_STRING_FLAG, STRING_SPLITER, SINGLE_SERVER_END_FLAG +from frontends.gamespy.protocols.server_browser.v2.contracts.requests import ServerListRequest +from frontends.gamespy.protocols.server_browser.v2.contracts.results import ( + P2PGroupRoomListResult, + ServerFullInfoListResult, + UpdateServerInfoResult, + ServerMainListResult, +) + +from frontends.gamespy.protocols.server_browser.v2.aggregations.enums import GameServerFlags, ResponseType + + +class DeleteServerInfoResponse(AdHocResponseBase): + _result: UpdateServerInfoResult + + def __init__(self, result: UpdateServerInfoResult) -> None: + assert isinstance(result, UpdateServerInfoResult) + self._result = result + + def build(self): + buffer = bytearray() + buffer.append(ResponseType.DELETE_SERVER_MESSAGE) + buffer.extend(self._result.game_server_info.host_ip_address_bytes) + self.sending_buffer = bytes(buffer) + + +class UpdateServerInfoResponse(AdHocResponseBase): + def __init__(self, result: UpdateServerInfoResult) -> None: + assert isinstance(result, UpdateServerInfoResult) + self._result = result + self._buffer = bytearray() + + def build(self) -> None: + self._buffer.append(ResponseType.PUSH_SERVER_MESSAGE) + self.__build_single_server_full_info() + msg_leng = bytearray(len(self._buffer).to_bytes(2, "big")) + # make sure the msg_leng is at first 2 bytes + self._buffer = msg_leng+self._buffer + self.sending_buffer = bytes(self._buffer) + + def __build_single_server_full_info(self): + header = build_server_info_header( + GameServerFlags.HAS_FULL_RULES_FLAG, self._result.game_server_info + ) + self._buffer.extend(header) + if self._result.game_server_info.data is not None: + data_str = UpdateServerInfoResponse._build_kv( + self._result.game_server_info.data) + self._buffer.extend(data_str) + + @staticmethod + def _build_kv(data: dict) -> bytearray: + buffer = bytearray() + for k, v in data.items(): + buffer.extend(get_bytes(k)) + buffer.append(STRING_SPLITER) + buffer.extend(get_bytes(v)) + buffer.append(STRING_SPLITER) + return buffer + + +class P2PGroupRoomListResponse(ServerListUpdateOptionResponseBase): + _result: P2PGroupRoomListResult + + def build(self) -> None: + super().build() + self.build_server_keys() + self.build_unique_value() + self._build_servers_full_info() + self.sending_buffer = bytes(self._buffer) + + def _build_servers_full_info(self): + # we have to add a server with group ip 0 to make peer sdk finish the sb process + empty_info = PeerRoomInfo(game_name="", groupid=0, hostname="") + self._result.peer_room_info.append(empty_info) + for room in self._result.peer_room_info: + self._buffer.append(GameServerFlags.HAS_KEYS_FLAG) + group_id_bytes = room.group_id.to_bytes(length=4) + self._buffer.extend(group_id_bytes) + # get gamespy format dict + gamespy_dict = room.get_gamespy_dict() + for key in self._result.keys: + self._buffer.append(NTS_STRING_FLAG) + value = ( + gamespy_dict[key] + if key in gamespy_dict.keys() + else "" + ) + self._buffer.extend(get_bytes(value)) + self._buffer.append(STRING_SPLITER) + # apped end flag + end_flag = b"\x00\x00\x00\x00" + self._buffer.extend(end_flag) + + +class ServerMainListResponse(ServerListUpdateOptionResponseBase): + _result: ServerMainListResult + + def __add_key_value_to_buffer(self, value): + self._buffer.append(NTS_STRING_FLAG) + self._buffer.extend(get_bytes(value)) + self._buffer.append(STRING_SPLITER) + + def __check_key_existance(self): + for info in self._result.servers_info: + for key in self._result.keys: + if key not in info.data: + raise SBException( + f"key:{key} is not in server info, please check database") + + def __build_servers_full_info(self): + for info in self._result.servers_info: + last_header = build_server_info_header(self._result.flag, info) + self._buffer.extend(last_header) + for key in self._result.keys: + value = info.data[key] + self.__add_key_value_to_buffer(value) + + def __build_tail(self): + # after all server is added we add the tail + self._buffer.extend(ALL_SERVER_END_FLAG) + + def build(self) -> None: + super().build() + self.build_server_keys() + self.build_unique_value() + self.__check_key_existance() + self.__build_servers_full_info() + self.__build_tail() + self.sending_buffer = bytes(self._buffer) + + +class ServerFullInfoListResponse(ServerListUpdateOptionResponseBase): + """ + currently we send all server info to game to make it pass HAS_FULL_RULES_FLAG + todo check how this cmd is handled + """ + _result: ServerFullInfoListResult + + def build(self) -> None: + """ + adhoc data can contains multiple message, + gamespy will read the response to the end + """ + # cryptheader is nessesary for make the connection with server browser + super().build() + push_buffer = bytearray() + for info in self._result.servers_info: + result = UpdateServerInfoResult(game_server_info=info) + response = UpdateServerInfoResponse(result) + response.build() + push_buffer.extend(response.sending_buffer) + # we append the push server full info response (Adhoc response) to the crypt header + self._buffer = self._buffer+push_buffer + self.sending_buffer = bytes(self._buffer) diff --git a/src/frontends/gamespy/protocols/server_browser/v2/contracts/results.py b/src/frontends/gamespy/protocols/server_browser/v2/contracts/results.py new file mode 100644 index 000000000..09d306d93 --- /dev/null +++ b/src/frontends/gamespy/protocols/server_browser/v2/contracts/results.py @@ -0,0 +1,38 @@ +from uuid import UUID + +from frontends.gamespy.protocols.query_report.aggregates.game_server_info import ( + GameServerInfo, +) +from frontends.gamespy.protocols.query_report.aggregates.peer_room_info import ( + PeerRoomInfo, +) +from frontends.gamespy.protocols.server_browser.v2.abstractions.contracts import ( + AdHocResultBase, + ResultBase, + ServerListUpdateOptionResultBase, +) +from frontends.gamespy.protocols.server_browser.v2.aggregations.enums import GameServerFlags + + +class UpdateServerInfoResult(AdHocResultBase): + pass + + +class P2PGroupRoomListResult(ServerListUpdateOptionResultBase): + peer_room_info: list[PeerRoomInfo] + + +class ServerMainListResult(ServerListUpdateOptionResultBase): + servers_info: list[GameServerInfo] + flag: GameServerFlags = GameServerFlags.HAS_KEYS_FLAG + + +class ServerFullInfoListResult(ServerListUpdateOptionResultBase): + servers_info: list[GameServerInfo] + flag: GameServerFlags = GameServerFlags.HAS_FULL_RULES_FLAG + + +class SendMessageResult(ResultBase): + sb_sender_id: UUID + natneg_message: str + server_info: GameServerInfo diff --git a/src/frontends/gamespy/protocols/web_services/__init__.py b/src/frontends/gamespy/protocols/web_services/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/gamespy/protocols/web_services/abstractions/contracts.py b/src/frontends/gamespy/protocols/web_services/abstractions/contracts.py new file mode 100644 index 000000000..55d56cedd --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/abstractions/contracts.py @@ -0,0 +1,37 @@ +import frontends.gamespy.library.abstractions.contracts as lib +import xml.etree.ElementTree as ET + +from frontends.gamespy.protocols.web_services.aggregations.exceptions import WebException +from frontends.gamespy.protocols.web_services.aggregations.soap_envelop import SoapEnvelop + + +class RequestBase(lib.RequestBase): + raw_request: str + _content_element: ET.Element + + def __init__(self, raw_request: str) -> None: + assert isinstance(raw_request, str) + super().__init__(raw_request) + + def parse(self) -> None: + xelements = ET.fromstring(self.raw_request) + self._content_element = xelements[0][0] + + +class ResultBase(lib.ResultBase): + pass + + +class ResponseBase(lib.ResponseBase): + _content: SoapEnvelop + """ + Soap envelope content, should be initialized in response sub class + """ + sending_buffer: str + + def __init__(self, result: ResultBase) -> None: + assert issubclass(type(result), ResultBase) + super().__init__(result) + + def build(self) -> None: + self.sending_buffer = str(self._content) diff --git a/src/frontends/gamespy/protocols/web_services/abstractions/handler.py b/src/frontends/gamespy/protocols/web_services/abstractions/handler.py new file mode 100644 index 000000000..3fa1bb01d --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/abstractions/handler.py @@ -0,0 +1,12 @@ +import frontends.gamespy.library.abstractions.handler as lib +from frontends.gamespy.protocols.web_services.applications.client import Client +from frontends.gamespy.protocols.web_services.abstractions.contracts import RequestBase + + +class CmdHandlerBase(lib.CmdHandlerBase): + _client: Client + + def __init__(self, client: Client, request: RequestBase) -> None: + assert isinstance(client, Client) + assert issubclass(type(request), RequestBase) + super().__init__(client, request) diff --git a/src/frontends/gamespy/protocols/web_services/aggregations/exceptions.py b/src/frontends/gamespy/protocols/web_services/aggregations/exceptions.py new file mode 100644 index 000000000..b4f839817 --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/aggregations/exceptions.py @@ -0,0 +1,6 @@ +from frontends.gamespy.library.exceptions.general import UniSpyException + + +class WebException(UniSpyException): + pass + diff --git a/src/frontends/gamespy/protocols/web_services/aggregations/soap_envelop.py b/src/frontends/gamespy/protocols/web_services/aggregations/soap_envelop.py new file mode 100644 index 000000000..d7ef43ba1 --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/aggregations/soap_envelop.py @@ -0,0 +1,53 @@ +import xml.etree.ElementTree as ET + +from frontends.gamespy.protocols.web_services.aggregations.exceptions import WebException + + +class SoapEnvelop: + current_element: ET.Element + content: ET.Element + + def __init__(self, root_name: str): + assert isinstance(root_name, str) + self.content = ET.Element(root_name) + self.current_element = self.content + + def change_to_element(self, name: str): + current_element = self.content.find( + f".//{name}") + if current_element is None: + raise WebException("can not find the node") + self.current_element = current_element + + def go_to_content_element(self): + self.current_element = self.content + + def add(self, name: str, value: object = None): + tag = f"{name}" + new_element = ET.SubElement( + self.current_element, tag + ) + + if value is None: + self.parent_element = self.current_element + self.current_element = new_element + else: + new_element.text = str(value) + + def __str__(self) -> str: + xml_str: str = ET.tostring( + self.content, + encoding="unicode" + ) + return xml_str + + +if __name__ == "__main__": + import xml.etree.ElementTree as ET + + s = SoapEnvelop("test_name") + s.add("level1", "1") + s.add("level1.1", "1.1") + s.go_to_content_element() + s.add("level2", "2") + str(s) diff --git a/src/frontends/gamespy/protocols/web_services/applications/client.py b/src/frontends/gamespy/protocols/web_services/applications/client.py new file mode 100644 index 000000000..213edb6c5 --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/applications/client.py @@ -0,0 +1,43 @@ +from frontends.gamespy.library.abstractions.client import ClientBase, ClientInfoBase +from frontends.gamespy.library.abstractions.switcher import SwitcherBase +from frontends.gamespy.library.log.log_manager import LogWriter +from frontends.gamespy.library.network.http_handler import HttpConnection +from frontends.gamespy.library.configs import ServerConfig + + +class ClientInfo(ClientInfoBase): + """ + Note!! the public exponent on SDK must set to 000001\n + because the multiple inverse of 1 is 1\n + data^1 mod n = data\n + enc^1 mod n = data^1^1 mod n = data\n + I do not want let our server to compute the rsa encryption so I made this trick\n + """ + + PEER_KEY_PRIVATE = "" + PEER_KEY_EXPONENT = "000001" + PEER_KEY_MODULUS = "aefb5064bbd1eb632fa8d57aab1c49366ce0ee3161cbef19f2b7971b63b811790ecbf6a47b34c55f65a0766b40c261c5d69c394cd320842dd2bccba883d30eae8fdba5d03b21b09bfc600dcb30b1b2f3fbe8077630b006dcb54c4254f14891762f72e7bbfe743eb8baf65f9e8c8d11ebe46f6b59e986b4c394cfbc2c8606e29f" + SERVER_DATA = "95980bf5011ce73f2866b995a272420c36f1e8b4ac946f0b5bfe87c9fef0811036da00cfa85e77e00af11c924d425ec06b1dd052feab1250376155272904cbf9da831b0ce3d52964424c0a426b869e2c0ad11ffa3e70496e27ea250adb707a96b3496bff190eafc0b6b9c99db75b02c2a822bb1b5b3d954e7b2c0f9b1487e3e1" + SIGNATURE_PREFIX = "0001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003020300C06082A864886F70D020505000410" + + PRIVATE_KEY_D = [0x96, 0xE2, 0xF4, 0xF9, 0x7C, 0x78, 0x81, 0x0C, 0x13, 0xE2, 0xA4, 0xCA, 0xC1, 0x12, 0x44, 0xBB, 0x5B, 0x37, 0xC5, 0x4E, 0x98, 0x20, 0xF1, 0x3F, 0xE9, 0xB5, 0x53, 0xDA, 0x10, 0xB1, 0xE8, 0xEF, 0x8E, 0xB0, 0x3F, 0x87, 0x68, 0x1B, 0x0E, 0x62, 0x4D, 0x1A, 0x8D, 0xE9, 0x17, 0x4C, 0xBE, 0xE5, 0xB8, 0xED, 0x92, 0xE4, 0xBE, 0x74, 0xF8, 0x6C, 0x30, 0x38, 0xCD, 0x7C, 0x1A, 0x20, 0xB9, 0xA3, + 0xDB, 0x1D, 0x49, 0x22, 0x62, 0x87, 0x38, 0x68, 0xFB, 0xA0, 0x8E, 0x1E, 0xAB, 0x5C, 0xBA, 0x86, 0x3F, 0x8F, 0xDB, 0xF4, 0x5E, 0xEA, 0x61, 0x4B, 0xBF, 0x6C, 0xFC, 0x47, 0x00, 0x81, 0x44, 0x2A, 0x97, 0x78, 0x7E, 0xB6, 0xEC, 0xA7, 0x1C, 0x48, 0x96, 0x81, 0x6C, 0x2A, 0x62, 0x72, 0x4C, 0x0E, 0x8C, 0xAA, 0xEE, 0xAB, 0x72, 0x78, 0xC2, 0x55, 0x4A, 0x13, 0x80, 0x94, 0x6E, 0xED, 0x21, 0x29] # fmt: skip + + MODULUES = [0xA9, 0x3E, 0x00, 0x19, 0x2C, 0x4A, 0x98, 0x69, 0xD7, 0x41, 0x9A, 0xFF, 0x66, 0x2E, 0xCA, 0xD6, 0xC8, 0xB9, 0x99, 0x09, 0xFD, 0xD0, 0xE7, 0xF8, 0xCA, 0xDD, 0x15, 0x32, 0xE8, 0xE3, 0x59, 0x37, 0x40, 0x83, 0xDA, 0xB8, 0xBE, 0x71, 0x7F, 0x60, 0x91, 0x60, 0xCD, 0x6A, 0x54, 0x11, 0xBE, 0xD7, 0x92, 0x7A, 0xD3, 0xB5, 0xC0, 0x0C, 0x4C, 0x4B, 0x34, 0x76, 0x71, 0xF2, 0x3F, 0xE0, 0x1E, 0xBB, + 0x2F, 0x83, 0x4B, 0xD8, 0xCA, 0x27, 0xC3, 0x55, 0x3E, 0x1E, 0x6B, 0xC2, 0x85, 0xAF, 0xC6, 0x3E, 0xC0, 0xE1, 0x1F, 0x59, 0xCA, 0xF6, 0xAC, 0x37, 0x5F, 0x4B, 0x0E, 0xB8, 0x2A, 0x4D, 0xA2, 0x2C, 0x0C, 0x10, 0x1D, 0x09, 0x13, 0x1A, 0x7C, 0x42, 0x0D, 0x4C, 0xC4, 0xD0, 0x95, 0x62, 0x4C, 0x42, 0xBC, 0xD8, 0xD7, 0x19, 0x16, 0xC8, 0xDC, 0x00, 0x48, 0x08, 0x6D, 0x74, 0x6A, 0x31, 0x55, 0xC7] # fmt: skip + + EXPONENT = [0x01, 0x00, 0x01] # fmt: skip + + +class Client(ClientBase): + info: ClientInfo + client_pool: dict[str, "Client"] = {} + + def __init__(self, connection: HttpConnection, server_config: ServerConfig, logger: LogWriter): + super().__init__(connection, server_config, logger) + self.info = ClientInfo() + self.is_log_raw = False + + def _create_switcher(self, buffer: bytes) -> SwitcherBase: + from frontends.gamespy.protocols.web_services.applications.switcher import Switcher + return Switcher(self, buffer.decode()) diff --git a/src/frontends/gamespy/protocols/web_services/applications/server_launcher.py b/src/frontends/gamespy/protocols/web_services/applications/server_launcher.py new file mode 100644 index 000000000..256a5be71 --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/applications/server_launcher.py @@ -0,0 +1,19 @@ +from frontends.gamespy.library.abstractions.server_launcher import ServicesFactory, ServiceBase +from frontends.gamespy.library.network.http_handler import HttpServer +from frontends.gamespy.protocols.web_services.applications.client import Client + + +class Service(ServiceBase): + def __init__(self) -> None: + super().__init__( + config_name="WebServices", + client_cls=Client, + network_server_cls=HttpServer + ) + + +if __name__ == "__main__": + from frontends.gamespy.library.extentions.debug_helper import DebugHelper + web = Service() + helper = DebugHelper("./frontends/", ServicesFactory([web])) + helper.start() diff --git a/src/frontends/gamespy/protocols/web_services/applications/switcher.py b/src/frontends/gamespy/protocols/web_services/applications/switcher.py new file mode 100644 index 000000000..89264fad9 --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/applications/switcher.py @@ -0,0 +1,130 @@ +from typing import TYPE_CHECKING, Optional, cast +from frontends.gamespy.library.abstractions.client import ClientBase +from frontends.gamespy.library.abstractions.handler import CmdHandlerBase +from frontends.gamespy.library.abstractions.switcher import SwitcherBase +import xml.etree.ElementTree as ET + +from frontends.gamespy.protocols.web_services.applications.client import Client +from frontends.gamespy.protocols.web_services.aggregations.exceptions import WebException +from frontends.gamespy.protocols.web_services.modules.auth.contracts.requests import CreateUserAccountRequest, LoginProfileRequest, LoginProfileWithGameIdRequest, LoginRemoteAuthRequest, LoginRemoteAuthWithGameIdRequest, LoginUniqueNickRequest, LoginUniqueNickWithGameIdRequest +from frontends.gamespy.protocols.web_services.modules.auth.applications.handlers import CreateUserAccountHandler, LoginProfileHandler, LoginProfileWithGameIdHandler, LoginRemoteAuthHandler, LoginRemoteAuthWithGameIdHandler, LoginUniqueNickHandler, LoginUniqueNickWithGameIdHandler +from frontends.gamespy.protocols.web_services.modules.direct2game.contracts.requests import GetPurchaseHistoryRequest, GetStoreAvailabilityRequest +from frontends.gamespy.protocols.web_services.modules.direct2game.applications.handlers import GetPurchaseHistoryHandler, GetStoreAvailabilityHandler +from frontends.gamespy.protocols.web_services.modules.sake.contracts.requests import CreateRecordRequest, GetMyRecordsRequest, SearchForRecordsRequest +from frontends.gamespy.protocols.web_services.modules.sake.applications.handlers import CreateRecordHandler, GetMyRecordsHandler, SearchForRecordsHandler + + +class Switcher(SwitcherBase): + _raw_request: str + + def __init__(self, client: ClientBase, raw_request: str) -> None: + assert isinstance(raw_request, str) + # assert isinstance(client,Client) + super().__init__(client, raw_request) + + def _process_raw_request(self) -> None: + try: + name_node = ET.fromstring(self._raw_request)[0][0] + except Exception as e: + raise WebException(f"xml serialization failed: {str(e)}") + if name_node is None: + raise WebException("name node is missing from soap request") + if name_node.tag is None: + raise WebException( + "name node text field is missing from soap request") + name = name_node.tag.split("}")[1] + + if len(name) < 4: + raise WebException("request name invalid") + self._requests.append((name, self._raw_request)) + + def _create_cmd_handlers(self, name: str, raw_request: str) -> CmdHandlerBase | None: + if TYPE_CHECKING: + self._client = cast(Client, self._client) + + match name: + # Altas services + case "CreateMatchlessSession": + raise NotImplementedError() + case "CreateSession": + raise NotImplementedError() + case "SetReportIntention": + raise NotImplementedError() + case "SubmitReport": + raise NotImplementedError() + + # Auth services + case "LoginProfile": + return LoginProfileHandler( + self._client, LoginProfileRequest(raw_request)) + case "LoginProfileWithGameId": + return LoginProfileWithGameIdHandler( + self._client, LoginProfileWithGameIdRequest(raw_request)) + case "LoginRemoteAuth": + return LoginRemoteAuthHandler(self._client, LoginRemoteAuthRequest(raw_request)) + + case "LoginRemoteAuthWithGameId": + return LoginRemoteAuthWithGameIdHandler(self._client, LoginRemoteAuthWithGameIdRequest(raw_request)) + + case "LoginUniqueNick": + return LoginUniqueNickHandler(self._client, LoginUniqueNickRequest(raw_request)) + case "LoginUniqueNickWithGameId": + return LoginUniqueNickWithGameIdHandler(self._client, LoginUniqueNickWithGameIdRequest(raw_request)) + case "CreateUserAccount": + return CreateUserAccountHandler(self._client, CreateUserAccountRequest(raw_request)) + # Direct2Game services + + case "GetStoreAvailability": + return GetStoreAvailabilityHandler(self._client, GetStoreAvailabilityRequest(raw_request)) + + case "GetPurchaseHistory": + return GetPurchaseHistoryHandler(self._client, GetPurchaseHistoryRequest(raw_request)) + + case "GetTargettedAd": + raise NotImplementedError() + + # InGameAd services + case "ReportAdUsage": + raise NotImplementedError() + + # PatchingAndTracking + case "Motd": + raise NotImplementedError() + case "Vercheck": + raise NotImplementedError() + + # Racing + case "GetContestData": + raise NotImplementedError() + case "GetFriendRankings": + raise NotImplementedError() + case "GetRegionalData": + raise NotImplementedError() + case "GetTenAboveRankings": + raise NotImplementedError() + case "GetTopTenRankings": + raise NotImplementedError() + case "SubmitScores": + raise NotImplementedError() + + # SAKE + case "CreateRecord": + return CreateRecordHandler(self._client, CreateRecordRequest(raw_request)) + case "DeleteRecord": + raise NotImplementedError() + case "GetMyRecords": + return GetMyRecordsHandler( + self._client, GetMyRecordsRequest(raw_request)) + case "GetRandomRecords": + raise NotImplementedError() + case "GetRecordLimit": + raise NotImplementedError() + case "RateRecord": + raise NotImplementedError() + case "SearchForRecords": + return SearchForRecordsHandler(self._client, SearchForRecordsRequest(raw_request)) + case "UpdateRecord": + raise NotImplementedError() + case _: + self._client.log_error(f"Unknown {name} request received") + return None diff --git a/src/frontends/gamespy/protocols/web_services/modules/altas/___init__.py b/src/frontends/gamespy/protocols/web_services/modules/altas/___init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/gamespy/protocols/web_services/modules/auth/abstractions/general.py b/src/frontends/gamespy/protocols/web_services/modules/auth/abstractions/general.py new file mode 100644 index 000000000..ca98e2da5 --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/modules/auth/abstractions/general.py @@ -0,0 +1,114 @@ +import hashlib +import frontends.gamespy.protocols.web_services.abstractions.contracts as lib +from frontends.gamespy.protocols.web_services.aggregations.soap_envelop import SoapEnvelop +from frontends.gamespy.protocols.web_services.applications.client import ClientInfo +from frontends.gamespy.protocols.web_services.modules.auth.exceptions.general import AuthException +import datetime + +NAMESPACE = "http://gamespy.net/AuthService/" + + +class LoginRequestBase(lib.RequestBase): + version: int + partner_code: int + namespace_id: int + + def parse(self) -> None: + super().parse() + version_node = self._content_element.find( + f".//{{{NAMESPACE}}}version") + if version_node is None or version_node.text is None: + raise AuthException("version is missing from the request.") + self.version = int(version_node.text) + partner_id_node = self._content_element.find( + f".//{{{NAMESPACE}}}partnercode") + if partner_id_node is None or partner_id_node.text is None: + raise AuthException("partner id is missing from the request.") + self.partner_code = int(partner_id_node.text) + namespace_id_node = self._content_element.find( + f".//{{{NAMESPACE}}}namespaceid") + if namespace_id_node is None or namespace_id_node.text is None: + raise AuthException("namespace id is missing from the request.") + self.namespace_id = int(namespace_id_node.text) + + +class LoginResultBase(lib.ResultBase): + response_code: int = 0 + length: int = 303 + user_id: int + profile_id: int + profile_nick: str + unique_nick: str + cdkey_hash: str + version: int + namespace_id: int + partner_code: int + + +class LoginResponseBase(lib.ResponseBase): + _result: LoginResultBase + _content: SoapEnvelop + _expiretime: int + + def __init__(self, result: LoginResultBase) -> None: + assert isinstance(result, LoginResultBase) + super().__init__(result) + self._expiretime = int( + (datetime.datetime.now() + datetime.timedelta(days=1)).timestamp() + ) + + def build(self) -> None: + self._build_context() + super().build() + + def _build_context(self): + self._content.add("responseCode", "0") + self._content.add("certificate") + self._content.add("length", self._result.length) + self._content.add("version", self._result.version) + self._content.add("partnercode", self._result.partner_code) + self._content.add("namespaceid", self._result.namespace_id) + self._content.add("userid", self._result.user_id) + self._content.add("profileid", self._result.profile_id) + self._content.add("expiretime", self._expiretime) + self._content.add("profilenick", self._result.profile_nick) + self._content.add("uniquenick", self._result.unique_nick) + self._content.add("cdkeyhash", self._result.cdkey_hash) + self._content.add("peerkeymodulus", ClientInfo.PEER_KEY_MODULUS) + self._content.add("peerkeyexponent", ClientInfo.PEER_KEY_EXPONENT) + self._content.add("serverdata", ClientInfo.SERVER_DATA) + hash_str = self.__compute_hash() + self._content.add("signature", ClientInfo.SIGNATURE_PREFIX + hash_str) + self._content.go_to_content_element() + self._content.add("peerkeyprivate", ClientInfo.PEER_KEY_EXPONENT) + + def __compute_hash(self) -> str: + """return md5 str""" + data_to_hash = bytearray() + data_to_hash.extend( + self._result.length.to_bytes(4, byteorder="little")) + data_to_hash.extend( + self._result.version.to_bytes(4, byteorder="little")) + data_to_hash.extend( + self._result.partner_code.to_bytes(4, byteorder="little")) + data_to_hash.extend( + self._result.namespace_id.to_bytes(4, byteorder="little")) + data_to_hash.extend( + self._result.user_id.to_bytes(4, byteorder="little")) + data_to_hash.extend( + self._result.profile_id.to_bytes(4, byteorder="little")) + data_to_hash.extend(self._expiretime.to_bytes(4, byteorder="little")) + data_to_hash.extend(self._result.profile_nick.encode("ascii")) + data_to_hash.extend(self._result.unique_nick.encode("ascii")) + data_to_hash.extend(self._result.cdkey_hash.encode("ascii")) + + data_to_hash.extend(bytes.fromhex(ClientInfo.PEER_KEY_MODULUS)) + data_to_hash.append(0x01) + + # server data should be convert to bytes[128] then added to list + data_to_hash.extend(bytes.fromhex(ClientInfo.SERVER_DATA)) + + hash_object = hashlib.md5() + hash_object.update(data_to_hash) + hash_string = hash_object.hexdigest() + return hash_string diff --git a/src/frontends/gamespy/protocols/web_services/modules/auth/applications/handlers.py b/src/frontends/gamespy/protocols/web_services/modules/auth/applications/handlers.py new file mode 100644 index 000000000..d2a1f156d --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/modules/auth/applications/handlers.py @@ -0,0 +1,118 @@ +from frontends.gamespy.protocols.web_services.abstractions.contracts import RequestBase +from frontends.gamespy.protocols.web_services.abstractions.handler import CmdHandlerBase +from frontends.gamespy.protocols.web_services.applications.client import Client +from frontends.gamespy.protocols.web_services.modules.auth.contracts.requests import ( + CreateUserAccountRequest, + LoginProfileRequest, + LoginProfileWithGameIdRequest, + LoginPs3CertRequest, + LoginPs3CertWithGameIdRequest, + LoginRemoteAuthRequest, + LoginRemoteAuthWithGameIdRequest, + LoginUniqueNickRequest, + LoginUniqueNickWithGameIdRequest, +) +from frontends.gamespy.protocols.web_services.modules.auth.contracts.responses import ( + CreateUserAccountResponse, + LoginProfileResponse, + LoginProfileWithGameIdResponse, + LoginPs3CertResponse, + LoginPs3CertWithGameIdResponse, + LoginRemoteAuthResponse, + LoginRemoteAuthWithGameIdResponse, + LoginUniqueNickResponse, + LoginUniqueNickWithGameIdResponse, +) +from frontends.gamespy.protocols.web_services.modules.auth.contracts.results import ( + CreateUserAccountResult, + LoginProfileResult, + LoginPs3CertResult, + LoginRemoteAuthResult, + LoginUniqueNickResult, +) + + +class LoginProfileHandler(CmdHandlerBase): + _request: LoginProfileRequest + _result: LoginProfileResult + + def __init__(self, client: Client, request: RequestBase) -> None: + super().__init__(client, request) + self._result_cls = LoginProfileResult + self._response_cls = LoginProfileResponse + + +class LoginProfileWithGameIdHandler(CmdHandlerBase): + _request: LoginProfileWithGameIdRequest + _result: LoginProfileResult + _response: LoginProfileWithGameIdResponse + + def __init__(self, client: Client, request: LoginProfileWithGameIdRequest) -> None: + super().__init__(client, request) + + +class LoginPs3CertHandler(CmdHandlerBase): + _request: LoginPs3CertRequest + _result: LoginPs3CertResult + _response: LoginPs3CertResponse + + def __init__(self, client: Client, request: LoginPs3CertRequest) -> None: + super().__init__(client, request) + + +class LoginPs3CertWithGameIdHandler(CmdHandlerBase): + _request: LoginPs3CertWithGameIdRequest + _result: LoginPs3CertResult + _response: LoginPs3CertWithGameIdResponse + + def __init__(self, client: Client, request: LoginPs3CertRequest) -> None: + super().__init__(client, request) + + +class LoginRemoteAuthHandler(CmdHandlerBase): + _request: LoginRemoteAuthRequest + _result: LoginRemoteAuthResult + _response: LoginRemoteAuthResponse + + def __init__(self, client: Client, request: LoginRemoteAuthRequest) -> None: + super().__init__(client, request) + self._result_cls = LoginRemoteAuthResult + self._response_cls = LoginRemoteAuthResponse + + +class LoginRemoteAuthWithGameIdHandler(CmdHandlerBase): + _request: LoginRemoteAuthWithGameIdRequest + _result: LoginRemoteAuthResult + _response: LoginRemoteAuthWithGameIdResponse + + def __init__(self, client: Client, request: LoginRemoteAuthWithGameIdRequest) -> None: + super().__init__(client, request) + + +class LoginUniqueNickHandler(CmdHandlerBase): + _request: LoginUniqueNickRequest + _result: LoginUniqueNickResult + _response: LoginUniqueNickResponse + + def __init__(self, client: Client, request: LoginUniqueNickRequest) -> None: + super().__init__(client, request) + + +class LoginUniqueNickWithGameIdHandler(CmdHandlerBase): + _request: LoginUniqueNickWithGameIdRequest + _result: LoginUniqueNickResult + _response: LoginUniqueNickWithGameIdResponse + + def __init__(self, client: Client, request: LoginUniqueNickWithGameIdRequest) -> None: + assert isinstance(request, LoginUniqueNickWithGameIdRequest) + super().__init__(client, request) + + +class CreateUserAccountHandler(CmdHandlerBase): + _request: CreateUserAccountRequest + _result: CreateUserAccountResult + _response: CreateUserAccountResponse + + def __init__(self, client: Client, request: CreateUserAccountRequest) -> None: + assert isinstance(request, CreateUserAccountRequest) + super().__init__(client, request) diff --git a/src/frontends/gamespy/protocols/web_services/modules/auth/contracts/requests.py b/src/frontends/gamespy/protocols/web_services/modules/auth/contracts/requests.py new file mode 100644 index 000000000..bb29de391 --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/modules/auth/contracts/requests.py @@ -0,0 +1,177 @@ +from frontends.gamespy.protocols.web_services.modules.auth.abstractions.general import ( + NAMESPACE, + LoginRequestBase, +) +from frontends.gamespy.protocols.web_services.modules.auth.exceptions.general import AuthException + + +class LoginProfileRequest(LoginRequestBase): + email: str + nick: str + cdkey: str + password: str + + def parse(self) -> None: + super().parse() + email = self._content_element.find(f".//{{{NAMESPACE}}}email") + if email is None or email.text is None: + raise AuthException("email is missing") + self.email = email.text + + nick = self._content_element.find( + f".//{{{NAMESPACE}}}profilenick") + if nick is None or nick.text is None: + raise AuthException("uniquenick is missing") + self.nick = nick.text + + password = self._content_element.find( + f".//{{{NAMESPACE}}}password//{{{NAMESPACE}}}Value") + if password is None or password.text is None: + raise AuthException("password is missing") + self.password = password.text + + +class LoginProfileWithGameIdRequest(LoginProfileRequest): + game_id: int + + def parse(self) -> None: + super().parse() + game_id = self._content_element.find(f".//{{{NAMESPACE}}}gameid") + if game_id is None or game_id.text is None: + raise AuthException("game id is missing") + + self.game_id = int(game_id.text) + + +class LoginPs3CertRequest(LoginRequestBase): + ps3_cert: str + game_id: int + npticket: str + + def parse(self) -> None: + super().parse() + ps3_cert = self._content_element.find( + f".//{{{NAMESPACE}}}ps3sert") + if ps3_cert is None or ps3_cert.text is None: + raise AuthException("ps3cert is missing from the request") + self.ps3_cert = ps3_cert.text + + game_id = self._content_element.find(f".//{{{NAMESPACE}}}gameid") + if game_id is None or game_id.text is None: + raise AuthException("game id is missing") + self.game_id = int(game_id.text) + + npticket = self._content_element.find(f".//{{{NAMESPACE}}}npticket") + if npticket is None or npticket.text is None: + raise AuthException("npticket is missing") + self.npticket = npticket.text + + +class LoginPs3CertWithGameIdRequest(LoginPs3CertRequest): + game_id: int + + def parse(self) -> None: + super().parse() + game_id = self._content_element.find(f".//{{{NAMESPACE}}}gameid") + if game_id is None or game_id.text is None: + raise AuthException("game id is missing") + self.game_id = int(game_id.text) + + +class LoginRemoteAuthRequest(LoginRequestBase): + auth_token: str + challenge: str + + def parse(self) -> None: + super().parse() + auth_token = self._content_element.find( + f".//{{{NAMESPACE}}}authtoken") + if auth_token is None or auth_token.text is None: + raise AuthException("authtoken is missing") + self.auth_token = auth_token.text + + challenge = self._content_element.find( + f".//{{{NAMESPACE}}}challenge") + if challenge is None or challenge.text is None: + raise AuthException("challenge is missing") + self.challenge = challenge.text + + game_id = self._content_element.find(f".//{{{NAMESPACE}}}gameid") + if game_id is None or game_id.text is None: + raise AuthException("game id is missing") + self.game_id = int(game_id.text) + + +class LoginRemoteAuthWithGameIdRequest(LoginRemoteAuthRequest): + game_id: int + + def parse(self) -> None: + super().parse() + game_id = self._content_element.find(f".//{{{NAMESPACE}}}gameid") + if game_id is None or game_id.text is None: + raise AuthException("game id is missing") + + self.game_id = int(game_id.text) + + +class LoginUniqueNickRequest(LoginRequestBase): + uniquenick: str + password: str + + def parse(self) -> None: + super().parse() + unique_nick_node = self._content_element.find( + f".//{{{NAMESPACE}}}uniquenick") + if unique_nick_node is None or unique_nick_node.text is None: + raise AuthException("uniquenick is missing") + self.uniquenick = unique_nick_node.text + + password = self._content_element.find( + f".//{{{NAMESPACE}}}password//{{{NAMESPACE}}}Value") + if password is None or password.text is None: + raise AuthException("password is missing") + self.password = password.text + + +class LoginUniqueNickWithGameIdRequest(LoginUniqueNickRequest): + game_id: int + + def parse(self) -> None: + super().parse() + game_id = self._content_element.find(f".//{{{NAMESPACE}}}gameid") + if game_id is None or game_id.text is None: + raise AuthException("game id is missing") + + self.game_id = int(game_id.text) + + +class CreateUserAccountRequest(LoginRequestBase): + email: str + nick: str + uniquenick: str + password: str + + def parse(self) -> None: + super().parse() + email = self._content_element.find(f".//{{{NAMESPACE}}}email") + if email is None or email.text is None: + raise AuthException("email is missing") + self.email = email.text + + nick = self._content_element.find( + f".//{{{NAMESPACE}}}profilenick") + if nick is None or nick.text is None: + raise AuthException("password is missing") + self.nick = nick.text + + uniquenick = self._content_element.find( + f".//{{{NAMESPACE}}}uniquenick") + if uniquenick is None or uniquenick.text is None: + raise AuthException("password is missing") + self.uniquenick = uniquenick.text + + password = self._content_element.find( + f".//{{{NAMESPACE}}}password//{{{NAMESPACE}}}Value") + if password is None or password.text is None: + raise AuthException("password is missing") + self.password = password.text diff --git a/src/frontends/gamespy/protocols/web_services/modules/auth/contracts/responses.py b/src/frontends/gamespy/protocols/web_services/modules/auth/contracts/responses.py new file mode 100644 index 000000000..31090a92e --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/modules/auth/contracts/responses.py @@ -0,0 +1,79 @@ +from frontends.gamespy.protocols.web_services.aggregations.soap_envelop import SoapEnvelop +from frontends.gamespy.protocols.web_services.modules.auth.abstractions.general import LoginResponseBase +from frontends.gamespy.protocols.web_services.modules.auth.contracts.requests import ( + LoginProfileRequest, + LoginProfileWithGameIdRequest, +) +from frontends.gamespy.protocols.web_services.modules.auth.contracts.results import ( + LoginProfileResult, + LoginPs3CertResult, +) + + +class LoginProfileResponse(LoginResponseBase): + _request: LoginProfileRequest + _result: LoginProfileResult + + def build(self) -> None: + self._content = SoapEnvelop("LoginProfileResult") + super().build() + + +class LoginProfileWithGameIdResponse(LoginResponseBase): + _request: LoginProfileWithGameIdRequest + + def build(self) -> None: + self._content = SoapEnvelop("LoginProfileWithGameIdResult") + super().build() + + +class LoginPs3CertResponse(LoginResponseBase): + _result: LoginPs3CertResult + + def build(self) -> None: + self._content = SoapEnvelop("LoginPs3CertResult") + self._content.add("responseCode", self._result.response_code) + self._content.add("authToken", self._result.auth_token) + self._content.add("partnerChallenge", self._result.partner_challenge) + super().build() + + +class LoginPs3CertWithGameIdResponse(LoginResponseBase): + _result: LoginPs3CertResult + + def build(self) -> None: + self._content = SoapEnvelop("LoginPs3CertWithGameIdResult") + self._content.add("responseCode", self._result.response_code) + self._content.add("authToken", self._result.auth_token) + self._content.add("partnerChallenge", self._result.partner_challenge) + super().build() + + +class LoginRemoteAuthResponse(LoginResponseBase): + def build(self) -> None: + self._content = SoapEnvelop("LoginRemoteAuthResult") + super().build() + + +class LoginRemoteAuthWithGameIdResponse(LoginResponseBase): + def build(self) -> None: + self._content = SoapEnvelop("LoginRemoteAuthWithGameIdResult") + super().build() + + +class LoginUniqueNickResponse(LoginResponseBase): + def build(self) -> None: + self._content = SoapEnvelop("LoginUniqueNickResult") + super().build() + + +class LoginUniqueNickWithGameIdResponse(LoginResponseBase): + def build(self) -> None: + self._content = SoapEnvelop("LoginUniqueNickWithGameIdResult") + super().build() + + +class CreateUserAccountResponse(LoginResponseBase): + def build(self) -> None: + self._content = SoapEnvelop("CreateUserAccountResult") + super().build() diff --git a/src/frontends/gamespy/protocols/web_services/modules/auth/contracts/results.py b/src/frontends/gamespy/protocols/web_services/modules/auth/contracts/results.py new file mode 100644 index 000000000..30c8cea3c --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/modules/auth/contracts/results.py @@ -0,0 +1,22 @@ +from frontends.gamespy.protocols.web_services.modules.auth.abstractions.general import LoginResultBase + + +class LoginProfileResult(LoginResultBase): + pass + + +class LoginPs3CertResult(LoginResultBase): + auth_token: str + partner_challenge: str + + +class LoginRemoteAuthResult(LoginResultBase): + pass + + +class LoginUniqueNickResult(LoginResultBase): + pass + + +class CreateUserAccountResult(LoginResultBase): + pass diff --git a/src/frontends/gamespy/protocols/web_services/modules/auth/exceptions/general.py b/src/frontends/gamespy/protocols/web_services/modules/auth/exceptions/general.py new file mode 100644 index 000000000..7bed127fd --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/modules/auth/exceptions/general.py @@ -0,0 +1,5 @@ +from frontends.gamespy.protocols.web_services.aggregations.exceptions import WebException + + +class AuthException(WebException): + pass diff --git a/src/frontends/gamespy/protocols/web_services/modules/direct2game/abstractions/contracts.py b/src/frontends/gamespy/protocols/web_services/modules/direct2game/abstractions/contracts.py new file mode 100644 index 000000000..6f4d0cfc8 --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/modules/direct2game/abstractions/contracts.py @@ -0,0 +1,16 @@ +import frontends.gamespy.protocols.web_services.abstractions.contracts as lib +from frontends.gamespy.protocols.web_services.aggregations.soap_envelop import SoapEnvelop + +NAMESPACE = "http://gamespy.net/commerce/" + + +class RequestBase(lib.RequestBase): + pass + + +class ResultBase(lib.ResultBase): + pass + + +class ResponseBase(lib.ResponseBase): + _content: SoapEnvelop \ No newline at end of file diff --git a/src/frontends/gamespy/protocols/web_services/modules/direct2game/abstractions/handler.py b/src/frontends/gamespy/protocols/web_services/modules/direct2game/abstractions/handler.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/gamespy/protocols/web_services/modules/direct2game/applications/handlers.py b/src/frontends/gamespy/protocols/web_services/modules/direct2game/applications/handlers.py new file mode 100644 index 000000000..b3f39d391 --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/modules/direct2game/applications/handlers.py @@ -0,0 +1,34 @@ +from frontends.gamespy.protocols.web_services.abstractions.handler import CmdHandlerBase +from frontends.gamespy.protocols.web_services.applications.client import Client +from frontends.gamespy.protocols.web_services.modules.direct2game.contracts.requests import ( + GetPurchaseHistoryRequest, + GetStoreAvailabilityRequest, +) +from frontends.gamespy.protocols.web_services.modules.direct2game.contracts.responses import ( + GetPurchaseHistoryResponse, + GetStoreAvailabilityResponse, +) +from frontends.gamespy.protocols.web_services.modules.direct2game.contracts.results import ( + GetPurchaseHistoryResult, + GetStoreAvailabilityResult, +) + + +class GetPurchaseHistoryHandler(CmdHandlerBase): + _request: GetPurchaseHistoryRequest + _result: GetPurchaseHistoryResult + _response: GetPurchaseHistoryResponse + + def __init__(self, client: Client, request: GetPurchaseHistoryRequest) -> None: + assert isinstance(request, GetPurchaseHistoryRequest) + super().__init__(client, request) + + +class GetStoreAvailabilityHandler(CmdHandlerBase): + _request: GetStoreAvailabilityRequest + _result: GetStoreAvailabilityResult + _response: GetStoreAvailabilityResponse + + def __init__(self, client: Client, request: GetStoreAvailabilityRequest) -> None: + assert isinstance(request, GetStoreAvailabilityRequest) + super().__init__(client, request) diff --git a/src/frontends/gamespy/protocols/web_services/modules/direct2game/contracts/requests.py b/src/frontends/gamespy/protocols/web_services/modules/direct2game/contracts/requests.py new file mode 100644 index 000000000..6db32b4a2 --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/modules/direct2game/contracts/requests.py @@ -0,0 +1,67 @@ +from frontends.gamespy.protocols.web_services.aggregations.exceptions import WebException +from frontends.gamespy.protocols.web_services.modules.direct2game.abstractions.contracts import ( + NAMESPACE, + RequestBase, +) + + +class GetPurchaseHistoryRequest(RequestBase): + game_id: int + access_token: str + proof: str + certificate: str + + def parse(self) -> None: + super().parse() + game_id = self._content_element.find(f".//{{{NAMESPACE}}}gameid") + if game_id is None or game_id.text is None: + raise WebException("gameid is missing from the request.") + self.game_id = int(game_id.text) + + proof = self._content_element.find(f".//{{{NAMESPACE}}}proof") + if proof is None or proof.text is None: + raise WebException("proof is missing from the request.") + self.proof = proof.text + + access_token = self._content_element.find( + f".//{{{NAMESPACE}}}access_token" + ) + + if access_token is None or access_token.text is None: + raise WebException("access_token is missing from the request.") + self.access_token = access_token.text + + certificate = self._content_element.find( + f".//{{{NAMESPACE}}}certificate") + if certificate is None or certificate.text is None: + raise WebException("certificate is missing from the request.") + self.certificate = certificate.text + + +class GetStoreAvailabilityRequest(RequestBase): + game_id: int + version: int + region: str + access_token: str + + def parse(self) -> None: + super().parse() + game_id = self._content_element.find(f".//{{{NAMESPACE}}}gameid") + if game_id is None or game_id.text is None: + raise WebException("gameid is missing from the request.") + self.game_id = int(game_id.text) + version = self._content_element.find(f".//{{{NAMESPACE}}}version") + if version is None or version.text is None: + raise WebException("version is missing from the request.") + self.version = int(version.text) + region = self._content_element.find(f".//{{{NAMESPACE}}}region") + if region is None or region.text is None: + raise WebException("region is missing from the request.") + self.region = region.text + + access_token = self._content_element.find( + f".//{{{NAMESPACE}}}accesstoken") + + if access_token is None or access_token.text is None: + raise WebException("accesstoken is missing from the request.") + self.access_token = access_token.text diff --git a/src/frontends/gamespy/protocols/web_services/modules/direct2game/contracts/responses.py b/src/frontends/gamespy/protocols/web_services/modules/direct2game/contracts/responses.py new file mode 100644 index 000000000..cc7e30523 --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/modules/direct2game/contracts/responses.py @@ -0,0 +1,32 @@ +from frontends.gamespy.protocols.web_services.abstractions.contracts import ResultBase +from frontends.gamespy.protocols.web_services.aggregations.soap_envelop import SoapEnvelop +from frontends.gamespy.protocols.web_services.modules.direct2game.abstractions.contracts import ResponseBase +from frontends.gamespy.protocols.web_services.modules.direct2game.contracts.results import ( + GetPurchaseHistoryResult, + GetStoreAvailabilityResult, +) + + +class GetPurchaseHistoryResponse(ResponseBase): + _result: GetPurchaseHistoryResult + + def build(self) -> None: + self._content = SoapEnvelop("GetPurchaseHistoryResult") + self._content.add("status") + self._content.add("code", self._result.code) + self._content.change_to_element("GetPurchaseHistoryResult") + self._content.add("orderpurchases") + self._content.add("count", 0) + super().build() + + +class GetStoreAvailabilityResponse(ResponseBase): + _result: GetStoreAvailabilityResult + + def build(self) -> None: + self._content = SoapEnvelop("GetStoreAvailabilityResult") + self._content.add("status") + self._content.add("code", self._result.code) + self._content.change_to_element("GetStoreAvailabilityResult") + self._content.add("storestatusid", int(self._result.store_status_id)) + super().build() diff --git a/src/frontends/gamespy/protocols/web_services/modules/direct2game/contracts/results.py b/src/frontends/gamespy/protocols/web_services/modules/direct2game/contracts/results.py new file mode 100644 index 000000000..97cf1e2b4 --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/modules/direct2game/contracts/results.py @@ -0,0 +1,19 @@ +from enum import IntEnum + +from frontends.gamespy.protocols.web_services.modules.direct2game.abstractions.contracts import ResultBase + + +class GetPurchaseHistoryResult(ResultBase): + code: int = 0 + + +class AvailableCode(IntEnum): + STORE_ONLINE = 10 + STORE_OFFLINE_FOR_MAINTAIN = 20 + STORE_OFFLINE_RETIRED = 50 + STORE_NOT_YET_LAUNCHED = 100 + + +class GetStoreAvailabilityResult(ResultBase): + code: int = 0 + store_status_id: AvailableCode = AvailableCode.STORE_ONLINE diff --git a/src/frontends/gamespy/protocols/web_services/modules/sake/abstractions/generals.py b/src/frontends/gamespy/protocols/web_services/modules/sake/abstractions/generals.py new file mode 100644 index 000000000..a2887eee7 --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/modules/sake/abstractions/generals.py @@ -0,0 +1,62 @@ +import frontends.gamespy.protocols.web_services.abstractions.handler as h +import frontends.gamespy.protocols.web_services.abstractions.contracts as lib +from frontends.gamespy.protocols.web_services.aggregations.soap_envelop import SoapEnvelop +from frontends.gamespy.protocols.web_services.modules.sake.exceptions.general import SakeException +import xml.etree.ElementTree as ET + +NAMESPACE = "http://gamespy.net/sake" + + +class RequestBase(lib.RequestBase): + game_id: int + secret_key: str + login_ticket: str + table_id: str + + def parse(self) -> None: + super().parse() + game_id = self._content_element.find(f".//{{{NAMESPACE}}}gameid") + if game_id is None or game_id.text is None: + raise SakeException("gameid is missing from the request.") + self.game_id = int(game_id.text) + + secret_key = self._content_element.find( + f".//{{{NAMESPACE}}}secretKey") + if secret_key is None or secret_key.text is None: + raise SakeException("secretkey id is missing from the request.") + self.secret_key = secret_key.text + + login_ticket = self._content_element.find( + f".//{{{NAMESPACE}}}loginTicket") + if login_ticket is None or login_ticket.text is None: + raise SakeException("loginTicket is missing from the request.") + self.login_ticket = login_ticket.text + + table_id = self._content_element.find( + f".//{{{NAMESPACE}}}tableid") + if table_id is None or table_id.text is None: + raise SakeException("tableid is missing from the request.") + self.table_id = table_id.text + + @staticmethod + def remove_namespace(tree: ET.Element): + tree.tag = tree.tag.split('}', 1)[-1] + for elem in tree: + # Remove the namespace by splitting the tag + # Keep the part after the '}' + elem.tag = elem.tag.split('}', 1)[-1] + return tree + + +class ResultBase(lib.ResultBase): + pass + + +class ResponseBase(lib.ResponseBase): + def __init__(self, result: ResultBase) -> None: + super().__init__(result) + + +class CmdHandlerBase(h.CmdHandlerBase): + _request: "RequestBase" + _result: "ResultBase" diff --git a/src/frontends/gamespy/protocols/web_services/modules/sake/applications/handlers.py b/src/frontends/gamespy/protocols/web_services/modules/sake/applications/handlers.py new file mode 100644 index 000000000..6588ec29f --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/modules/sake/applications/handlers.py @@ -0,0 +1,35 @@ +from frontends.gamespy.protocols.web_services.applications.client import Client +from frontends.gamespy.protocols.web_services.modules.sake.abstractions.generals import CmdHandlerBase +from frontends.gamespy.protocols.web_services.modules.sake.contracts.requests import CreateRecordRequest, GetMyRecordsRequest, SearchForRecordsRequest +from frontends.gamespy.protocols.web_services.modules.sake.contracts.responses import CreateRecordResponse, GetMyRecordResponse, SearchForRecordsResponse +from frontends.gamespy.protocols.web_services.modules.sake.contracts.results import CreateRecordResult, GetMyRecordsResult, SearchForRecordsResult + + +class CreateRecordHandler(CmdHandlerBase): + _request: CreateRecordRequest + _result: CreateRecordResult + _response: CreateRecordResponse + + def __init__(self, client: Client, request: CreateRecordRequest) -> None: + assert isinstance(request, CreateRecordRequest) + super().__init__(client, request) + + +class GetMyRecordsHandler(CmdHandlerBase): + _request: GetMyRecordsRequest + _result: GetMyRecordsResult + _response: GetMyRecordResponse + + def __init__(self, client: Client, request: GetMyRecordsRequest) -> None: + assert isinstance(request, GetMyRecordsRequest) + super().__init__(client, request) + + +class SearchForRecordsHandler(CmdHandlerBase): + _request: SearchForRecordsRequest + _result: SearchForRecordsResult + _response: SearchForRecordsResponse + + def __init__(self, client: Client, request: SearchForRecordsRequest) -> None: + assert isinstance(request, SearchForRecordsRequest) + super().__init__(client, request) diff --git a/src/frontends/gamespy/protocols/web_services/modules/sake/contracts/requests.py b/src/frontends/gamespy/protocols/web_services/modules/sake/contracts/requests.py new file mode 100644 index 000000000..b5dfe0962 --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/modules/sake/contracts/requests.py @@ -0,0 +1,262 @@ + +import xml.etree.ElementTree as ET + +from frontends.gamespy.protocols.web_services.aggregations.exceptions import WebException +from frontends.gamespy.protocols.web_services.modules.sake.abstractions.generals import ( + RequestBase, + NAMESPACE, +) +import xmltodict + +from frontends.gamespy.protocols.web_services.modules.sake.exceptions.general import SakeException + + +class CreateRecordRequest(RequestBase): + values: list[tuple[str, str, str]] = [] + """ + (name,type,value) + """ + + def parse(self) -> None: + super().parse() + values = self._content_element.find(f".//{{{NAMESPACE}}}values") + if values is None: + raise SakeException("values is missing from request") + record_fields = values.findall(f".//{{{NAMESPACE}}}RecordField") + for f in record_fields: + temp = [] + name = f.find(f".//{{{NAMESPACE}}}name") + if name is None or name.text is None: + raise WebException("name can not be None") + temp.append(name.text) + value = f.find(f".//{{{NAMESPACE}}}value") + if value is None or value.text is None: + raise WebException("value can not be None") + for v in value: + temp.append(v.tag.split("}")[1]) + for i in v: + temp.append(i.text) + + self.values.append(tuple(temp)) + + +class DeleteRecordRequest(RequestBase): + record_id: int + + def parse(self) -> None: + super().parse() + record_id = self._content_element.find(f".//{{{NAMESPACE}}}recordid") + + if record_id is None or record_id.text is None: + raise SakeException("recordid is missing from request") + + self.record_id = int(record_id.text) + + +class GetMyRecordsRequest(RequestBase): + fields: list[tuple[str | None, str]] + + def __init__(self, raw_request: str) -> None: + super().__init__(raw_request) + self.fields = [] + + def parse(self) -> None: + super().parse() + fields = self._content_element.find(f".//{{{NAMESPACE}}}fields") + if fields is None: + raise SakeException("fields is missing from request") + for e in fields: + data = (e.text, e.tag.split("}")[1]) + if data is None: + raise WebException("data can not be None") + self.fields.append(data) + + +class GetRandomRecordsRequest(RequestBase): + max: int + fields: list[tuple[str | None, str]] = [] + + def parse(self) -> None: + super().parse() + max = self._content_element.find(f".//{{{NAMESPACE}}}max") + if max is None or max.text is None: + raise SakeException("max is missing from request") + self.max = int(max.text) + + fields = self._content_element.find(f".//{{{NAMESPACE}}}fields") + if fields is None: + raise SakeException("fields is missing from request") + for e in fields: + data = (e.text, e.tag.split("}")[1]) + if data is None: + raise WebException("data can not be None") + self.fields.append(data) + + +class GetRecordLimitRequest(RequestBase): + pass + + +class GetSpecificRecordsRequest(RequestBase): + + record_ids: list[tuple] = [] + """ + [ + (field_name,field_type), + (field_name,field_type), + (field_name,field_type), + ... + (field_name,field_type) + ] + """ + fields: list[tuple] = [] + """ + [ + (field_name,field_type), + (field_name,field_type), + (field_name,field_type), + ... + (field_name,field_type) + ] + """ + + def parse(self) -> None: + super().parse() + record_ids = self._content_element.find( + f".//{{{NAMESPACE}}}recordids") + if record_ids is None: + raise SakeException("No record id found.") + for e in record_ids: + data = (e.text, e.tag.split("}")[1]) + self.record_ids.append(data) + fields = self._content_element.find( + f".//{{{NAMESPACE}}}fields") + if fields is None: + raise SakeException("No record id found.") + + for e in fields: + data = (e.text, e.tag.split("}")[1]) + self.fields.append(data) + + +class RateRecordRequest(RequestBase): + record_id: str + rating: str + + def parse(self) -> None: + super().parse() + record_id = self._content_element.find( + f".//{{{NAMESPACE}}}recordid") + if record_id is None or record_id.text is None: + raise SakeException("No record id found.") + self.record_id = record_id.text + + rating = self._content_element.find( + f".//{{{NAMESPACE}}}rating") + if rating is None or rating.text is None: + raise SakeException("No rating found.") + self.rating = rating.text + + +class SearchForRecordsRequest(RequestBase): + filter: str | None + sort: str | None + offset: str + max: str + surrounding: str + owner_ids: str | None + cache_flag: str + fields: list[tuple[str | None, str]] + """ + [ + (field_name,field_type), + (field_name,field_type), + (field_name,field_type), + ... + (field_name,field_type) + ] + """ + + def parse(self) -> None: + super().parse() + filter = self._content_element.find( + f".//{{{NAMESPACE}}}filter") + if filter is None: + raise SakeException("No filter found.") + self.filter = filter.text + + sort = self._content_element.find( + f".//{{{NAMESPACE}}}sort") + if sort is None: + raise SakeException("No sort found.") + self.sort = sort.text + + offset = self._content_element.find( + f".//{{{NAMESPACE}}}offset") + if offset is None or offset.text is None: + raise SakeException("No offset found.") + self.offset = offset.text + + vmax = self._content_element.find( + f".//{{{NAMESPACE}}}max") + if vmax is None or vmax.text is None: + raise SakeException("No max found.") + self.max = vmax.text + + surrounding = self._content_element.find( + f".//{{{NAMESPACE}}}surrounding") + if surrounding is None or surrounding.text is None: + raise SakeException("No surrounding found.") + self.surrounding = surrounding.text + + owner_ids = self._content_element.find( + f".//{{{NAMESPACE}}}ownerids") + if owner_ids is None: + raise SakeException("No ownderids found.") + self.owner_ids = owner_ids.text + + cache_flag = self._content_element.find( + f".//{{{NAMESPACE}}}cacheFlag") + if cache_flag is None or cache_flag.text is None: + raise SakeException("No cache flag found.") + self.cache_flag = cache_flag.text + + fields = self._content_element.find( + f".//{{{NAMESPACE}}}fields") + self.fields = [] + if fields is None: + raise SakeException("No record id found.") + for e in fields: + data = (e.text, e.tag.split("}")[1]) + if data is not None: + self.fields.append(data) + + +class UpdateRecordRequest(RequestBase): + record_id: str + values: list + """ + [ + (field_name,field_type,field_value), + (field_name,field_type,field_value), + (field_name,field_type,field_value), + ... + (field_name,field_type,field_value) + ] + """ + + def parse(self) -> None: + super().parse() + record_id = self._content_element.find( + f".//{{{NAMESPACE}}}recordid") + if record_id is None or record_id.text is None: + raise SakeException("No record id found.") + self.record_id = record_id.text + values_node = self._content_element.find( + f".//{{{NAMESPACE}}}values") + # todo fix this + if values_node is None: + raise WebException("value node can not be none") + temp_str = ET.tostring( + element=values_node, encoding="unicode").replace("ns0:", "") + self.values = xmltodict.parse(temp_str)['values']["RecordField"] diff --git a/src/frontends/gamespy/protocols/web_services/modules/sake/contracts/responses.py b/src/frontends/gamespy/protocols/web_services/modules/sake/contracts/responses.py new file mode 100644 index 000000000..0c105f6db --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/modules/sake/contracts/responses.py @@ -0,0 +1,38 @@ +from frontends.gamespy.protocols.web_services.modules.sake.abstractions.generals import ResponseBase +from frontends.gamespy.protocols.web_services.modules.sake.contracts.requests import CreateRecordRequest, SearchForRecordsRequest +from frontends.gamespy.protocols.web_services.modules.sake.contracts.results import CreateRecordResult, SearchForRecordsResult + + +class CreateRecordResponse(ResponseBase): + _result: "CreateRecordResult" + _request: "CreateRecordRequest" + + def build(self) -> None: + self._content.add("CreateRecordResult") + self._content.add("tableid", self._result.table_id) + self._content.add("recordid", self._result.record_id) + + for field in self._result.fields: + self._content.add("fields", field) + + super().build() + + +class GetMyRecordResponse(ResponseBase): + pass + + +class SearchForRecordsResponse(ResponseBase): + _result: "SearchForRecordsResult" + _request: "SearchForRecordsRequest" + + def build(self) -> None: + self._content.add("SearchForRecordsResponse") + self._content.add("SearchForRecordsResult", "Success") + if self._result.user_data is not None: + for key, value in self._result.user_data.items(): + self._content.add("values", value) + else: + self._content.add("values") + + super().build() diff --git a/src/frontends/gamespy/protocols/web_services/modules/sake/contracts/results.py b/src/frontends/gamespy/protocols/web_services/modules/sake/contracts/results.py new file mode 100644 index 000000000..71c3c5360 --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/modules/sake/contracts/results.py @@ -0,0 +1,22 @@ +from typing import OrderedDict + +from pydantic import BaseModel +from frontends.gamespy.protocols.web_services.modules.sake.abstractions.generals import ResultBase + + +class CreateRecordResult(ResultBase): + table_id: str + record_id: str + fields: list + + +class GetMyRecordsResult(ResultBase): + class GetMyRecordsInfo(BaseModel): + field_name: str + field_type: str + field_value: str + records: list[GetMyRecordsInfo] + + +class SearchForRecordsResult(ResultBase): + user_data: OrderedDict[str, str] diff --git a/src/frontends/gamespy/protocols/web_services/modules/sake/exceptions/general.py b/src/frontends/gamespy/protocols/web_services/modules/sake/exceptions/general.py new file mode 100644 index 000000000..9dba83e7b --- /dev/null +++ b/src/frontends/gamespy/protocols/web_services/modules/sake/exceptions/general.py @@ -0,0 +1,5 @@ +from frontends.gamespy.protocols.web_services.aggregations.exceptions import WebException + + +class SakeException(WebException): + pass diff --git a/src/frontends/tests/__init__.py b/src/frontends/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/tests/gamespy/__init__.py b/src/frontends/tests/gamespy/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/tests/gamespy/chat/__init__.py b/src/frontends/tests/gamespy/chat/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/tests/gamespy/chat/game_tests.py b/src/frontends/tests/gamespy/chat/game_tests.py new file mode 100644 index 000000000..dce6e768e --- /dev/null +++ b/src/frontends/tests/gamespy/chat/game_tests.py @@ -0,0 +1,81 @@ +import unittest + +import responses + +from frontends.tests.gamespy.chat.mock_objects import create_client + + +class GameTests(unittest.TestCase): + @responses.activate + def test_civilization4(self): + raws = [ + "USRIP", + "USER X419pGl4sX|18 127.0.0.1 peerchat.gamespy.com :aa3041ada9385b28fc4d4e47db288769", + "NICK a1701-5", + "CDKEY 81123-67814-77652-27631-11723-47707-22638-10701", + "JOIN #GSP!anno1701 ", + "MODE #GSP!anno1701", + "GETCKEY #GSP!anno1701 * 008 0 :\\b_flags", + "WHO a1701-5", + "JOIN #GSP!anno1701!M9zK0KJaKM ", + "MODE #GSP!anno1701!M9zK0KJaKM", + "SETCKEY #GSP!anno1701 a1701-5 :\\b_flags\\s", + "SETCKEY #GSP!anno1701!M9zK0KJaKM a1701-5 :\\b_flags\\sh", + "GETCKEY #GSP!anno1701!M9zK0KJaKM * 009 0 :\\b_flags", + "TOPIC #GSP!anno1701!M9zK0KJaKM :test", + "MODE #GSP!anno1701!M9zK0KJaKM +l 4", + "MODE #GSP!anno1701!M9zK0KJaKM -i-p-s+m+n+t+l+e 4", + "PART #GSP!anno1701 :", + ] + client = create_client() + for raw in raws: + client.on_received(raw.encode()) + + @responses.activate + def test_worm3d(self): + raws = [ + "CRYPT des 1 worms3\r\n", + "USRIP\r\n", + "USER X419pGl4sX|6 127.0.0.1 peerchat.gamespy.com :aa3041ada9385b28fc4d4e47db288769\r\n", + "NICK worms10\r\n", + "JOIN #GPG!622\r\n", + "MODE #GPG!622\r\n", + "GETCKEY #GPG!622 * 024 0 :\\username\\b_flags\r\n", + "JOIN #GSP!worms3!Ml4lz344lM\r\n", + "MODE #GSP!worms3!Ml4lz344lM\r\n", + "SETCKEY #GPG!622 worms10 :\\b_flags\\s" + "\r\n", + "SETCKEY #GSP!worms3!Ml4lz344lM worms10 :\\b_flags\\sh" + "\r\n", + "GETCKEY #GSP!worms3!Ml4lz344lM * 025 0 :\\username\\b_flags\r\n", + "TOPIC #GSP!worms3!Ml4lz344lM :tesr\r\n", + "MODE #GSP!worms3!Ml4lz344lM +l 2\r\n", + "PART #GPG!622 :Joined staging room\r\n", + "SETCKEY #GSP!worms3!Ml4lz344lM worms10 :\\b_firewall\\1\\b_profileid\\6\\b_ipaddress\\b_publicip\\255.255.255.255\\b_privateip\\192.168.0.60\b_authresponse\\b_gamever\\1073\\b_val\\0\r\n", + "WHO worms10\r\n", + "SETCHANKEY #GSP!worms3!Ml4lz344lM :\\b_hostname\\test\\b_hostport\\b_MaxPlayers\\2\\b_NumPlayers\\1\\b_SchemeChanging\\0\\b_gamever\\1073\\b_gametype\\b_mapname\\Random\\b_firewall\\1\\b_publicip\\255.255.255.255\\b_privateip\\192.168.0.60\\b_gamemode\\openstaging\\b_val\\0\\b_password\\1\r\n", + "GETKEY worms20 026 0 :\\b_firewall\b_profileid\\b_ipaddress\\b_publicip\\b_privateip\\b_authresponse\\b_gamever\\b_val\r\n", + "GETCKEY #GSP!worms3!Ml4lz344lM worms20 027 0 :\\b_firewall\\b_profileid\\b_ipaddress\\b_publicip\\b_privateip\\b_authresponse\\b_gamever\\b_val\r\n", + "SETCHANKEY #GSP!worms3!Ml4lz344lM :\\b_hostname\\test\\b_hostport\\b_MaxPlayers\\2\\b_NumPlayers\\1\\b_SchemeChanging\\0\\b_gamever\\1073\\b_gametype\\b_mapname\\Random\\b_firewall\\1\\b_publicip\\255.255.255.255\\b_privateip\\192.168.0.60\\b_gamemode\\openstaging\\b_val\0\\b_password\\1\r\n", + "SETCHANKEY #GSP!worms3!Ml4lz344lM :\\b_hostname\\test\\b_hostport\\b_MaxPlayers\\2\\b_NumPlayers\\1\\b_SchemeChanging\\0\\b_gamever\\1073\\b_gametype\\b_mapname\\Random\\b_firewall\\1\\b_publicip\\255.255.255.255\\b_privateip\\192.168.0.60\\b_gamemode\\openstaging\\b_val\\0\\b_password\\1\r\n", + "UTM #GSP!worms3!Ml4lz344lM :MDM |Obj|3|Land.Time|0|LogicalSeed|3891226431|GraphicalSeed|3269271590|Land.RealSeed|3281489942|Land.Theme|Pirate.Lumps|LevelToUse|FE.Level.RandomLand|Land.Ind|0|Wormpot.Reel1|17|Wormpot.Reel2|17|Wormpot.Reel3|17|TimeStamp|6206364\r\n", + "UTM #GSP!worms3!Ml4lz344lM :TDM aA\r\n", + "UTM #GSP!worms3!Ml4lz344lM :SDM ASFE.Scheme.StandardCUnAACADCBBCACBBFFBKBB8C/C3C!A!A*C*C None: + super().__init__("test", "ws://test.com", print) + + def subscribe(self): + pass + + def publish_message(self, message): + pass + + def unsubscribe(self): + pass + + @property + def ip_port(self): + return "127.0.0.1:10086" + + +class ClientMock(Client): + def start_brocker(self): + self.brocker = WebSocketBrockerMock() # type:ignore + self.brocker.subscribe() # type:ignore + + +def create_client() -> Client: + CONFIG.unittest.is_raise_except = True + handler = RequestHandlerMock() + logger = LogMock() + config = CONFIG.servers["Chat"] + conn = ConnectionMock( + handler=handler, config=config, t_client=ClientMock, logger=logger + ) + create_mock_url(config, CryptHandler, CryptResult( + secret_key="test").model_dump()) + create_mock_url( + config, LoginHandler, LoginResult(profile_id=1, user_id=1).model_dump() + ) + create_mock_url( + config, + NamesHandler, + NamesResult( + channel_nicks=[NamesResultData(nick_name="test")], + channel_name="test", + requester_nick_name="test1", + ).model_dump(), + ) + create_mock_url(config, QuitHandler, {"message": "ok"}) + create_mock_url(config, UserIPHandler, {"message": "ok"}) + create_mock_url( + config, + JoinHandler, + JoinResult( + joiner_nick_name="nickname", + joiner_user_name="username", + channel_name="#GP!test" + ).model_dump(), + ) + create_mock_url(config, UserHandler, {"message": "ok"}) + create_mock_url(config, CdKeyHandler, {"message": "ok"}) + create_mock_url( + config, + GetCKeyHandler, + + GetCKeyResult + ( + channel_name="test", + infos=[GetCKeyResult.GetCKeyInfos( + nick_name="test_nick", + key_values={"hello": "hi"} + )], + cookie="000", + keys=["hello"] + ).model_dump(), + ) + create_mock_url( + config, + ModeHandler, + ModeResult.model_validate( + { + "channel_name": "test", + "channel_modes": ["n", "m"], + "joiner_nick_name": "test_nick", + } + ).model_dump(), + ) + create_mock_url(config, + SetCKeyHandler, + SetCKeyResult.model_validate( + {"setter_nick_name": "unispy", + "setter_user_name": "unispy", + "channel_name": "#GP!test", + "cookie": "000", + "key_value": {}} + ).model_dump(mode="json")) + create_mock_url( + config, + TopicHandler, + TopicResult(channel_name="test_chan", + channel_topic="test").model_dump(), + ) + create_mock_url( + config, + PartHandler, + PartResult( + leaver_nick_name="nickname", + leaver_user_name="username", + is_channel_creator=False, + channel_name="test_chan", + reason="part" + ).model_dump(), + ) + create_mock_url(config, NickHandler, NickResult( + nick_name="test").model_dump()) + create_mock_url(config, WhoHandler, WhoResult( + infos=[], + request_type=WhoRequestType.GET_CHANNEL_USER_INFO, + channel_name="#GP!test", + nick_name="unispy").model_dump()) + create_mock_url( + config, + SetChannelKeyHandler, + SetChannelKeyResult( + setter_nick_name="nickname", + setter_user_name="username", + channel_name="test", + key_value={} + ).model_dump(), + ) + create_mock_url( + config, GetKeyHandler, GetKeyResult( + nick_name="unispy", values=[], cookie="000").model_dump() + ) + create_mock_url( + config, + UTMHandler, + UtmResult(sender_nick_name="unispy", sender_user_name="unispy", + target_name="unispy", message="hello").model_dump(), + ) + + if TYPE_CHECKING: + conn._client = cast(Client, conn._client) + conn._client.on_connected() + return conn._client + + +if __name__ == "__main__": + create_client() diff --git a/src/frontends/tests/gamespy/chat/request_tests.py b/src/frontends/tests/gamespy/chat/request_tests.py new file mode 100644 index 000000000..4f1351228 --- /dev/null +++ b/src/frontends/tests/gamespy/chat/request_tests.py @@ -0,0 +1,188 @@ +import unittest + +from frontends.gamespy.protocols.chat.aggregates.enums import GetKeyRequestType, MessageType, ModeName, ModeOperation +from frontends.gamespy.protocols.chat.contracts.requests import AtmRequest, GetCKeyRequest, GetChannelKeyRequest, JoinRequest, KickRequest, ModeRequest, NoticeRequest, PartRequest, PrivateRequest, SetCKeyRequest, SetChannelKeyRequest, TopicRequest, UtmRequest + +# region General +CD_KEY = "CDKEY XXXX-XXXX-XXXX-XXXX\r\n" +CRYPT = "CRYPT des 1 gmtest\r\n" +GET_KEY = "GETKEY spyguy 004 0 :\\b_firewall\\b_profileid\\b_ipaddress\\b_publicip\\b_privateip\\b_authresponse\\b_gamever\\b_val\r\n" # CRLF +GET_UDP_RELAY = "GETUDPRELAY\r\n" +INVITE = "INVITE test spyguy\r\n" +LIST_LIMIT = "LISTLIMIT 5 test\r\n" +LIST = "LIST test\r\n" +LOGIN_PRE_AUTH = "LOGINPREAUTH xxxxx yyyyy\r\n" +# TODO: add binary data test [0D][0A] +LOGIN_NICK_AND_EMAIL = "LOGIN 0 * xxxxx :spyguy@spyguy@gamespy.com\r\n" +LOGIN_UNIQUE_NICK = "LOGIN 0 spyguy xxxxx\r\n" +NAMES = "NAMES\r\n" +MODES_GET = "MODES #gmtest" +MODES_SET = "MODES #gmtest +s" +NICK = "NICK :spyguy\r\n" +PING = "PING\r\n" # TODO: add binary data test [0D][0A] +PONG = "PONG :Pong!\r\n" +QUIT = "QUIT :Later!\r\n" # TODO: add binary data test [0D][0A] +REGISTER_NICK = "REGISTERNICK 0 spyguy XXXX-XXXX-XXXX-XXXX\r\n" +SET_GROUP = "SETGROUP test\r\n" +SET_KEY = "SETKEY :test\r\n" +USER_IP = "USRIP\r\n" +USER = "USER spyguy 127.0.0.1 peerchat.unispy.org :spyguy2\r\n" +WHO_IS = "WHOIS spyguy\r\n" +WHO_CHANNEL_USERS_INFO = "WHO #room\r\n" +WHO_USER_INFO = "WHO spyguy\r\n" + + +class GeneralRequestTests(unittest.TestCase): + def test_get_chann_key(self): + pass + + +# region Channel +GET_CHANNEL_KEY = "GETCHANKEY #GSP!room!test 0000 0 :\\username\\nickname\0\r\n" +GET_CKEY_CHANNEL_SPECIFIC_USER = ( + "GETCKEY #GSP!room!test spyguy 0000 0 :\\username\\nickname\0\r\n" +) +GET_CKEY_CHANNEL_ALL_USER = ( + "GETCKEY #GSP!room!test * 0000 0 :\\username\\nickname\0\r\n" +) +JOIN = "JOIN #GSP!room!test\r\n" +JOIN_WITH_PASS = "JOIN #GSP!room!test pass123\r\n" +KICK = "KICK #islabul spyguy :Spam\r\n" +MODE_CHANNEL = "MODE #GSP!room!test +l 2\r\n" +MODE_USER = "MODE spyguy +s\r\n" +PART = "PART #GSP!room!test :test\r\n" +SET_CHANNEL_KEY = "SETCHANNELKEY #GSP!room!test 0000 0:\\b_flags\\sh\0\r\n" +SET_CKEY = "SETCKEY #GSP!room!test spyguy 0000 0:\\b_flags\\sh\0\r\n" +TOPIC_GET_CHANNEL_TOPIC = "TOPIC #GSP!room!test\r\n" +TOPIC_SET_CHANNEL_TOPIC = "TOPIC #GSP!room!test :This is a topic message.\r\n" + + +class ChannelRequestTests(unittest.TestCase): + def test_get_channel_key(self): + request = GetChannelKeyRequest(GET_CHANNEL_KEY) + request.parse() + self.assertEqual(request.channel_name, "#GSP!room!test") + self.assertEqual(request.cookie, "0000") + self.assertEqual(request.keys[0], "username") + self.assertEqual(request.keys[1], "nickname") + + def test_get_ckey_channel_specific_user(self): + request = GetCKeyRequest(GET_CKEY_CHANNEL_SPECIFIC_USER) + request.parse() + self.assertEqual( + request.request_type, GetKeyRequestType.GET_CHANNEL_SPECIFIC_USER_KEY_VALUE + ) + self.assertEqual(request.channel_name, "#GSP!room!test") + self.assertEqual(request.nick_name, "spyguy") + self.assertEqual(request.cookie, "0000") + self.assertEqual(request.keys[0], "username") + self.assertEqual(request.keys[1], "nickname") + + def test_get_ckey_channel_all_user(self): + request = GetCKeyRequest(GET_CKEY_CHANNEL_ALL_USER) + request.parse() + self.assertEqual( + request.request_type, GetKeyRequestType.GET_CHANNEL_ALL_USER_KEY_VALUE + ) + self.assertEqual(request.channel_name, "#GSP!room!test") + self.assertEqual(request.cookie, "0000") + self.assertEqual(request.keys[0], "username") + self.assertEqual(request.keys[1], "nickname") + + def test_join(self): + request = JoinRequest(JOIN) + request.parse() + self.assertEqual(request.channel_name, "#GSP!room!test") + + request = JoinRequest(JOIN_WITH_PASS) + request.parse() + self.assertEqual(request.channel_name, "#GSP!room!test") + self.assertEqual(request.password, "pass123") + + def test_kick(self): + request = KickRequest(KICK) + request.parse() + self.assertEqual(request.kickee_nick_name, "spyguy") + self.assertEqual(request.reason, "Spam") + + def test_mode(self): + request = ModeRequest(MODE_CHANNEL) + request.parse() + self.assertEqual( + request.mode_operations, + {ModeName.CHANNEL_USER_LIMITS.value: ModeOperation.SET.value}, + ) + self.assertEqual(request.channel_name, "#GSP!room!test") + self.assertEqual(request.mode_flag, "+l") + self.assertEqual(request.limit_number, 2) + + request = ModeRequest("MODE #GSP!gmtest!MlNK4q4l1M -i-p-s+m-n+t+l+e 2") + request.parse() + + def test_part(self): + request = PartRequest(PART) + request.parse() + self.assertEqual(request.reason, "test") + + def test_set_channel_key(self): + request = SetChannelKeyRequest(SET_CHANNEL_KEY) + request.parse() + # Add assertions as needed + + def test_set_ckey(self): + request = SetCKeyRequest(SET_CKEY) + request.parse() + self.assertEqual(request.channel_name, "#GSP!room!test") + self.assertEqual(request.nick_name, "spyguy") + self.assertEqual(request.key_values, {"b_flags": "sh"}) + + def test_topic_get_channel_topic(self): + request = TopicRequest(TOPIC_GET_CHANNEL_TOPIC) + request.parse() + self.assertEqual(request.channel_name, "#GSP!room!test") + + def test_topic_set_channel_topic(self): + request = TopicRequest(TOPIC_SET_CHANNEL_TOPIC) + request.parse() + self.assertEqual(request.channel_name, "#GSP!room!test") + self.assertEqual(request.channel_topic, "This is a topic message.") + + +# region Message + + +ABOVE_THE_TABLE_MSG = "ATM #GSP!room!test :hello this is a test.\r\n" +NOTICE_MSG = "NOTICE #GSP!room!test :hello this is a test.\r\n" +PRIVATE_MSG = "PRIVMSG #GSP!room!test :hello this is a test.\r\n" +UNDER_THE_TABLE_MSG = "UTM #GSP!room!test :hello this is a test.\r\n" +ACTION_MSG = "PRIVMSG #GSP!room!test :\001ACTION hello this is a test.\001\r\n" + + +class MessageRequestTests(unittest.TestCase): + def test_atm(self): + request = AtmRequest(ABOVE_THE_TABLE_MSG) + request.parse() + self.assertEqual(MessageType.CHANNEL_MESSAGE, request.type) + self.assertEqual(False, hasattr(request, "nick_name")) + self.assertEqual("#GSP!room!test", request.channel_name) + + def test_notice(self): + request = NoticeRequest(NOTICE_MSG) + request.parse() + self.assertEqual(MessageType.CHANNEL_MESSAGE, request.type) + self.assertEqual(False, hasattr(request, "nick_name")) + self.assertEqual("#GSP!room!test", request.channel_name) + + def test_private(self): + request = PrivateRequest(PRIVATE_MSG) + request.parse() + self.assertEqual(MessageType.CHANNEL_MESSAGE, request.type) + self.assertEqual(False, hasattr(request, "nick_name")) + self.assertEqual("#GSP!room!test", request.channel_name) + + def test_utm(self): + request = UtmRequest(UNDER_THE_TABLE_MSG) + request.parse() + self.assertEqual(MessageType.CHANNEL_MESSAGE, request.type) + self.assertEqual(False, hasattr(request, "nick_name")) + self.assertEqual("#GSP!room!test", request.channel_name) diff --git a/src/frontends/tests/gamespy/game_status/__init__.py b/src/frontends/tests/gamespy/game_status/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/tests/gamespy/game_status/game_tests.py b/src/frontends/tests/gamespy/game_status/game_tests.py new file mode 100644 index 000000000..9e642062e --- /dev/null +++ b/src/frontends/tests/gamespy/game_status/game_tests.py @@ -0,0 +1,40 @@ + + +import unittest + +import responses + +from frontends.tests.gamespy.game_status.mock_objects import create_client + + +class GameTest(unittest.TestCase): + @responses.activate + def test_worm3d_20230331(self): + raws1 = [ + "\\auth\\\\gamename\\worms3\\response\\bc3ca727a7825879eb9f13d9fd51bbb9\\port\\0\\id\\1\\final\\", + "\\newgame\\\\connid\\0\\sesskey\\144562\\final\\", + "\\authp\\\\pid\\1\\resp\\7b6658e99f448388fbeddc93654e6dd4\\lid\\2\\final\\", + "\\setpd\\\\pid\\1\\ptype\\1\\dindex\\0\\kv\\1\\lid\\2\\length\\111\\data\\\\report\\|title||victories|0|timestamp|66613|league|Team17|winner||crc|-1|player_0|spyguy|ip_0||pid_0|0|auth_0|[00]\\final\\", + ] + client = create_client() + for raw in raws1: + client.on_received(raw.encode()) + + @responses.activate + def test_gmtest(self): + raws = [ + "\\auth\\\\gamename\\crysis2\\response\\xxxxx\\port\\30\\id\\1\\final\\", + "\\getpd\\\\pid\\0\\ptype\\0\\dindex\\1\\keys\\hello\x01hi\\lid\\1\\final\\", + "\\getpid\\\\nick\\xiaojiuwo\\keyhash\\00000\\lid\\1\\final\\", + "\\newgame\\\\connid\\123\\sesskey\\123456\\lid\\1\\final\\", + "\\newgame\\\\connid\\123\\sesskey\\2020\\lid\\1\\final\\", + "\\newgame\\\\connid\\123\\sesskey\\123456\\challenge\\123456789\\lid\\1\\final\\", + "\\newgame\\\\connid\\123\\sesskey\\2020\\challenge\\123456789\\lid\\1\\final\\", + "\\setpd\\\\pid\\123\\ptype\\0\\dindex\\1\\kv\\1\\lid\\1\\length\\5\\data\\11\\lid\\1\\final\\", + "\\updgame\\\\sesskey\\0\\done\\1\\gamedata\\hello\\lid\\1\\final\\", + "\\updgame\\\\sesskey\\2020\\done\\1\\gamedata\\hello\\lid\\1\\final\\", + "\\updgame\\\\sesskey\\2020\\connid\\1\\done\\1\\gamedata\\hello\\lid\\1\\final\\", + "\\updgame\\\\sesskey\\0\\connid\\1\\done\\1\\gamedata\\hello\\lid\\1\\final\\"] + client = create_client() + for raw in raws: + client.on_received(raw.encode()) diff --git a/src/frontends/tests/gamespy/game_status/handler_tests.py b/src/frontends/tests/gamespy/game_status/handler_tests.py new file mode 100644 index 000000000..6f83f8dcf --- /dev/null +++ b/src/frontends/tests/gamespy/game_status/handler_tests.py @@ -0,0 +1,158 @@ +import unittest +import responses + +from frontends.gamespy.protocols.game_status.aggregations.gscrypt import GSCrypt +from frontends.gamespy.protocols.game_status.contracts.requests import ( + AuthGameRequest, + AuthPlayerRequest, + GetPlayerDataRequest, + GetProfileIdRequest, + NewGameRequest, + SetPlayerDataRequest, + UpdateGameRequest, +) +from frontends.gamespy.protocols.game_status.aggregations.enums import ( + PersistStorageType, +) +from frontends.gamespy.protocols.game_status.applications.handlers import ( + AuthPlayerHandler, + SetPlayerDataHandler, + UpdateGameHandler, +) +from frontends.tests.gamespy.game_status.mock_objects import create_client + + +class HandlerTests(unittest.TestCase): + @responses.activate + # @unittest.skip("not implemented") + def test_set_player_data_20230329(self): + raw = "\\setpd\\\\pid\\1\\ptype\\1\\dindex\\0\\kv\\1\\lid\\2\\length\\111\\data\\\\report\\|title||victories|0|timestamp|37155|league|Team17|winner||crc|-1|player_0|spyguy|ip_0||pid_0|0|auth_0|[00]\\final\\" + client = create_client() + request = SetPlayerDataRequest(raw) + request.parse() + self.assertEqual(1, request.profile_id) + self.assertEqual(PersistStorageType.PRIVATE_READ_WRITE, + request.storage_type) + self.assertEqual(0, request.data_index) + self.assertEqual("", request.data) + self.assertEqual(111, request.length) + self.assertEqual( + "|title||victories|0|timestamp|37155|league|Team17|winner||crc|-1|player_0|spyguy|ip_0||pid_0|0|auth_0|[00]", + request.report, + ) + + handler = SetPlayerDataHandler(client, request) + handler.handle() + + @responses.activate + # @unittest.skip("not implemented") + def test_gamespysdk_update_game_20230329(self): + raw1 = "\\updgame\\\\sesskey\\20298203\\connid\\0\\done\\0\\gamedata\\\u0001hostname\u0001My l33t Server\u0001mapname\u0001Level 33\u0001gametype\u0001hunter\u0001gamever\u00011.230000\u0001player_0\u0001Bob!\u0001points_0\u00014\u0001deaths_0\u00012\u0001pid_0\u000132432423\u0001auth_0\u00017cca8e60a13781eebc820a50754f57cd\u0001player_1\u0001Joey\u0001points_1\u00012\u0001deaths_1\u00014\u0001pid_1\u0001643423\u0001auth_1\u000119ea14d9d92a7fcc635cf5716944d9bc\\final\\" + raw2 = "\\updgame\\\\sesskey\\20298203\\connid\\0\\done\\1\\gamedata\\\u0001hostname\u0001My l33t Server\u0001mapname\u0001Level 33\u0001gametype\u0001hunter\u0001gamever\u00011.230000\u0001player_0\u0001Bob!\u0001points_0\u00016\u0001deaths_0\u00013\u0001pid_0\u000132432423\u0001auth_0\u00017cca8e60a13781eebc820a50754f57cd\u0001player_1\u0001Joey\u0001points_1\u00013\u0001deaths_1\u00016\u0001pid_1\u0001643423\u0001auth_1\u000119ea14d9d92a7fcc635cf5716944d9bc\\final\\" + client = create_client() + request = UpdateGameRequest(raw1) + handler = UpdateGameHandler(client, request) + handler.handle() + self.assertEqual("20298203", request.session_key) + self.assertEqual(0, request.connection_id) + self.assertEqual(False, request.is_done) + self.assertEqual( + "\u0001hostname\u0001My l33t Server\u0001mapname\u0001Level 33\u0001gametype\u0001hunter\u0001gamever\u00011.230000\u0001player_0\u0001Bob!\u0001points_0\u00014\u0001deaths_0\u00012\u0001pid_0\u000132432423\u0001auth_0\u00017cca8e60a13781eebc820a50754f57cd\u0001player_1\u0001Joey\u0001points_1\u00012\u0001deaths_1\u00014\u0001pid_1\u0001643423\u0001auth_1\u000119ea14d9d92a7fcc635cf5716944d9bc", + request.game_data, + ) + request = UpdateGameRequest(raw2) + handler = UpdateGameHandler(client, request) + handler.handle() + + @responses.activate + @unittest.skip("Encrypted request is not correct") + def test_worm3d_auth_player(self): + raw = b"2\\x0F\\x16\\x10]%+=veKaB3a(UC`b$\\x1CO\\x11VZX\\x09w\\x1Cu\\x08L@\\x13=X!\\x1E{\\x0EL\\x1DLf[qN \\x04G\\x130[#N'\\x09(IC`b$\\final\\" + plaintext = GSCrypt().decrypt(raw) + request = AuthPlayerRequest(plaintext) + client = create_client() + handler = AuthPlayerHandler(client, request) + handler.handle() + + # self.assertEqual() + + @responses.activate + def test_auth(self): + raw = "\\auth\\\\gamename\\crysis2\\response\\xxxxx\\port\\30\\id\\1\\final\\" + request = AuthGameRequest(raw) + request.parse() + self.assertEqual("crysis2", request.game_name) + self.assertEqual(30, request.port) + self.assertEqual(1, request.local_id) + + @responses.activate + def test_get_player_data(self): + raw = ( + "\\getpd\\\\pid\\0\\ptype\\0\\dindex\\1\\keys\\hello\x01hi\\lid\\1\\final\\" + ) + + request = GetPlayerDataRequest(raw) + request.parse() + self.assertEqual(0, request.profile_id) + self.assertEqual(PersistStorageType.PRIVATE_READ_ONLY, + request.storage_type) + self.assertEqual(1, request.data_index) + self.assertEqual(2, len(request.keys)) + self.assertEqual("hello", request.keys[0]) + self.assertEqual("hi", request.keys[1]) + + @responses.activate + def test_get_profile_id(self): + raw = "\\getpid\\\\nick\\xiaojiuwo\\keyhash\\00000\\lid\\1\\final\\" + request = GetProfileIdRequest(raw) + request.parse() + self.assertEqual("xiaojiuwo", request.nick) + self.assertEqual("00000", request.key_hash) + self.assertEqual(1, request.local_id) + + @responses.activate + def test_new_game(self): + raw1 = "\\newgame\\\\connid\\123\\sesskey\\123456\\lid\\1\\final\\" + request1 = NewGameRequest(raw1) + request1.parse() + + self.assertEqual(123, request1.connection_id) + self.assertEqual("123456", request1.session_key) + self.assertEqual(1, request1.local_id) + + raw2 = "\\newgame\\\\connid\\123\\sesskey\\123456\\challenge\\123456789\\lid\\1\\final\\" + request2 = NewGameRequest(raw2) + request2.parse() + self.assertEqual(123, request2.connection_id) + self.assertEqual("123456", request2.session_key) + self.assertEqual("123456789", request2.challenge) + self.assertEqual(1, request2.local_id) + + @responses.activate + def test_update_game(self): + raw1 = "\\updgame\\\\sesskey\\0\\done\\1\\gamedata\\hello\\lid\\1\\final\\" + request1 = UpdateGameRequest(raw1) + request1.parse() + self.assertEqual("0", request1.session_key) + self.assertEqual(True, request1.is_done) + self.assertEqual("hello", request1.game_data) + self.assertEqual(None, request1.connection_id) + raw2 = "\\updgame\\\\sesskey\\0\\connid\\1\\done\\1\\gamedata\\hello\\lid\\1\\final\\" + request2 = UpdateGameRequest(raw2) + request2.parse() + self.assertEqual("0", request2.session_key) + self.assertEqual(True, request2.is_done) + self.assertEqual("hello", request2.game_data) + self.assertEqual(1, request2.connection_id) + + @responses.activate + def test_auth_player_2025_11_06(self): + raw = '\\authp\\\\nick\\spyguy\\keyhash\\00000a308fd86a7eb92cbc8322b03a36\\resp\\a146083990caca4925e3144deb552817\\lid\\1\\final\\' + request = AuthPlayerRequest(raw) + client = create_client() + handler = AuthPlayerHandler(client, request) + handler.handle() + + +if __name__ == "__main__": + unittest.main() diff --git a/src/frontends/tests/gamespy/game_status/mock_objects.py b/src/frontends/tests/gamespy/game_status/mock_objects.py new file mode 100644 index 000000000..3d5ba74be --- /dev/null +++ b/src/frontends/tests/gamespy/game_status/mock_objects.py @@ -0,0 +1,74 @@ +from datetime import datetime +from typing import cast +from frontends.gamespy.library.configs import CONFIG +from frontends.gamespy.protocols.game_status.applications.client import Client +from frontends.gamespy.protocols.game_status.applications.handlers import ( + AuthGameHandler, + AuthPlayerHandler, + GetPlayerDataHandler, + GetProfileIdHandler, + NewGameHandler, + SetPlayerDataHandler, + UpdateGameHandler, +) +from frontends.gamespy.protocols.game_status.contracts.results import ( + AuthGameResult, + AuthPlayerResult, + GetPlayerDataResult, + GetProfileIdResult, +) +from frontends.tests.gamespy.library.mock_objects import ( + ConnectionMock, + LogMock, + RequestHandlerMock, + create_mock_url, +) + + +class ClientMock(Client): + pass + + +def create_client() -> Client: + CONFIG.unittest.is_raise_except = True + handler = RequestHandlerMock() + logger = LogMock() + conn = ConnectionMock( + handler=handler, + config=CONFIG.servers["GameStatus"], + t_client=ClientMock, + logger=logger, + ) + config = CONFIG.servers["GameStatus"] + create_mock_url(config, SetPlayerDataHandler, {"message": "ok"}) + create_mock_url( + config, + GetPlayerDataHandler, + GetPlayerDataResult( + data="\\key1\\value1\\key2\\value2\\key3\\value3", + local_id=0, + profile_id=0, + modified=datetime.now() + ).model_dump(mode="json"), + ) + create_mock_url( + config, + GetProfileIdHandler, + GetProfileIdResult.model_validate( + {"profile_id": 1, "local_id": 0}).model_dump(), + ) + create_mock_url(config, UpdateGameHandler, {"message": "ok"}) + create_mock_url( + config, AuthPlayerHandler, AuthPlayerResult.model_validate( + {"profile_id": 1, "local_id": 0}).model_dump(mode="json") + ) + create_mock_url(config, NewGameHandler, {"message": "ok"}) + create_mock_url( + config, + AuthGameHandler, + AuthGameResult(session_key="123456", + local_id=0, + game_name="gmtest").model_dump(), + ) + + return cast(Client, conn._client) diff --git a/src/frontends/tests/gamespy/game_traffic_relay/__init__.py b/src/frontends/tests/gamespy/game_traffic_relay/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/tests/gamespy/game_traffic_relay/handler_tests.py b/src/frontends/tests/gamespy/game_traffic_relay/handler_tests.py new file mode 100644 index 000000000..7dcde2bc4 --- /dev/null +++ b/src/frontends/tests/gamespy/game_traffic_relay/handler_tests.py @@ -0,0 +1,31 @@ +import unittest + +from frontends.gamespy.protocols.game_traffic_relay.applications.client import ConnectionListener +from frontends.gamespy.protocols.game_traffic_relay.applications.handlers import ( + PingHandler, +) +from frontends.gamespy.protocols.natneg.contracts.requests import PingRequest +from frontends.tests.gamespy.game_traffic_relay.mock_objects import create_client + + +class HandlerTests(unittest.TestCase): + def test_ping(self): + """ + test whether 2 clients can be binding togather with ping command + """ + ping_raw = ( + b"\xfd\xfc\x1efj\xb2\x03\x07\x00\x00\x02\x9a\xc0\xa8\x01gl\xfd\x00\x00" + ) + client1 = create_client(("127.0.0.1", 1234)) + client1._log_prefix = "[127.0.0.1:1234]" + client2 = create_client(("127.0.0.1", 1235)) + client2._log_prefix = "[127.0.0.1:1235]" + client1.on_received(ping_raw) + client2.on_received(ping_raw) + # cookie length check + self.assertEqual(len(ConnectionListener.cookie_pool), 1) + clients = list(ConnectionListener.cookie_pool.values())[0] + self.assertEqual(len(clients), 2) + client1 = create_client(("127.0.0.1", 1234)) + client1.on_received(ping_raw) + pass diff --git a/src/frontends/tests/gamespy/game_traffic_relay/mock_objects.py b/src/frontends/tests/gamespy/game_traffic_relay/mock_objects.py new file mode 100644 index 000000000..a8d761954 --- /dev/null +++ b/src/frontends/tests/gamespy/game_traffic_relay/mock_objects.py @@ -0,0 +1,32 @@ +from typing import cast +from frontends.gamespy.library.configs import CONFIG +from frontends.gamespy.protocols.game_traffic_relay.applications.client import Client +from frontends.gamespy.protocols.game_traffic_relay.applications.handlers import ( + PingHandler, +) +from frontends.tests.gamespy.library.mock_objects import ( + ConnectionMock, + LogMock, + RequestHandlerMock, + create_mock_url, +) + + +class ClientMock(Client): + pass + + +def create_client(client_address: tuple = ("192.168.0.1", 0)) -> Client: + CONFIG.unittest.is_raise_except = True + handler = RequestHandlerMock(client_address) + logger = LogMock() + conn = ConnectionMock( + handler=handler, + config=CONFIG.servers["GameTrafficRelay"], + t_client=ClientMock, + logger=logger, + ) + + config = CONFIG.servers["GameTrafficRelay"] + create_mock_url(config, PingHandler, {"message": "ok"}) + return cast(Client, conn._client) diff --git a/src/frontends/tests/gamespy/library/__init__.py b/src/frontends/tests/gamespy/library/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/tests/gamespy/library/encrypt_tests.py b/src/frontends/tests/gamespy/library/encrypt_tests.py new file mode 100644 index 000000000..a3b743eb3 --- /dev/null +++ b/src/frontends/tests/gamespy/library/encrypt_tests.py @@ -0,0 +1,25 @@ +import unittest +from frontends.gamespy.library.encryption.gs_encryption import ChatCrypt +from frontends.gamespy.library.encryption.xor_encryption import XorEncoding, XorType + + +class EncryptionTest(unittest.TestCase): + def test_chat_encryption(self): + enc = ChatCrypt("123345") + result = enc.encrypt("hello".encode("ascii")) + self.assertEqual(result, b"\xda\xaek^d") + + def test_chat_decryption(self): + enc = ChatCrypt("123345") + result = enc.decrypt(b"\xda\xaek^d") + self.assertEqual(result, b"hello") + + def test_xor_encoding(self): + raw = b"abcdefghijklmnopqrstuvwxyz" + plaintext = XorEncoding.encode(raw, XorType.TYPE_1) + self.assertEqual( + b"&\x03\x0e\x016\x16\x1e[--\n\x01\x08=\x1f\tB64\x15\x18\x13$\x08\x00I", plaintext) + + +if __name__ == "__main__": + unittest.main() diff --git a/src/frontends/tests/gamespy/library/mock_objects.py b/src/frontends/tests/gamespy/library/mock_objects.py new file mode 100644 index 000000000..6057a03f5 --- /dev/null +++ b/src/frontends/tests/gamespy/library/mock_objects.py @@ -0,0 +1,65 @@ +import socketserver + +import responses +from frontends.gamespy.library.abstractions.brocker import BrockerBase +from frontends.gamespy.library.abstractions.connections import ConnectionBase +from frontends.gamespy.library.abstractions.handler import CmdHandlerBase +from frontends.gamespy.library.log.log_manager import GLOBAL_LOGGER, LogWriter +from frontends.gamespy.library.configs import CONFIG, ServerConfig + + +class ConnectionMock(ConnectionBase): + def send(self, data: bytes) -> None: + pass + + +class RequestHandlerMock(socketserver.BaseRequestHandler): + client_address: tuple + + def __init__(self, client_address: tuple = ("192.168.0.1", 0)) -> None: + self.client_address = client_address + + pass + + +class LogMock(LogWriter): + def __init__(self) -> None: + super().__init__(None) + + def debug(self, message): + print(message) + GLOBAL_LOGGER.debug(message) + + def info(self, message): + print(message) + GLOBAL_LOGGER.info(message) + + def error(self, message): + print(message) + GLOBAL_LOGGER.error(message) + + def warn(self, message): + print(message) + GLOBAL_LOGGER.warn(message) + + +class BrokerMock(BrockerBase): + def __init__(self) -> None: + pass + + def subscribe(self): + pass + + def publish_message(self, message): + pass + + def unsubscribe(self): + pass + + +def create_mock_url( + config: ServerConfig, handler: type[CmdHandlerBase], data: dict +) -> None: + url = f"{CONFIG.backend.url}/GameSpy/{config.server_name}/{handler.__name__}" + resp = {"result": data} + responses.add(responses.POST, url, json=resp, status=200) diff --git a/src/frontends/tests/gamespy/natneg/__init__.py b/src/frontends/tests/gamespy/natneg/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/tests/gamespy/natneg/contract_tests.py b/src/frontends/tests/gamespy/natneg/contract_tests.py new file mode 100644 index 000000000..0350e6d06 --- /dev/null +++ b/src/frontends/tests/gamespy/natneg/contract_tests.py @@ -0,0 +1,20 @@ +from unittest import TestCase + +from frontends.gamespy.protocols.natneg.aggregations.enums import NatClientIndex +from frontends.gamespy.protocols.natneg.applications.switcher import Switcher +from frontends.gamespy.protocols.natneg.contracts.requests import ConnectAckRequest +from frontends.tests.gamespy.natneg.mock_objects import create_client + + +class ContractTests(TestCase): + def test_connect_ack(self): + raws = [ + b'\xfd\xfc\x1efj\xb2\x04\x06\x00\x00\x02\x9a\x00\x01\x00\x00\xd8\xf2@\x00\x00', + b'\xfd\xfc\x1efj\xb2\x04\x06\x00\x00\x02\x9aj\x01\x04\x07\x00\x00\x02\x9a\xac', + b'\xfd\xfc\x1efj\xb2\x04\x06\x00\x00\x02\x9aj\x01\x04\x07\x00\x00\x02\x9a\xac', + b'\xfd\xfc\x1efj\xb2\x04\x06\x00\x00\x02\x9a@\x01\x00\x00\xc0\xf28o\xfd', + ] + for raw in raws: + r = ConnectAckRequest(raw) + r.parse() + self.assertEqual(r.client_index, NatClientIndex.GAME_SERVER) diff --git a/src/frontends/tests/gamespy/natneg/handler_tests.py b/src/frontends/tests/gamespy/natneg/handler_tests.py new file mode 100644 index 000000000..1b8cc7395 --- /dev/null +++ b/src/frontends/tests/gamespy/natneg/handler_tests.py @@ -0,0 +1,159 @@ +import unittest + +from frontends.gamespy.library.configs import CONFIG +from frontends.gamespy.protocols.natneg.applications.handlers import ( + AddressCheckHandler, + ErtAckHandler, + InitHandler, + NatifyHandler, +) +import responses +from frontends.gamespy.protocols.natneg.contracts.requests import ( + AddressCheckRequest, + ErtAckRequest, + InitRequest, + NatifyRequest, + PreInitRequest, +) +from frontends.gamespy.protocols.natneg.aggregations.enums import ( + NatClientIndex, + NatPortType, + PreInitState, + RequestType, +) + +from frontends.tests.gamespy.natneg.mock_objects import create_client + +CONFIG.unittest.is_raise_except = True + + +class HandlerTests(unittest.TestCase): + @responses.activate + def test_init(self): + raw = bytes( + [ + 0xfd, 0xfc, 0x1e, 0x66, 0x6a, 0xb2, 0x03, + 0x00, + 0x00, 0x00, 0x03, 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + ] + ) # fmt: skip + + client = create_client() + + # test request parsing + request = InitRequest(raw) + request.parse() + self.assertEqual(777, request.cookie) + self.assertEqual(RequestType.INIT, request.command_name) + self.assertEqual(NatClientIndex.GAME_CLIENT, request.client_index) + self.assertEqual(False, request.use_game_port) + self.assertEqual(3, request.version) + self.assertEqual(NatPortType.NN1, request.port_type) + handler = InitHandler(client, request) + handler.handle() + + # test response constructing + self.assertTrue( + handler._response.sending_buffer + == b"\xfd\xfc\x1efj\xb2\x03\x01\x00\x00\x03\t\x01\x00\x00\xc0\xa8\x00\x01\x00\x00" + ) + + @responses.activate + def test_address_check(self): + raw = bytes( + [ + 0xfd, 0xfc, 0x1e, 0x66, 0x6a, 0xb2, 0x03, 0x0a, 0x00, 0x00, 0x03, 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + ] + ) # fmt: skip + + request = AddressCheckRequest(raw) + request.parse() + self.assertEqual(777, request.cookie) + self.assertEqual(RequestType.ADDRESS_CHECK, request.command_name) + self.assertEqual(NatClientIndex.GAME_CLIENT, request.client_index) + self.assertEqual(False, request.use_game_port) + self.assertEqual(3, request.version) + self.assertEqual(NatPortType.NN1, request.port_type) + + client = create_client() + handler = AddressCheckHandler(client, request) + handler.handle() + + self.assertTrue( + handler._response.sending_buffer + == b"\xfd\xfc\x1efj\xb2\x03\x0b\x00\x00\x03\t\x01\x00\x00\xc0\xa8\x00\x01\x00\x00" + ) + + @responses.activate + def test_ert_ack(self): + raw = bytes( + [ + 0xfd, 0xfc, 0x1e, 0x66, 0x6a, 0xb2, 0x03, + 0x03, + 0x00, 0x00, 0x03, 0x09, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + ] + ) # fmt: skip + request = ErtAckRequest(raw) + request.parse() + self.assertEqual(777, request.cookie) + self.assertEqual(RequestType.ERT_ACK, request.command_name) + self.assertEqual(NatClientIndex.GAME_CLIENT, request.client_index) + self.assertEqual(3, request.version) + self.assertEqual(False, request.use_game_port) + self.assertEqual(NatPortType.NN1, request.port_type) + client = create_client() + + handler = ErtAckHandler(client, request) + handler.handle() + self.assertTrue( + handler._response.sending_buffer + == b'\xfd\xfc\x1efj\xb2\x03\x03\x00\x00\x03\t\x01\x00\x00\xc0\xa8\x00\x01\x00\x00' + ) + + @responses.activate + def test_natify(self): + raw = bytes( + [ + 0xfd, 0xfc, 0x1e, 0x66, 0x6a, 0xb2, 0x03, + 0x0c, + 0x00, 0x00, 0x03, 0x09, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + ] + ) # fmt: skip + request = NatifyRequest(raw) + request.parse() + self.assertEqual(777, request.cookie) + self.assertEqual(RequestType.NATIFY_REQUEST, request.command_name) + self.assertEqual(NatClientIndex.GAME_CLIENT, request.client_index) + self.assertEqual(3, request.version) + self.assertEqual(False, request.use_game_port) + self.assertEqual(NatPortType.NN1, request.port_type) + client = create_client() + + handler = NatifyHandler(client, request) + handler.handle() + self.assertTrue( + handler._response.sending_buffer + == b'\xfd\xfc\x1efj\xb2\x03\x02\x00\x00\x03\t\x01\x00\x00\xc0\xa8\x00\x01\x00\x00' + ) + + @responses.activate + def test_preinit(self): + raw = bytes( + [ + 0xfd, 0xfc, 0x1e, 0x66, 0x6a, 0xb2, 0x04, 0x0f, 0xb5, 0xe0, 0x95, 0x2a, 0x00, 0x24, 0x38, 0xb2, 0xb3, 0x5e + ] + ) # fmt: skip + + req = PreInitRequest(raw) + req.parse() + self.assertEqual(3051394346, req.cookie) + self.assertEqual(RequestType.PRE_INIT, req.command_name) + self.assertEqual(4, req.version) + self.assertEqual(NatPortType.GP, req.port_type) + self.assertEqual(PreInitState.WAITING_FOR_CLIENT, req.state) + + +if __name__ == "__main__": + unittest.main() diff --git a/src/frontends/tests/gamespy/natneg/mock_objects.py b/src/frontends/tests/gamespy/natneg/mock_objects.py new file mode 100644 index 000000000..0f4d91bde --- /dev/null +++ b/src/frontends/tests/gamespy/natneg/mock_objects.py @@ -0,0 +1,45 @@ +from frontends.gamespy.protocols.natneg.contracts.results import AddressCheckResult, ConnectResult, InitResult +from frontends.tests.gamespy.library.mock_objects import ( + ConnectionMock, + LogMock, + RequestHandlerMock, + create_mock_url, +) +from frontends.gamespy.library.configs import CONFIG +from frontends.gamespy.protocols.natneg.applications.client import Client +from typing import cast + +from frontends.gamespy.protocols.natneg.applications.handlers import ( + AddressCheckHandler, + ConnectHandler, + ErtAckHandler, + InitHandler, + NatifyHandler, +) + + +class ClientMock(Client): + pass + + +def create_client() -> Client: + CONFIG.unittest.is_raise_except = True + handler = RequestHandlerMock() + logger = LogMock() + conn = ConnectionMock( + handler=handler, + config=CONFIG.servers["NatNegotiation"], + t_client=ClientMock, + logger=logger, + ) + + config = CONFIG.servers["NatNegotiation"] + create_mock_url(config, InitHandler, InitResult.model_validate( + {"version": 3, "cookie": 777, "public_ip_addr": "127.0.0.1", "public_port": 1234, "use_game_port": False, "port_type": 1, "client_index": 0, "use_game_port": 0}).model_dump(mode="json")) + create_mock_url(config, AddressCheckHandler, AddressCheckResult.model_validate( + {"version": 3, "cookie": 0, "public_ip_addr": "127.0.0.1", "public_port": 1234, "use_game_port": False, "port_type": 0, "client_index": 0, "use_game_port": 0}).model_dump(mode="json")) + create_mock_url(config, NatifyHandler, {"message": "ok"}) + create_mock_url(config, ErtAckHandler, {"message": "ok"}) + create_mock_url(config, ConnectHandler, ConnectResult.model_validate( + {"version": 3, "cookie": 0, "is_both_client_ready": True, "ip": "192.168.0.1", "port": 7890, "status": 0}).model_dump(mode="json")) + return cast(Client, conn._client) diff --git a/src/frontends/tests/gamespy/natneg/redis.py b/src/frontends/tests/gamespy/natneg/redis.py new file mode 100644 index 000000000..667890cf9 --- /dev/null +++ b/src/frontends/tests/gamespy/natneg/redis.py @@ -0,0 +1,37 @@ +# import datetime +# + +# from pydantic.v1 import EmailStr + +# from redis_om import Field, HashModel, Migrator + + +# class Customer(HashModel): +# first_name: str +# last_name: str = Field(index=True) +# email: EmailStr +# join_date: datetime.date +# age: int = Field(index=True) +# bio: str | None + + +# # Now, if we use this model with a Redis deployment that has the +# # RediSearch module installed, we can run queries like the following. + +# # Before running queries, we need to run migrations to set up the +# # indexes that Redis OM will use. You can also use the `migrate` +# # CLI tool for this! +# Migrator().run() + +# # Find all customers with the last name "Brookins" +# Customer.find(Customer.last_name == "Brookins").all() + +# # Find all customers that do NOT have the last name "Brookins" +# Customer.find(Customer.last_name != "Brookins").all() + +# # Find all customers whose last name is "Brookins" OR whose age is +# # 100 AND whose last name is "Smith" +# Customer.find( +# (Customer.last_name == "Brookins") +# | (Customer.age == 100) & (Customer.last_name == "Smith") +# ).all() diff --git a/src/frontends/tests/gamespy/presence_connection_manager/__init__.py b/src/frontends/tests/gamespy/presence_connection_manager/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/tests/gamespy/presence_connection_manager/game_tests.py b/src/frontends/tests/gamespy/presence_connection_manager/game_tests.py new file mode 100644 index 000000000..269003fba --- /dev/null +++ b/src/frontends/tests/gamespy/presence_connection_manager/game_tests.py @@ -0,0 +1,44 @@ +import unittest + +from frontends.gamespy.protocols.presence_connection_manager.contracts.requests import StatusRequest +from frontends.tests.gamespy.presence_connection_manager.mock_objects import create_client +import responses + + +class GameTest(unittest.TestCase): + @responses.activate + def test_civilization_4(self) -> None: + raw_requests = [ + "\\newuser\\\\email\\civ4@unispy.org\\nick\\civ4-tk\\passwordenc\\JMHGwQ__\\productid\\10435\\gamename\\civ4\\namespaceid\\17\\uniquenick\\civ4-tk\\id\\1\\final\\", + "\\login\\\\challenge\\xMsHUXuWNXL3KMwmhoQZJrP0RVsArCYT\\uniquenick\\civ4-tk\\userid\\25\\profileid\\26\\response\\7f2c9c6685570ea18b7207d2cbd72452\\firewall\\1\\port\\0\\productid\\10435\\gamename\\civ4\\namespaceid\\17\\sdkrevision\\1\\id\\1\\final\\", + ] + client = create_client() + + + for x in raw_requests: + client.on_received(x.encode()) + pass + + @unittest.skip("not finished handler") + @responses.activate + def test_conflict_global_storm(self) -> None: + # "\\lc\\1\\challenge\\NRNUJLZMLX\\id\\1\\final\\", + raw_requests = [ + "\\login\\\\challenge\\KMylyQbZfqzKn9otxx32q4076sOUnKif\\user\\cgs1@cgs1@rs.de\\response\\c1a6638bbcfe130e4287bfe4aa792949\\port\\-15737\\productid\\10469\\gamename\\conflictsopc\\namespaceid\\1\\id\\1\\final\\", + "\\inviteto\\\\sesskey\\58366\\products\\1038\\final\\", + ] + client = create_client() + for x in raw_requests: + client.on_received(x.encode("ascii")) + pass + + def test_sbwfrontps2(self) -> None: + raw = "\\status\\1\\sesskey\\1111\\statstring\\EN LIGNE\\locstring\\\\final\\" + request = StatusRequest(raw) + request.parse() + self.assertTrue(request.location_string == "") + self.assertTrue(request.status_string == "EN LIGNE") + + +if __name__ == "__main__": + unittest.main() diff --git a/src/frontends/tests/gamespy/presence_connection_manager/handler_tests.py b/src/frontends/tests/gamespy/presence_connection_manager/handler_tests.py new file mode 100644 index 000000000..f778efe0e --- /dev/null +++ b/src/frontends/tests/gamespy/presence_connection_manager/handler_tests.py @@ -0,0 +1,5 @@ +import unittest + +class HandlerTests(unittest.TestCase): + def test_status(self): + pass \ No newline at end of file diff --git a/src/frontends/tests/gamespy/presence_connection_manager/mock_objects.py b/src/frontends/tests/gamespy/presence_connection_manager/mock_objects.py new file mode 100644 index 000000000..5451fc56f --- /dev/null +++ b/src/frontends/tests/gamespy/presence_connection_manager/mock_objects.py @@ -0,0 +1,60 @@ +from typing import cast +from frontends.gamespy.library.configs import CONFIG +from frontends.tests.gamespy.library.mock_objects import ( + ConnectionMock, + LogMock, + RequestHandlerMock, + create_mock_url, +) +from frontends.gamespy.protocols.presence_connection_manager.applications.client import ( + Client, +) +from frontends.gamespy.protocols.presence_connection_manager.applications.handlers import ( + LoginHandler, + NewUserHandler, +) + + +class ClientMock(Client): + pass + + +def create_client() -> Client: + CONFIG.unittest.is_raise_except = True + handler = RequestHandlerMock() + logger = LogMock() + conn = ConnectionMock( + handler=handler, + config=CONFIG.servers["PresenceConnectionManager"], + t_client=ClientMock, + logger=logger, + ) + config = CONFIG.servers["PresenceConnectionManager"] + create_mock_url(config, NewUserHandler, { + "user_id": 0, "profile_id": 0, "operation_id": 0}) + create_mock_url( + config, + LoginHandler, + { + "response_proof": "7f2c9c6685570ea18b7207d2cbd72452", + "data": { + "user_id": 0, + "profile_id": 0, + "nick": "test", + "email": "test@gamespy.com", + "unique_nick": "test_unique", + "password_hash": "password", + "email_verified_flag": True, + "namespace_id": 0, + "sub_profile_id": 0, + "banned_flag": False, + }, + "operation_id": 0, + "user_data": "", + "type": 0, + "partner_id": 0, + "user_challenge": "xMsHUXuWNXL3KMwmhoQZJrP0RVsArCYT" + }, + ) + + return cast(Client, conn._client) diff --git a/src/frontends/tests/gamespy/presence_connection_manager/request_tests.py b/src/frontends/tests/gamespy/presence_connection_manager/request_tests.py new file mode 100644 index 000000000..01a502cfb --- /dev/null +++ b/src/frontends/tests/gamespy/presence_connection_manager/request_tests.py @@ -0,0 +1,174 @@ +import unittest +from frontends.gamespy.protocols.presence_connection_manager.contracts.requests import ( + AddBuddyRequest, + DelBuddyRequest, + InviteToRequest, + StatusRequest, + LoginRequest, + AddBlockRequest, + GetProfileRequest, + NewProfileRequest, + RegisterCDKeyRequest, + RegisterNickRequest, + UpdateProfileRequest, +) + +from frontends.gamespy.protocols.presence_connection_manager.aggregates.enums import ( + LoginType, + QuietModeType, + SdkRevisionType, +) + +ADD_BLOCK = "\\addblock\\\\profileid\\0\\final\\" +GET_PROFILE = "\\getprofile\\\\sesskey\\xxxx\\profileid\\0\\final\\" +NEW_PROFILE = "\\newprofile\\\\sesskey\\xxxx\\nick\\spyguy\\id\\1\\final\\" +NEW_PROFILE_REPLACE = "\\newprofile\\\\sesskey\\xxxx\\nick\\spyguy2\\replace\\1\\oldnick\\spyguy\\id\\1\\final\\" +REGISTER_CD_KEY = "\\registercdkey\\\\sesskey\\xxxx\\cdkeyenc\\xxxx\\id\\1\\final\\" +REGISTER_NICK = ( + "\\registernick\\\\sesskey\\xxxx\\uniquenick\\spyguy\\partnerid\\0\\id\\1\\final\\" +) + + +LOGIN_AUTH_TOKEN = "\\login\\\\challenge\\xxxx\\authtoken\\example_auth\\userid\\1\\profileid\\1\\partnerid\\0\\response\\xxxxx\\firewall\\1\\port\\0000\\productid\\0\\gamename\\gmtest\\sdkrevision\\4\\quiet\\0\\id\\1\\final\\" +LOGIN_UNIQUE_NICK = "\\login\\\\challenge\\xxxx\\uniquenick\\spyguy\\userid\\1\\profileid\\1\\namespaceid\\0\\partnerid\\0\\response\\xxxxx\\firewall\\1\\port\\0000\\productid\\0\\gamename\\gmtest\\sdkrevision\\4\\quiet\\0\\id\\1\\final\\" +LOGIN_USER = "\\login\\\\challenge\\xxxx\\user\\spyguy@spyguy@gamespy.com\\userid\\0\\profileid\\0\\partnerid\\0\\namespaceid\\0\\response\\xxxxx\\firewall\\1\\port\\0000\\productid\\0\\gamename\\gmtest\\sdkrevision\\4\\quiet\\0\\id\\1\\final\\" + +ADD_BUDDY = "\\addbuddy\\\\sesskey\\0\\newprofileid\\0\\reason\\test\\final\\" +DEL_BUDDY = "\\delbuddy\\\\sesskey\\0\\delprofileid\\0\\final\\" +INVITE_TO = "\\inviteto\\\\sesskey\\0\\productid\\0\\profileid\\0\\final\\" +STATUS = [ + "\\status\\0\\sesskey\\1111\\statstring\\test\\locstring\\test\\final\\", + "\\status\\1\\sesskey\\1111\\statstring\\Not Ready\\locstring\\gptestc\\final\\", +] + + +class RequestTests(unittest.TestCase): + # region General + def test_login_auth_token(self) -> None: + request = LoginRequest(LOGIN_AUTH_TOKEN) + request.parse() + self.assertEqual(LoginType.AUTH_TOKEN, request.type) + self.assertEqual("xxxx", request.user_challenge) + self.assertEqual("example_auth", request.auth_token) + self.assertEqual(1, request.user_id) + self.assertEqual(1, request.profile_id) + self.assertEqual(0, request.partner_id) + self.assertEqual("xxxxx", request.response) + self.assertEqual(True, request.firewall) + self.assertEqual(request.game_port, 0) + self.assertEqual(request.product_id, 0) + self.assertEqual("gmtest", request.game_name) + self.assertEqual( + SdkRevisionType.GPINEW_REVOKE_NOTIFICATION, request.sdk_revision_type[0] + ) + self.assertEqual(QuietModeType.SILENCE_NONE, request.quiet_mode_flags) + + def test_login_unique_nick(self) -> None: + request = LoginRequest(LOGIN_UNIQUE_NICK) + request.parse() + self.assertEqual(LoginType.UNIQUENICK_NAMESPACE_ID, request.type) + self.assertEqual("xxxx", request.user_challenge) + self.assertEqual("spyguy", request.unique_nick) + self.assertEqual(0, request.namespace_id) + self.assertEqual(1, request.user_id) + self.assertEqual(1, request.profile_id) + self.assertEqual(0, request.partner_id) + self.assertEqual("xxxxx", request.response) + self.assertEqual(True, request.firewall) + self.assertEqual(0, request.game_port) + self.assertEqual(0, request.product_id) + self.assertEqual("gmtest", request.game_name) + self.assertEqual( + SdkRevisionType.GPINEW_REVOKE_NOTIFICATION, request.sdk_revision_type[0] + ) + self.assertEqual(QuietModeType.SILENCE_NONE, request.quiet_mode_flags) + + def test_login_user(self) -> None: + request = LoginRequest(LOGIN_USER) + request.parse() + self.assertEqual(LoginType.NICK_EMAIL, request.type) + self.assertEqual("xxxx", request.user_challenge) + self.assertEqual("spyguy", request.nick) + self.assertEqual("spyguy@gamespy.com", request.email) + self.assertEqual(0, request.namespace_id) + self.assertEqual(0, request.user_id) + self.assertEqual(0, request.profile_id) + self.assertEqual(0, request.partner_id) + self.assertEqual("xxxxx", request.response) + self.assertEqual(True, request.firewall) + self.assertEqual(0, request.game_port) + self.assertEqual(0, request.product_id) + self.assertEqual("gmtest", request.game_name) + self.assertEqual( + SdkRevisionType.GPINEW_REVOKE_NOTIFICATION, request.sdk_revision_type[0] + ) + self.assertEqual(QuietModeType.SILENCE_NONE, request.quiet_mode_flags) + # region Profile + + def test_add_block(self) -> None: + request = AddBlockRequest(ADD_BLOCK) + request.parse() + self.assertEqual(0, request.taget_id) + + def test_get_profile(self) -> None: + request = GetProfileRequest(GET_PROFILE) + request.parse() + self.assertEqual("xxxx", request.session_key) + self.assertEqual(0, request.profile_id) + + def test_new_profile(self) -> None: + request = NewProfileRequest(NEW_PROFILE) + request.parse() + self.assertEqual("xxxx", request.session_key) + self.assertEqual("spyguy", request.new_nick) + + def test_new_profile_replace(self) -> None: + request = NewProfileRequest(NEW_PROFILE_REPLACE) + request.parse() + self.assertEqual("xxxx", request.session_key) + self.assertEqual("spyguy2", request.new_nick) + self.assertEqual("spyguy", request.old_nick) + + def test_register_cd_key(self) -> None: + request = RegisterCDKeyRequest(REGISTER_CD_KEY) + request.parse() + self.assertEqual("xxxx", request.session_key) + self.assertEqual("xxxx", request.cdkey_enc) + + def test_register_nick(self) -> None: + request = RegisterNickRequest(REGISTER_NICK) + request.parse() + self.assertEqual("xxxx", request.session_key) + self.assertEqual("spyguy", request.unique_nick) + self.assertEqual(0, request.partner_id) + + def test_update_profile(self) -> None: + crysisWarsRaw = "\\updatepro\\\\sesskey\\1111\\countrycode\\DE\\birthday\\168232912\\partnerid\\0\\final\\" + request = UpdateProfileRequest(crysisWarsRaw) + request.parse() + + # region Buddy + def test_add_buddy(self) -> None: + request = AddBuddyRequest(ADD_BUDDY) + request.parse() + self.assertEqual(0, request.friend_profile_id) + self.assertEqual("test", request.reason) + + def test_del_buddy(self) -> None: + request = DelBuddyRequest(DEL_BUDDY) + request.parse() + self.assertEqual(0, request.friend_profile_id) + + def test_invite_to(self) -> None: + request = InviteToRequest(INVITE_TO) + request.parse() + self.assertEqual(0, request.product_id) + self.assertEqual(0, request.profile_id) + + def test_status_test(self) -> None: + request = StatusRequest(STATUS[0]) + request.parse() + self.assertEqual("test", request.status_string) + self.assertEqual("test", request.location_string) + request = StatusRequest(STATUS[1]) + request.parse() diff --git a/src/frontends/tests/gamespy/presence_search_player/__init__.py b/src/frontends/tests/gamespy/presence_search_player/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/tests/gamespy/presence_search_player/game_tests.py b/src/frontends/tests/gamespy/presence_search_player/game_tests.py new file mode 100644 index 000000000..fad562804 --- /dev/null +++ b/src/frontends/tests/gamespy/presence_search_player/game_tests.py @@ -0,0 +1,33 @@ +from typing import TYPE_CHECKING, cast +import unittest + +from frontends.gamespy.protocols.presence_search_player.contracts.requests import CheckRequest +from frontends.gamespy.protocols.presence_search_player.applications.switcher import Switcher +import responses + +from frontends.gamespy.protocols.presence_search_player.contracts.responses import CheckResponse +from frontends.tests.gamespy.presence_search_player.mock_objects import create_client + + +class GameTest(unittest.TestCase): + @responses.activate + def test_check(self): + raw = "\\check\\\\nick\\spyguy\\email\\spyguy@gamespy.com\\pass\\0000\\final\\" + client = create_client() + + switcher = Switcher(client, raw) + switcher.handle() + request = switcher._handlers[0]._request + if TYPE_CHECKING: + request = cast(CheckRequest, request) + response = switcher._handlers[0]._response + if TYPE_CHECKING: + response = cast(CheckResponse, response) + self.assertEqual("spyguy", request.nick) + self.assertEqual("spyguy@gamespy.com", request.email) + self.assertEqual("4a7d1ed414474e4033ac29ccb8653d9b", request.password) + self.assertEqual("\\cur\\0\\pid\\0\\final\\", response.sending_buffer) + + +if __name__ == "__main__": + unittest.main() diff --git a/src/frontends/tests/gamespy/presence_search_player/handler_tests.py b/src/frontends/tests/gamespy/presence_search_player/handler_tests.py new file mode 100644 index 000000000..0a9b0815a --- /dev/null +++ b/src/frontends/tests/gamespy/presence_search_player/handler_tests.py @@ -0,0 +1,69 @@ +import unittest + +import responses + +from frontends.gamespy.protocols.presence_search_player.contracts.requests import SearchRequest +from frontends.gamespy.protocols.presence_search_player.applications.handlers import SearchHandler +from frontends.tests.gamespy.presence_search_player.mock_objects import create_client +CHECK1 = "\\check\\\\nick\\spyguy\\email\\spyguy@gamespy.com\\pass\\0000\\final\\" + +SEARCH_1 = "\\search\\\\sesskey\\xxxx\\profileid\\1\\namespaceid\\0\\uniquenick\\spyguy\\firstname\\spy\\lastname\\guy\\icquin\\123\\skip\\0\\gamename\\gmtest\\final\\" +SEARCH_2 = "\\search\\\\sesskey\\xxxx\\profileid\\1\\nick\\spyguy\\email\\spyguy@gamespy.com\\firstname\\spy\\lastname\\guy\\icquin\\123\\skip\\0\\gamename\\gmtest\\final\\" +SEARCH_3 = "\\search\\\\sesskey\\xxxx\\profileid\\1\\nick\\spyguy\\firstname\\spy\\lastname\\guy\\icquin\\123\\skip\\0\\gamename\\gmtest\\final\\" +SEARCH_4 = "\\search\\\\sesskey\\xxxx\\profileid\\1\\email\\spyguy@gamespy.com\\firstname\\spy\\lastname\\guy\\icquin\\123\\skip\\0\\gamename\\gmtest\\final\\" + +SEARCH_UNIQUENICK = "\\searchunique\\\\sesskey\\xxxx\\profileid\\0\\uniquenick\\spyguy\\namespaces\\1,2,3,4,5\\gamename\\gmtest\\final\\" + +VALID = "\\valid\\\\email\\spyguy@gamespy.com\\partnerid\\1\\gamename\\gmtest\\final\\" + +NICKS = "\\nicks\\\\email\\spyguy@gamespy.com\\passenc\\xxxxx\\namespaceid\\0\\partnerid\\0\\gamename\\gmtest\\final\\" + + +PMATCH = "\\pmatch\\\\sesskey\\123456\\profileid\\0\\productid\\0\\final\\" + +NEWUSER = "\\newuser\\\\nick\\xiaojiuwo\\email\\xiaojiuwo@gamespy.com\\passenc\\xxxx\\productID\\0\\namespaceid\\0\\uniquenick\\xiaojiuwo\\cdkey\\xxx-xxx-xxx-xxx\\partnerid\\0\\gamename\\gmtest\\final\\" + +OTHER_BUDDY = "\\others\\\\sesskey\\123456\\profileid\\0\\namespaceid\\0\\gamename\\gmtest\\final\\" + +OTHERS_BUDDY_LIST = "\\otherlist\\\\sesskey\\123456\\profileid\\0\\numopids\\2\\opids\\1|2\\namespaceid\\0\\gamename\\gmtest\\final\\" + +SUGGEST_UNIQUE = "\\uniquesearch\\\\preferrednick\\xiaojiuwo\\namespaceid\\0\\gamename\\gmtest\\final\\" + + +class HandlerTests(unittest.TestCase): + + @responses.activate + def test_profile(self): + client = create_client() + request = SearchRequest(SEARCH_1) + request.parse() + self.assertEqual("xxxx", request.session_key) + self.assertEqual("spyguy", request.uniquenick) + self.assertEqual(0, request.profile_id) + self.assertEqual(0, request.namespace_id) + self.assertEqual(0, request.skip_num) + self.assertEqual("spy", request.firstname) + self.assertEqual("guy", request.lastname) + self.assertEqual("123", request.icquin) + + request = SearchRequest(SEARCH_2) + request.parse() + self.assertEqual("spyguy", request.nick) + self.assertEqual("spyguy@gamespy.com", request.email) + + request = SearchRequest(SEARCH_3) + request.parse() + self.assertEqual("spyguy", request.nick) + + request = SearchRequest(SEARCH_4) + request.parse() + self.assertEqual("spyguy@gamespy.com", request.email) + + handler = SearchHandler(client, request) + handler.handle() + self.assertEqual("\\bsr\\0\\nick\\spyguy\\uniquenick\\spyguy\\namespaceid\\0\\firstname\\spy\\lastname\\guy\\email\\spyguy@gamespy.com\\bsrdone\\\\more\\0\\final\\", + handler._response.sending_buffer) + + +if __name__ == "__main__": + unittest.main() diff --git a/src/frontends/tests/gamespy/presence_search_player/mock_objects.py b/src/frontends/tests/gamespy/presence_search_player/mock_objects.py new file mode 100644 index 000000000..83dfbeec0 --- /dev/null +++ b/src/frontends/tests/gamespy/presence_search_player/mock_objects.py @@ -0,0 +1,28 @@ +from typing import cast +from frontends.gamespy.library.configs import CONFIG +from frontends.tests.gamespy.library.mock_objects import ConnectionMock, LogMock, RequestHandlerMock, create_mock_url +from frontends.gamespy.protocols.presence_search_player.applications.client import Client +from frontends.gamespy.protocols.presence_search_player.applications.handlers import CheckHandler, SearchHandler +from frontends.gamespy.protocols.presence_search_player.contracts.results import CheckResult, SearchResult + + +class ClientMock(Client): + pass + + +def create_client() -> Client: + CONFIG.unittest.is_raise_except = True + handler = RequestHandlerMock() + logger = LogMock() + conn = ConnectionMock( + handler=handler, + config=CONFIG.servers["PresenceSearchPlayer"], t_client=ClientMock, + logger=logger) + config = CONFIG.servers["PresenceSearchPlayer"] + create_mock_url(config, CheckHandler, CheckResult.model_validate( + {"profile_id": 0}).model_dump()) + + create_mock_url(config, SearchHandler, SearchResult.model_validate({"data": [{"profile_id": 0, "nick": "spyguy", "uniquenick": "spyguy", + "email": "spyguy@gamespy.com", "firstname": "spy", "lastname": "guy", "namespace_id": 0}]}).model_dump()) + + return cast(Client, conn._client) diff --git a/src/frontends/tests/gamespy/query_report/__init__.py b/src/frontends/tests/gamespy/query_report/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/tests/gamespy/query_report/game_tests.py b/src/frontends/tests/gamespy/query_report/game_tests.py new file mode 100644 index 000000000..00490ae00 --- /dev/null +++ b/src/frontends/tests/gamespy/query_report/game_tests.py @@ -0,0 +1,18 @@ +import unittest + +import responses +from frontends.tests.gamespy.query_report.mock_objects import create_client + + +class GameTests(unittest.TestCase): + @responses.activate + def test_faltout2(self): + raw = b'\x03\xc2\x94\x1c\xe7localip0\x00192.168.0.50\x00localip1\x00172.16.74.1\x00localip2\x00172.17.0.1\x00localip3\x00192.168.122.1\x00localip4\x00172.16.65.1\x00localport\x0023756\x00natneg\x001\x00statechanged\x001\x00gamename\x00flatout2pc\x00publicip\x000\x00publicport\x000\x00hostkey\x00-820966322\x00hostname\x00Spore\x00gamever\x00FO14\x00gametype\x00race\x00gamevariant\x00normal_race\x00gamemode\x00openwaiting\x00numplayers\x001\x00maxplayers\x008\x00mapname\x00Timberlands_1\x00timelimit\x000\x00password\x000\x00car_type\x000\x00car_class\x000\x00races_p\x00100\x00derbies_p\x000\x00stunts_p\x000\x00normal_race_p\x00100\x00pong_race_p\x000\x00wreck_derby_p\x000\x00survivor_derby_p\x000\x00frag_derby_p\x000\x00tag_p\x000\x00upgrades\x002\x00nitro_regeneration\x002\x00damage_level\x002\x00derby_damage_level\x001\x00next_race_type\x00normal_race\x00laps_or_timelimit\x004\x00num_races\x001\x00num_derbies\x000\x00num_stunts\x000\x00datachecksum\x003546d58093237eb33b2a96bb813370d846ffcec8\x00\x00\x00\x00\x00\x00\x00\x00' + client = create_client() + client.on_received(raw) + + @responses.activate + def test_worm3d(self): + raw = b'\x03Q]\xa0\xe8localip0\x00192.168.0.60\x00localport\x006500\x00natneg\x001\x00statechanged\x003\x00gamename\x00worms3\x00hostname\x00test\x00gamemode\x00openstaging\x00groupid\x00622\x00numplayers\x001\x00maxplayers\x002\x00hostname\x00test\x00hostport\x00\x00maxplayers\x002\x00numplayers\x001\x00SchemeChanging\x000\x00gamever\x001073\x00gametype\x00\x00mapname\x00\x00firewall\x000\x00publicip\x00255.255.255.255\x00privateip\x00192.168.0.60\x00gamemode\x00openstaging\x00val\x000\x00password\x000\x00\x00\x00\x01player_\x00ping_\x00hostname\x00hostport\x00maxplayers\x00numplayers\x00SchemeChanging\x00gamever\x00gametype\x00mapname\x00firewall\x00publicip\x00privateip\x00gamemode\x00val\x00password\x00\x00worms10\x000\x00\x00\x00\x00\x00\x001073\x00\x00\x001\x00255.255.255.255\x00192.168.0.60\x00\x000\x00\x00\x00\x00hostname\x00hostport\x00maxplayers\x00numplayers\x00SchemeChanging\x00gamever\x00gametype\x00mapname\x00firewall\x00publicip\x00privateip\x00gamemode\x00val\x00password\x00\x00' + client = create_client() + client.on_received(raw) diff --git a/src/frontends/tests/gamespy/query_report/mock_objects.py b/src/frontends/tests/gamespy/query_report/mock_objects.py new file mode 100644 index 000000000..4847c6793 --- /dev/null +++ b/src/frontends/tests/gamespy/query_report/mock_objects.py @@ -0,0 +1,26 @@ +from typing import cast +from frontends.gamespy.library.configs import CONFIG +from frontends.gamespy.protocols.query_report.applications.client import Client +from frontends.gamespy.protocols.query_report.v2.applications.handlers import AvailableHandler, HeartbeatHandler, KeepAliveHandler +from frontends.gamespy.protocols.query_report.v2.contracts.results import HeartbeatResult +from frontends.tests.gamespy.library.mock_objects import ConnectionMock, LogMock, RequestHandlerMock, create_mock_url + + +class ClientMock(Client): + pass + + +def create_client() -> Client: + CONFIG.unittest.is_raise_except = True + handler = RequestHandlerMock() + logger = LogMock() + conn = ConnectionMock( + handler=handler, + config=CONFIG.servers["QueryReport"], t_client=ClientMock, + logger=logger) + config = CONFIG.servers["QueryReport"] + create_mock_url(config, HeartbeatHandler, HeartbeatResult.model_validate( + {"remote_ip": conn.remote_ip, "remote_port": conn.remote_port, "instant_key": "123", "command_name": 3}).model_dump(mode='json')) + create_mock_url(config, AvailableHandler, {"message": "ok"}) + create_mock_url(config, KeepAliveHandler, {"message": "ok"}) + return cast(Client, conn._client) diff --git a/src/frontends/tests/gamespy/query_report/request_tests.py b/src/frontends/tests/gamespy/query_report/request_tests.py new file mode 100644 index 000000000..bc64519c0 --- /dev/null +++ b/src/frontends/tests/gamespy/query_report/request_tests.py @@ -0,0 +1,58 @@ +import unittest + +from frontends.gamespy.protocols.query_report.v2.aggregates.enums import RequestType +from frontends.gamespy.protocols.query_report.v2.contracts.requests import AvaliableRequest, ChallengeRequest, EchoRequest, HeartbeatRequest + +AVALIABLE_REQUEST = bytes([0x09, # packet type + 0x00, 0x00, 0x00, 0x00, # instant key + 0x09, 0x00, 0x00, 0x00, 0x00, # prefix + 0x67, 0x61, 0x6D, 0x65, 0x73, 0x70, 0x79, # gamename + 0x00]) + +CHALLENGE_REQUEST = bytes([ + 0x01, # packet type + 0x00, 0x00, 0x00, 0x00, # instant key + 0x67, 0x61, 0x6D, 0x65, 0x73, 0x70, 0x79, # gamename + 0x00 +]) + +ECHO_REQUEST = bytes([ + 0x02, # packet type + 0x00, 0x00, 0x00, 0x00, # instant key + 0x67, 0x61, 0x6D, 0x65, 0x73, 0x70, 0x79, # gamename + 0x00 +]) + +HEARTBEAT_REQUEST = bytes([ + 0x03, 0xae, 0x1f, 0x77, 0x64, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x70, 0x30, 0x00, 0x31, 0x39, 0x32, 0x2e, 0x31, 0x36, 0x38, 0x2e, 0x30, 0x2e, 0x31, 0x30, 0x39, 0x00, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x70, 0x6f, 0x72, 0x74, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x00, 0x6e, 0x61, 0x74, 0x6e, 0x65, 0x67, 0x00, 0x31, 0x00, 0x73, 0x74, 0x61, 0x74, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x00, 0x33, 0x00, 0x67, 0x61, 0x6d, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x67, 0x6d, 0x74, 0x65, 0x73, 0x74, 0x00, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x47, 0x61, 0x6d, 0x65, 0x53, 0x70, 0x79, 0x20, 0x51, 0x52, 0x32, 0x20, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x00, 0x67, 0x61, 0x6d, 0x65, 0x76, 0x65, 0x72, 0x00, 0x32, 0x2e, 0x30, 0x30, 0x00, 0x68, 0x6f, 0x73, 0x74, 0x70, 0x6f, 0x72, 0x74, 0x00, 0x32, 0x35, 0x30, 0x30, 0x30, 0x00, 0x6d, 0x61, 0x70, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x67, 0x6d, 0x74, 0x6d, 0x61, 0x70, 0x31, 0x00, 0x67, 0x61, 0x6d, 0x65, 0x74, 0x79, 0x70, 0x65, 0x00, 0x61, 0x72, 0x65, 0x6e, 0x61, 0x00, 0x6e, 0x75, 0x6d, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x00, 0x36, 0x00, 0x6e, 0x75, 0x6d, 0x74, 0x65, 0x61, 0x6d, 0x73, 0x00, 0x32, 0x00, 0x6d, 0x61, 0x78, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x00, 0x33, 0x32, 0x00, 0x67, 0x61, 0x6d, 0x65, 0x6d, 0x6f, 0x64, 0x65, 0x00, 0x6f, 0x70, 0x65, 0x6e, 0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x00, 0x74, 0x65, 0x61, 0x6d, 0x70, 0x6c, 0x61, 0x79, 0x00, 0x31, 0x00, 0x66, 0x72, 0x61, 0x67, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x00, 0x30, 0x00, 0x74, 0x69, 0x6d, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x00, 0x34, 0x30, 0x00, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x79, 0x00, 0x38, 0x30, 0x30, 0x00, 0x72, 0x61, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x6f, 0x6e, 0x00, 0x31, 0x00, 0x00, 0x00, 0x06, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x00, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x00, 0x64, 0x65, 0x61, 0x74, 0x68, 0x73, 0x5f, 0x00, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x00, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x00, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x00, 0x00, 0x4a, 0x6f, 0x65, 0x20, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x00, 0x32, 0x37, 0x00, 0x36, 0x00, 0x31, 0x32, 0x33, 0x00, 0x31, 0x00, 0x34, 0x30, 0x39, 0x00, 0x4c, 0x33, 0x33, 0x74, 0x20, 0x30, 0x6e, 0x33, 0x00, 0x36, 0x00, 0x32, 0x33, 0x00, 0x32, 0x37, 0x37, 0x00, 0x30, 0x00, 0x36, 0x37, 0x33, 0x00, 0x52, 0x61, 0x70, 0x74, 0x6f, 0x72, 0x00, 0x33, 0x30, 0x00, 0x31, 0x00, 0x31, 0x34, 0x36, 0x00, 0x31, 0x00, 0x37, 0x30, 0x31, 0x00, 0x47, 0x72, 0x38, 0x31, 0x00, 0x32, 0x31, 0x00, 0x31, 0x36, 0x00, 0x31, 0x32, 0x35, 0x00, 0x31, 0x00, 0x35, 0x38, 0x32, 0x00, 0x46, 0x6c, 0x75, 0x62, 0x62, 0x65, 0x72, 0x00, 0x33, 0x00, 0x32, 0x31, 0x00, 0x31, 0x31, 0x30, 0x00, 0x30, 0x00, 0x32, 0x39, 0x38, 0x00, 0x53, 0x61, 0x72, 0x67, 0x65, 0x00, 0x33, 0x00, 0x32, 0x38, 0x00, 0x31, 0x32, 0x35, 0x00, 0x31, 0x00, 0x35, 0x39, 0x30, 0x00, 0x00, 0x02, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x74, 0x00, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x74, 0x00, 0x61, 0x76, 0x67, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x00, 0x00, 0x52, 0x65, 0x64, 0x00, 0x32, 0x39, 0x34, 0x00, 0x33, 0x37, 0x39, 0x00, 0x42, 0x6c, 0x75, 0x65, 0x00, 0x38, 0x39, 0x00, 0x33, 0x38, 0x33, 0x00]) + + +class RequestTest(unittest.TestCase): + def test_available(self): + request = AvaliableRequest(AVALIABLE_REQUEST) + request.parse() + self.assertEqual(RequestType.AVALIABLE_CHECK, request.command_name) + self.assertEqual("0", request.instant_key) + + def test_challenge(self): + + request = ChallengeRequest(CHALLENGE_REQUEST) + request.parse() + self.assertEqual(RequestType.CHALLENGE, request.command_name) + self.assertEqual("0", request.instant_key) + + def test_echo_request(self): + + request = EchoRequest(ECHO_REQUEST) + request.parse() + self.assertEqual(RequestType.ECHO, request.command_name) + self.assertEqual("0", request.instant_key) + + def test_heartbeat(self): + + request = HeartbeatRequest(HEARTBEAT_REQUEST) + request.parse() + self.assertEqual("gmtest", request.game_name) + self.assertEqual("2921297764", request.instant_key) + assert request.data is not None + self.assertEqual(61, len(request.data)) diff --git a/src/frontends/tests/gamespy/server_browser/__init__.py b/src/frontends/tests/gamespy/server_browser/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/tests/gamespy/server_browser/contract_tests.py b/src/frontends/tests/gamespy/server_browser/contract_tests.py new file mode 100644 index 000000000..0f4de0e92 --- /dev/null +++ b/src/frontends/tests/gamespy/server_browser/contract_tests.py @@ -0,0 +1,64 @@ +from datetime import datetime +import unittest +from uuid import UUID + +from frontends.gamespy.protocols.query_report.aggregates.enums import GameServerStatus +from frontends.gamespy.protocols.query_report.aggregates.game_server_info import ( + GameServerInfo, +) + +from frontends.gamespy.protocols.server_browser.v2.aggregations.enums import ( + GameServerFlags, + ServerListUpdateOption, +) +from frontends.gamespy.protocols.server_browser.v2.applications.switcher import Switcher +from frontends.gamespy.protocols.server_browser.v2.contracts.responses import ( + ServerMainListResponse, +) +from frontends.gamespy.protocols.server_browser.v2.contracts.results import ( + ServerMainListResult, +) + + +class ResponseTests(unittest.TestCase): + def test_main_list(self): + result = ServerMainListResult( + client_remote_ip="127.0.0.1", + flag=GameServerFlags.HAS_KEYS_FLAG, + game_secret_key="xxxx", + keys=["hostname", "gametype", "mapname", + "numplayers", "maxplayers"], + servers_info=[ + GameServerInfo( + server_id=UUID("950b7638-a90d-469b-ac1f-861e63c8c613"), + instant_key="12356", + game_name="gmtest", + query_report_port=6900, + update_time=datetime.now(), + status=GameServerStatus.NORMAL, + data={"hostname": "GameSpy QR2 Sample", "gametype": "", + "mapname": "", "numplayers": "", "maxplayers": ""}, + host_ip_address="127.0.0.1", + ) + ], + ) + response = ServerMainListResponse(result) + response.build() + correct = b'\xee\x00\x00\xe00000000000\x7f\x00\x00\x01\x19d\x05\x00hostname\x00\x00gametype\x00\x00mapname\x00\x00numplayers\x00\x00maxplayers\x00\x00P\x7f\x00\x00\x01\x1a\xf4\xffGameSpy QR2 Sample\x00\xff\x00\xff\x00\xff\x00\xff\x00\x00\xff\xff\xff\xff' + self.assertTrue(response.sending_buffer == correct) + + def test_server_list_with_filter(self): + """ + filter: US servers with more than 5 players, or servers with a hostname containing 'GameSpy' + """ + raw = b"\x00\x95\x00\x01\x03\x00\x00\x00\x00gmtest\x00gmtest\x000`mpW:[>(country = 'US' and numplayers > 5) or hostname like ' % GameSpy % '\x00\\hostname\\gametype\\mapname\\numplayers\\maxplayers\x00\x00\x00\x00\x00" + + def test_server_info_request(self): + raw = b'\x00%\x00\x01\x03\x00\x00\x00\x00gmtest\x00gmtest\x00$(A:{<]p\x00\x00\x00\x00\x00\x02\x00\t\x01\xac\x13\x00\x05+g' + option = Switcher.get_update_option(raw) + self.assertEqual(option, ServerListUpdateOption.SERVER_FULL_INFO_LIST) + pass + + +if __name__ == "__main__": + ResponseTests().test_server_info_request() diff --git a/src/frontends/tests/gamespy/server_browser/encrypt_tests.py b/src/frontends/tests/gamespy/server_browser/encrypt_tests.py new file mode 100644 index 000000000..8048c6c60 --- /dev/null +++ b/src/frontends/tests/gamespy/server_browser/encrypt_tests.py @@ -0,0 +1,29 @@ +import unittest + +from frontends.gamespy.protocols.server_browser.v2.aggregations.encryption import Byte, EnctypeX + + +class EncryptionTest(unittest.TestCase): + def test_enctypex(self): + """ + test if enctypex param init correctness + """ + enc = EnctypeX("000000", "00000000") + self.assertTrue(enc._enc_params.index_0.value == 250) + self.assertTrue(enc._enc_params.index_1.value == 220) + self.assertTrue(enc._enc_params.index_2.value == 245) + self.assertTrue(enc._enc_params.index_3.value == 229) + self.assertTrue(enc._enc_params.index_4.value == 49) + register = b"\x7A\xFA\x64\xDC\xB9\xF5\xF6\xE5\x89\x84\x9D\x66\xD7\xEA\x8E\xD8\xD4\xC0\xA1\xA4\x67\xA9\xAA\xDF\xF0\x71\x99\xEC\x87\xFD\xD0\xA2\xF3\xB5\xE3\x01\xE7\x7D\xE9\xE2\xEB\x97\xF1\x6F\x70\xFC\xD6\xFB\x82\x95\xC1\xB1\xD9\xBF\xD1\xE0\x9E\x81\xE8\xBB\xE1\xF8\xAD\xDA\xDB\xE4\x65\xAE\xCE\xAB\xB4\xBD\xA5\xB6\xB8\xEE\xF4\x75\xBC\xC3\xC6\xB7\xC8\xC9\xBA\xA6\xC4\xC5\x85\x6B\x78\x6D\xC2\xA7\xCC\xCD\x62\x9F\xBE\xA8\xCB\xB0\xE6\xDD\x79\xA3\xCA\xF2\xCF\xAC\x6A\xEF\xFE\xED\xD5\xB2\xDE\xB3\x72\xF7\x6C\xF9\xC7\x39\xA0\xAF\x77\x35\x73\x74\x68\x76\x8A\x80\x6E\x63\x7B\x7C\x7F\x98\x9B\x88\x91\x94\x83\x93\x8D\x86\x9C\x9A\x7E\x92\x8B\x8C\xD2\x96\x8F\x90\xFF\x41\x32\x33\x34\x3D\x36\x37\x38\x49\x3A\x3B\x3C\x45\x3E\x3F\x40\x51\x42\x43\x44\x4D\x46\x47\x48\x59\x4A\x4B\x4C\x55\x4E\x4F\x50\x61\x52\x53\x54\x5D\x56\x57\x58\x69\x5A\x5B\x5C\xD3\x5E\x5F\x60\x00\x09\x02\x03\x04\x05\x06\x07\x08\x11\x0A\x0B\x0C\x0D\x0E\x0F\x10\x19\x12\x13\x14\x15\x16\x17\x18\x21\x1A\x1B\x1C\x1D\x1E\x1F\x20\x29\x22\x23\x24\x25\x26\x27\x28\x31\x2A\x2B\x2C\x2D\x2E\x2F\x30" + temp_register = bytes([v.value for v in enc._enc_params.register]) + self.assertTrue(temp_register == register) + plain_text = bytes([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) + cipher = [] + for i in range(len(plain_text)): + c = enc.byte_shift(Byte(plain_text[i])) + cipher.append(c.value) + b_cipher = bytes(cipher) + correct_cipher = b"\x84\xF2\xF5\x20\xE8\x4D\x86\x67\xB6\xD3\xB3\xC0\x23\x0D\x40\x74\x67\xFE\x9C\x30" + self.assertTrue(b_cipher == correct_cipher) + pass diff --git a/src/frontends/tests/gamespy/server_browser/game_tests.py b/src/frontends/tests/gamespy/server_browser/game_tests.py new file mode 100644 index 000000000..0940a6448 --- /dev/null +++ b/src/frontends/tests/gamespy/server_browser/game_tests.py @@ -0,0 +1,65 @@ +import unittest + +import responses +from frontends.tests.gamespy.query_report.mock_objects import create_client +from frontends.tests.gamespy.server_browser.mock_objects import create_v2_client + + +class GameTest(unittest.TestCase): + @responses.activate + def test_gmtest_20200309(self): + qr_raw = b"\x03\xea+\xafPlocalip0\x00192.168.122.226\x00localport\x0011111\x00natneg\x001\x00statechanged\x003\x00gamename\x00gmtest\x00hostname\x00GameSpy QR2 Sample\x00gamever\x002.00\x00hostport\x0025000\x00mapname\x00gmtmap1\x00gametype\x00arena\x00numplayers\x0010\x00numteams\x002\x00maxplayers\x0032\x00gamemode\x00openplaying\x00teamplay\x001\x00fraglimit\x000\x00timelimit\x0040\x00gravity\x00800\x00rankingon\x001\x00\x00\x00\nplayer_\x00score_\x00deaths_\x00ping_\x00team_\x00time_\x00\x00Joe Player\x004\x002\x0077\x000\x00185\x00L33t 0n3\x006\x0024\x0068\x001\x00820\x00Raptor\x0010\x0029\x00216\x001\x00664\x00Gr81\x008\x006\x00327\x001\x00697\x00Flubber\x0015\x002\x00179\x000\x0048\x00Sarge\x009\x0012\x00337\x000\x00296\x00Void\x0027\x0029\x0045\x000\x00355\x00runaway\x0024\x004\x00197\x001\x00428\x00Ph3ar\x0030\x0030\x00339\x001\x00525\x00wh00t\x0031\x0028\x00269\x001\x0077\x00\x00\x02team_t\x00score_t\x00avgping_t\x00\x00Red\x00487\x00336\x00Blue\x0082\x00458\x00" + qr_client = create_client() + qr_client.on_received(qr_raw) + sb_raw = b"\x00\t\x01\xc0\xa8z\xe2+g" + sb_client = create_v2_client() + sb_client.on_received(sb_raw) + + @responses.activate + def test_anno1701_20220620(self): + qr_raws = [ + # available request + b"\t\x00\x00\x00\x00anno1701\x00", + b"\x03\x1dU\xcc\xcalocalip0\x00192.168.0.80\x00localport\x0021701\x00natneg\x001\x00statechanged\x003\x00gamename\x00anno1701\x00publicip\x000\x00publicport\x000\x00hostname\x00(unknown game)\x00gamemode\x00openstaging\x00numplayers\x001\x00maxplayers\x004\x00gamever\x0021903\x00mapname\x00Random map\x00gametype\x00Easy\x00password\x000\x00settings_options\x00377563076\x00numaiplayers\x00\x00openslots\x00\x00gamevariant\x00PvP\x00settings_winconditions\x000\x00settings_usercontent_mapname\x00\x00\x00\x00\x01player_\x00ping_\x00ping_\x00\x00anno1701_220\x000\x000\x00\x00\x01\x00", + b"\x03\x1dU\xcc\xcalocalip0\x00192.168.0.80\x00localport\x0021701\x00natneg\x001\x00statechanged\x003\x00gamename\x00anno1701\x00publicip\x000\x00publicport\x000\x00hostname\x00(unknown game)\x00gamemode\x00openstaging\x00numplayers\x001\x00maxplayers\x004\x00gamever\x0021903\x00mapname\x00Random map\x00gametype\x00Easy\x00password\x000\x00settings_options\x00377563076\x00numaiplayers\x00\x00openslots\x00\x00gamevariant\x00PvP\x00settings_winconditions\x000\x00settings_usercontent_mapname\x00\x00\x00\x00\x01player_\x00ping_\x00ping_\x00\x00anno1701_220\x000\x000\x00\x00\x01\x00", + b"\x03\x1dU\xcc\xcalocalip0\x00192.168.0.80\x00localport\x0021701\x00natneg\x001\x00statechanged\x001\x00gamename\x00anno1701\x00publicip\x000\x00publicport\x000\x00hostname\x00(unknown game)\x00gamemode\x00openstaging\x00numplayers\x001\x00maxplayers\x004\x00gamever\x0021903\x00mapname\x00Random map\x00gametype\x00Easy\x00password\x000\x00settings_options\x00109127620\x00numaiplayers\x000\x00openslots\x004\x00gamevariant\x00PvP\x00settings_winconditions\x000\x00settings_usercontent_mapname\x00\x00\x00\x00\x01player_\x00ping_\x00ping_\x00\x00anno1701_220\x000\x000\x00\x00\x01\x00", + b"\x03\x1dU\xcc\xcalocalip0\x00192.168.0.80\x00localport\x0021701\x00natneg\x001\x00statechanged\x001\x00gamename\x00anno1701\x00publicip\x000\x00publicport\x000\x00hostname\x00(unknown game)\x00gamemode\x00openstaging\x00numplayers\x001\x00maxplayers\x004\x00gamever\x0021903\x00mapname\x00Random map\x00gametype\x00Easy\x00password\x000\x00settings_options\x00109127620\x00numaiplayers\x000\x00openslots\x004\x00gamevariant\x00PvP\x00settings_winconditions\x000\x00settings_usercontent_mapname\x00\x00\x00\x00\x01player_\x00ping_\x00ping_\x00\x00anno1701_220\x000\x000\x00\x00\x01\x00", + b"\x03\x1dU\xcc\xcalocalip0\x00192.168.0.80\x00localport\x0021701\x00natneg\x001\x00gamename\x00anno1701\x00publicip\x000\x00publicport\x000\x00hostname\x00(unknown game)\x00gamemode\x00openstaging\x00numplayers\x001\x00maxplayers\x004\x00gamever\x0021903\x00mapname\x00Random map\x00gametype\x00Easy\x00password\x000\x00settings_options\x00109127620\x00numaiplayers\x000\x00openslots\x004\x00gamevariant\x00PvP\x00settings_winconditions\x000\x00settings_usercontent_mapname\x00\x00\x00\x00\x01player_\x00ping_\x00ping_\x00\x00anno1701_220\x000\x000\x00\x00\x01\x00", + b"\x03\x1dU\xcc\xcalocalip0\x00192.168.0.80\x00localport\x0021701\x00natneg\x001\x00gamename\x00anno1701\x00publicip\x000\x00publicport\x000\x00hostname\x00(unknown game)\x00gamemode\x00openstaging\x00numplayers\x001\x00maxplayers\x004\x00gamever\x0021903\x00mapname\x00Random map\x00gametype\x00Easy\x00password\x000\x00settings_options\x00109127620\x00numaiplayers\x000\x00openslots\x004\x00gamevariant\x00PvP\x00settings_winconditions\x000\x00settings_usercontent_mapname\x00\x00\x00\x00\x01player_\x00ping_\x00ping_\x00\x00anno1701_220\x000\x000\x00\x00\x01\x00", + b"\x03\x1dU\xcc\xcalocalip0\x00192.168.0.80\x00localport\x0021701\x00natneg\x001\x00gamename\x00anno1701\x00publicip\x000\x00publicport\x000\x00hostname\x00(unknown game)\x00gamemode\x00openstaging\x00numplayers\x001\x00maxplayers\x004\x00gamever\x0021903\x00mapname\x00Random map\x00gametype\x00Easy\x00password\x000\x00settings_options\x00109127620\x00numaiplayers\x000\x00openslots\x004\x00gamevariant\x00PvP\x00settings_winconditions\x000\x00settings_usercontent_mapname\x00\x00\x00\x00\x01player_\x00ping_\x00ping_\x00\x00anno1701_220\x000\x000\x00\x00\x01\x00", + # client message + b"\xfe\xfd\x03\x1dU\xcc\xcaTTT\x00\x00[+2\xba\x00\x00\x00\x00\xc5T\x00\x00", + # keep alive + b"\x08\x1dU\xcc\xca", + ] + sb_raws = [ + b"\x00\x9a\x00\x01\x03\x8fU\x00\x00anno1701\x00anno1701\x00D:@o)Okhgroupid is null\x00\\hostname\\gamemode\\gamever\\gametype\\password\\mapname\\numplayers\\numaiplayers\\openslots\\gamevariant\x00\x00\x00\x00\x04", + b"\x00\x9a\x00\x01\x03\x8fU\x00\x00anno1701\x00anno1701\x00AHl='lhIgroupid is null\x00\\hostname\\gamemode\\gamever\\gametype\\password\\mapname\\numplayers\\numaiplayers\\openslots\\gamevariant\x00\x00\x00\x00\x04", + b"\x00\x9a\x00\x01\x03\x8fU\x00\x00anno1701\x00anno1701\x00TsFhHjvQgroupid is null\x00\\hostname\\gamemode\\gamever\\gametype\\password\\mapname\\numplayers\\numaiplayers\\openslots\\gamevariant\x00\x00\x00\x00\x04", + b"\x00\t\x01[+2\xbaT\xc5", + b"\xfd\xfc\x1efj\xb2\x00\x00\x171", + ] + + qr_client = create_client() + for raw in qr_raws: + qr_client.on_received(raw) + + sb_client = create_v2_client() + for raw in sb_raws: + sb_client.crypto = None + sb_client.on_received(raw) + + @responses.activate + def test_anno1701_20221104(self): + qr_raw = { + "qr1": b"\t\x00\x00\x00\x00anno1701\x00", + "qr2": b"\x03\x98\x92%\xa0localip0\x00192.168.0.50\x00localip1\x00192.168.122.1\x00localport\x0021701\x00natneg\x001\x00statechanged\x003\x00gamename\x00anno1701\x00publicip\x000\x00publicport\x000\x00hostname\x00(unknown game)\x00gamemode\x00openstaging\x00numplayers\x001\x00maxplayers\x004\x00gamever\x0021903\x00mapname\x00Random map\x00gametype\x00Easy\x00password\x000\x00settings_options\x00369174468\x00numaiplayers\x00\x00openslots\x00\x00gamevariant\x00PvP\x00settings_winconditions\x000\x00settings_usercontent_mapname\x00\x00\x00\x00\x01player_\x00ping_\x00ping_\x00\x00sporesirius\x000\x000\x00\x00\x01\x00", + "sb1": b"\x00\x9a\x00\x01\x03\x8fU\x00\x00anno1701\x00anno1701\x00RcX;M({Ggroupid is null\x00\\hostname\\gamemode\\gamever\\gametype\\password\\mapname\\numplayers\\numaiplayers\\openslots\\gamevariant\x00\x00\x00\x00\x04", + "qr3": b"\x07\x98\x92%\xa0\x00\x00\x00\x00", + } + + @responses.activate + def test_aarts_20230618(self): + sb_raw = b"\x00\xb8\x00\x01\x03\x00\x00\x00\x00aarts\x00aarts\x00F|Cy9!&w\x00\\hostname\\gamemode\\hostport\\hostname\\gamename\\gametype\\gamever\\mapname\\numplayers\\maxplayers\\gamemode\\password\\groupid\\mapsessiontype\\mapids\\internet\x00\x00\x00\x00\x04" + client = create_v2_client() + client.on_received(sb_raw) diff --git a/src/frontends/tests/gamespy/server_browser/mock_objects.py b/src/frontends/tests/gamespy/server_browser/mock_objects.py new file mode 100644 index 000000000..06beef543 --- /dev/null +++ b/src/frontends/tests/gamespy/server_browser/mock_objects.py @@ -0,0 +1,92 @@ +from typing import cast +from frontends.gamespy.library.configs import CONFIG +from frontends.tests.gamespy.library.mock_objects import ( + ConnectionMock, + LogMock, + RequestHandlerMock, + create_mock_url, +) +from frontends.gamespy.protocols.server_browser.v2.applications.client import Client +from frontends.gamespy.protocols.server_browser.v2.applications.handlers import ( + UpdateServerInfoHandler, + ServerMainListHandler, +) +from frontends.gamespy.protocols.server_browser.v2.contracts.results import ( + UpdateServerInfoResult, + ServerMainListResult, +) + + +class ClientMock(Client): + pass + + +def create_v2_client() -> Client: + handler = RequestHandlerMock() + logger = LogMock() + conn = ConnectionMock( + handler=handler, + config=CONFIG.servers["ServerBrowserV2"], + t_client=ClientMock, + logger=logger, + ) + config = CONFIG.servers["ServerBrowserV2"] + + create_mock_url( + config, + ServerMainListHandler, + ServerMainListResult.model_validate( + { + "client_remote_ip": "127.0.0.1", + "flag": 64, + "game_secret_key": "123567", + "servers_info": [], + "keys": [] + } + ).model_dump(mode="json"), + ) + create_mock_url( + config, + UpdateServerInfoHandler, + UpdateServerInfoResult.model_validate( + { + "game_server_info": { + "server_id": "550e8400-e29b-41d4-a716-446655440000", + "host_ip_address": "192.168.1.1", + "instant_key": "123456", + "game_name": "Example Game", + "query_report_port": 8080, + "update_time": "2023-10-01T12:00:00Z", + "status": 3, + "data": { + "max_players": "100", + "current_players": "50", + "region": "US-East", + }, + } + } + ).model_dump(mode="json"), + ) + + return cast(Client, conn._client) + + +def create_v1_client() -> Client: + handler = RequestHandlerMock() + logger = LogMock() + conn = ConnectionMock( + handler=handler, + config=CONFIG.servers["ServerBrowserV1"], + t_client=ClientMock, + logger=logger, + ) + config = CONFIG.servers["ServerBrowserV1"] + create_mock_url( + config, + ServerMainListHandler, + ServerMainListResult.model_validate( + {"remote_ip": conn.remote_ip, "remote_port": conn.remote_port} + ).model_dump(), + ) + + return cast(Client, conn._client) diff --git a/src/frontends/tests/gamespy/web_services/__init__.py b/src/frontends/tests/gamespy/web_services/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/frontends/tests/gamespy/web_services/altas_tests.py b/src/frontends/tests/gamespy/web_services/altas_tests.py new file mode 100644 index 000000000..91cdac0d5 --- /dev/null +++ b/src/frontends/tests/gamespy/web_services/altas_tests.py @@ -0,0 +1,75 @@ +import unittest + +CREATE_MATCHLESS_SESSION = """ + + + + XXXXXX + XXXXXX + 0 + + + """ + +CREATE_SESSION = """ + + + + XXXXXX + XXXXXX + 0 + + + """ + +SET_REPORT_INTENTION = """ + + + + XXXXXX + XXXXXX + 0 + 0 + 0 + XXXXXX + + + """ + +SUBMIT_REPORT = """ + + + + XXXXXX + XXXXXX + 0 + 0 + 0 + XXXXXX + + + """ + + +class AltasTests(unittest.TestCase): + pass + + +if __name__ == "__main__": + unittest.main() diff --git a/src/frontends/tests/gamespy/web_services/auth_tests.py b/src/frontends/tests/gamespy/web_services/auth_tests.py new file mode 100644 index 000000000..4c02d4450 --- /dev/null +++ b/src/frontends/tests/gamespy/web_services/auth_tests.py @@ -0,0 +1,175 @@ +import unittest + +import responses + +from frontends.gamespy.protocols.web_services.modules.auth.contracts.requests import CreateUserAccountRequest, LoginProfileWithGameIdRequest, LoginPs3CertRequest, LoginRemoteAuthRequest, LoginUniqueNickRequest + +LOGIN_PROFILE = """ + + 1 + 0 + 0 + 0 + spyguy@gamespy.com + spyguy + + + 00026cfb61b75553fb113e8a158a1ce8c88dcb5415a405efeeb4ba605c315bb9204c09a53e23fb63081d208f44f813f5967c4da7d85f55ef66d4d39a4c89a9800771ee4f742bb808f35bced93fe7fa289eb4bdc94a44fa6f9121ef0eba4d3827d0cacaaeafdc85b64e4d9dc34814f6d4178363303f543a2fd8d8af0030303030 + + + + """ +LOGIN_PS3_CERT = """ + + + + 0 + 0 + 0 + 0001 + 0 + 0001 + + + """ + +LOGIN_REMOTE_AUTH = """ + + + + 1 + 0 + 0 + 0 + XXXXXXXXXXX + XXXXXXXXXXX + + + """ + +LOGIN_UNIQUENICK = """ + + + + 1 + 0 + 0 + spyguy + + XXXXXXXXXXX + + + + """ + +CRYSIS = """ + + + + 1 + 95 + 95 + spyguy + + 0000 + + + + """ + +CREATE_USER_ACCOUNT = """ + + 1 + 99 + 102 + 4C84AA7017F21B0A5B83B56D6D06C86D22E93662@example.com + 4C84AA7017F21B0A5B83 + 4C84AA7017F21B0A5B83B56D6D06C86D22E93662 + + 411CDA6489C3223A4FB6CA7BD6521F961679CFA5E04C6C95A988995658975B4B99D2C1E91629354F8422E470BDA5EC06614E42576E2E812A1792E75589EC9BDA0CF3B9D1D60BF1847A424717950AA1C81DD93CEF029F931A33359208D6EC2F0A8AEF3C49F1048E9D585D55AFA0A9E2D545EAF2DB0460B3DE2965EB55E5FF88A2 + + + """ + + +class AuthTests(unittest.TestCase): + @responses.activate + def test_create_user_account(self): + request = CreateUserAccountRequest(CREATE_USER_ACCOUNT) + request.parse() + pass + + @responses.activate + def test_crysis_auth(self): + + request = LoginUniqueNickRequest(CRYSIS) + request.parse() + + @responses.activate + def test_login_profile(self): + request = LoginProfileWithGameIdRequest(LOGIN_PROFILE) + request.parse() + self.assertEqual(1, request.version) + self.assertEqual(0, request.game_id) + self.assertEqual(0, request.partner_code) + self.assertEqual(0, request.namespace_id) + self.assertEqual("spyguy@gamespy.com", request.email) + self.assertEqual("spyguy", request.nick) + self.assertEqual("00026cfb61b75553fb113e8a158a1ce8c88dcb5415a405efeeb4ba605c315bb9204c09a53e23fb63081d208f44f813f5967c4da7d85f55ef66d4d39a4c89a9800771ee4f742bb808f35bced93fe7fa289eb4bdc94a44fa6f9121ef0eba4d3827d0cacaaeafdc85b64e4d9dc34814f6d4178363303f543a2fd8d8af0030303030", request.password) + + # handler = LoginProfileWithGameIdHandler(request) + # handler.handle() + + def test_login_ps3_cert(self): + request = LoginPs3CertRequest(LOGIN_PS3_CERT) + request.parse() + self.assertEqual(0, request.version) + self.assertEqual(0, request.game_id) + self.assertEqual(1, request.partner_code) + self.assertEqual(0, request.namespace_id) + self.assertEqual("0", request.ps3_cert) + self.assertEqual("0001", request.npticket) + + def test_remote_auth(self): + request = LoginRemoteAuthRequest(LOGIN_REMOTE_AUTH) + request.parse() + self.assertEqual(1, request.version) + self.assertEqual(0, request.game_id) + self.assertEqual(0, request.partner_code) + self.assertEqual(0, request.namespace_id) + self.assertEqual("XXXXXXXXXXX", request.auth_token) + self.assertEqual("XXXXXXXXXXX", request.challenge) + + def test_login_uniquenick(self): + request = LoginUniqueNickRequest(LOGIN_UNIQUENICK) + request.parse() + self.assertEqual(1, request.version) + self.assertEqual(0, request.partner_code) + self.assertEqual(0, request.namespace_id) + self.assertEqual("spyguy", request.uniquenick) + self.assertEqual("XXXXXXXXXXX", request.password) + + +if __name__ == "__main__": + unittest.main() diff --git a/src/frontends/tests/gamespy/web_services/racing_tests.py b/src/frontends/tests/gamespy/web_services/racing_tests.py new file mode 100644 index 000000000..e9fb9fec1 --- /dev/null +++ b/src/frontends/tests/gamespy/web_services/racing_tests.py @@ -0,0 +1,123 @@ +import unittest + + +GET_CONTEST_DATA = """ + + + + 0 + 0 + 0 + + + """ + +GET_FRIEND_RANKINGS = """ + + + + + 0 + 0 + 0 + 0 + + + +""" + +GET_REGIONAL_DATA = """ + + + + 0 + 0 + + + """ + +GET_TEN_ABOVE_RANKINGS = """ + + + + 0 + 0 + 0 + 0 + + + """ + +GET_TOP_RANKINGS = """ + + + + 0 + 0 + 0 + + + +""" + +SUBMIT_GHOST = """ + + + + 0 + 0 + 0 + 0 + XXXXXX + 0 + + + """ + +SUBMIT_SCORES = """ + + + + 0 + 0 + 0 + 0 + 0 + XXXXXX + + + """ + + +class RacingTests(unittest.TestCase): + def test_get_centest_data(self): + # request = GetContestDataRequest + pass diff --git a/src/frontends/tests/gamespy/web_services/sake_tests.py b/src/frontends/tests/gamespy/web_services/sake_tests.py new file mode 100644 index 000000000..5657e2601 --- /dev/null +++ b/src/frontends/tests/gamespy/web_services/sake_tests.py @@ -0,0 +1,470 @@ +import unittest + +import responses + +from frontends.gamespy.protocols.web_services.modules.sake.contracts.requests import CreateRecordRequest, DeleteRecordRequest, GetMyRecordsRequest, GetRandomRecordsRequest, GetRecordLimitRequest, GetSpecificRecordsRequest, RateRecordRequest, SearchForRecordsRequest, UpdateRecordRequest + + +CRYSIS_2_SAKE = """ + + + + 3300 + 8TTq4M + 0000000000000000000000__ + DEDICATEDSTATS + PROFILE =‵ + recordid + 0 + 1 + 0 + 2 + 0 + + DATA + recordid + + + + """ + +GET_RECORD_LIMIT = """ + + + + 0 + XXXXXX + xxxxxxxx_YYYYYYYYYY__ + nicks + + + """ + +RATE_RECORD = """ + + + + 0 + XXXXXX + xxxxxxxx_YYYYYYYYYY__ + test + 158 + 200 + + + """ + +GET_RANDOM_RECORDS = """ + + + + 0 + XXXXXX + xxxxxxxx_YYYYYYYYYY__ + levels + 1 + + recordid + score + + + + """ + +GET_SPECIFIC_RECORDS = """ + + + + 0 + XXXXXX + xxxxxxxx_YYYYYYYYYY__ + scores + + 1 + 2 + 4 + 5 + + + recordid + ownerid + score + + + + """ + +GET_MY_RECORDS = """ + + + + 0 + XXXXXX + xxxxxxxx_YYYYYYYYYY__ + test + + recordid + ownerid + MyByte + MyShort + MyInt + MyFloat + MyAsciiString + MyUnicodeString + MyBoolean + MyDateAndTime + MyBinaryData + MyFileID + num_ratings + average_rating + + + + """ + +SEARCH_FOR_RECORDS = """ + + + + 0 + XXXXXX + xxxxxxxx_YYYYYYYYYY__ + scores + + + 0 + 3 + 0 + + 0 + + score + recordid + + + + """ + +DELETE_RECORD = """ + + + + 0 + XXXXXX + xxxxxxxx_YYYYYYYYYY__ + test + 150 + + + """ + +UPDATE_RECORD = """ + + + + 0 + XXXXXX + xxxxxxxx_YYYYYYYYYY__ + test + 158 + + + MyByte + + + 123 + + + + + MyShort + + + 12345 + + + + + MyInt + + + 123456789 + + + + + MyFloat + + + 3.141593 + + + + + MyAsciiString + + + ascii + + + + + MyUnicodeString + + + unicode + + + + + MyBoolean + + + 1 + + + + + MyDateAndTime + + + 2020-05-21T11:13:41Z + + + + + MyBinaryData + + + EjRWq80= + + + + + + + """ + +CREATE_RECORD = """ + + + + 0 + XXXXXX + xxxxxxxx_YYYYYYYYYY__ + test + + + MyAsciiString + + + this is a record + + + + + + + """ + + +class SakeTests(unittest.TestCase): + @responses.activate + def test_get_record_limit(self): + request = GetRecordLimitRequest(GET_RECORD_LIMIT) + request.parse() + self.assertEqual(0, request.game_id) + self.assertEqual("XXXXXX", request.secret_key) + self.assertEqual("xxxxxxxx_YYYYYYYYYY__", request.login_ticket) + self.assertEqual("nicks", request.table_id) + + @responses.activate + def test_rate_record(self): + request = RateRecordRequest(RATE_RECORD) + request.parse() + self.assertEqual(0, request.game_id) + self.assertEqual("XXXXXX", request.secret_key) + self.assertEqual("xxxxxxxx_YYYYYYYYYY__", request.login_ticket) + self.assertEqual("test", request.table_id) + self.assertEqual("158", request.record_id) + self.assertEqual("200", request.rating) + + @responses.activate + def test_get_random_records(self): + request = GetRandomRecordsRequest(GET_RANDOM_RECORDS) + request.parse() + self.assertEqual(0, request.game_id) + self.assertEqual("XXXXXX", request.secret_key) + self.assertEqual("xxxxxxxx_YYYYYYYYYY__", request.login_ticket) + self.assertEqual("levels", request.table_id) + self.assertEqual(1, request.max) + self.assertEqual("recordid", request.fields[0][0]) + self.assertEqual("string", request.fields[0][1]) + self.assertEqual("score", request.fields[1][0]) + self.assertEqual("string", request.fields[1][1]) + + @responses.activate + def test_get_specific_record(self): + request = GetSpecificRecordsRequest(GET_SPECIFIC_RECORDS) + request.parse() + self.assertEqual(0, request.game_id) + self.assertEqual("XXXXXX", request.secret_key) + self.assertEqual("xxxxxxxx_YYYYYYYYYY__", request.login_ticket) + self.assertEqual("scores", request.table_id) + self.assertEqual("1", request.record_ids[0][0]) + self.assertEqual("int", request.record_ids[0][1]) + self.assertEqual("2", request.record_ids[1][0]) + self.assertEqual("int", request.record_ids[1][1]) + self.assertEqual("4", request.record_ids[2][0]) + self.assertEqual("int", request.record_ids[2][1]) + self.assertEqual("5", request.record_ids[3][0]) + self.assertEqual("int", request.record_ids[3][1]) + self.assertEqual("recordid", request.fields[0][0]) + self.assertEqual("string", request.fields[0][1]) + self.assertEqual("ownerid", request.fields[1][0]) + self.assertEqual("string", request.fields[1][1]) + self.assertEqual("score", request.fields[2][0]) + self.assertEqual("string", request.fields[2][1]) + + @responses.activate + def test_get_my_record(self): + request = GetMyRecordsRequest(GET_MY_RECORDS) + request.parse() + self.assertEqual(0, request.game_id) + self.assertEqual("XXXXXX", request.secret_key) + self.assertEqual("xxxxxxxx_YYYYYYYYYY__", request.login_ticket) + self.assertEqual("test", request.table_id) + + self.assertEqual("recordid", request.fields[0][0]) + self.assertEqual("string", request.fields[0][1]) + self.assertEqual("ownerid", request.fields[1][0]) + self.assertEqual("string", request.fields[1][1]) + self.assertEqual("MyByte", request.fields[2][0]) + self.assertEqual("string", request.fields[2][1]) + self.assertEqual("MyShort", request.fields[3][0]) + self.assertEqual("string", request.fields[3][1]) + self.assertEqual("MyInt", request.fields[4][0]) + self.assertEqual("string", request.fields[4][1]) + self.assertEqual("MyFloat", request.fields[5][0]) + self.assertEqual("string", request.fields[5][1]) + self.assertEqual("MyAsciiString", request.fields[6][0]) + self.assertEqual("string", request.fields[6][1]) + self.assertEqual("MyUnicodeString", request.fields[7][0]) + self.assertEqual("string", request.fields[7][1]) + self.assertEqual("MyBoolean", request.fields[8][0]) + self.assertEqual("string", request.fields[8][1]) + self.assertEqual("MyDateAndTime", request.fields[9][0]) + self.assertEqual("string", request.fields[9][1]) + self.assertEqual("MyBinaryData", request.fields[10][0]) + self.assertEqual("string", request.fields[10][1]) + self.assertEqual("MyFileID", request.fields[11][0]) + self.assertEqual("string", request.fields[11][1]) + self.assertEqual("num_ratings", request.fields[12][0]) + self.assertEqual("string", request.fields[12][1]) + self.assertEqual("average_rating", request.fields[13][0]) + self.assertEqual("string", request.fields[13][1]) + + @responses.activate + def test_search_for_records(self): + request = SearchForRecordsRequest(SEARCH_FOR_RECORDS) + request.parse() + self.assertEqual(0, request.game_id) + self.assertEqual("XXXXXX", request.secret_key) + self.assertEqual("xxxxxxxx_YYYYYYYYYY__", request.login_ticket) + self.assertEqual("scores", request.table_id) + self.assertEqual(None, request.filter) + self.assertEqual(None, request.sort) + self.assertEqual("0", request.offset) + self.assertEqual("0", request.surrounding) + self.assertEqual(None, request.owner_ids) + self.assertEqual("0", request.cache_flag) + # todo check how to implement this + # self.assertEqual("score", request.fields[0][0]) + # self.assertEqual("string", request.fields[0][1]) + # self.assertEqual("recordid", request.fields[1][0]) + # self.assertEqual("string", request.fields[1][1]) + + @responses.activate + def test_delete_record(self): + request = DeleteRecordRequest(DELETE_RECORD) + request.parse() + + self.assertEqual(0, request.game_id) + self.assertEqual("XXXXXX", request.secret_key) + self.assertEqual("xxxxxxxx_YYYYYYYYYY__", request.login_ticket) + self.assertEqual("test", request.table_id) + self.assertEqual(150, request.record_id) + + @responses.activate + def test_update_record(self): + request = UpdateRecordRequest(UPDATE_RECORD) + request.parse() + + self.assertEqual(0, request.game_id) + self.assertEqual("XXXXXX", request.secret_key) + self.assertEqual("xxxxxxxx_YYYYYYYYYY__", request.login_ticket) + self.assertEqual("test", request.table_id) + self.assertEqual("158", request.record_id) + + # TODO: Deserialization of RecordFields + self.assertEqual("MyByte", request.values[0]["name"]) + self.assertEqual( + "123", request.values[0]["value"]["byteValue"]['value']) + + @responses.activate + def test_create_record(self): + request = CreateRecordRequest(CREATE_RECORD) + request.parse() + self.assertEqual(0, request.game_id) + self.assertEqual("XXXXXX", request.secret_key) + self.assertEqual("xxxxxxxx_YYYYYYYYYY__", request.login_ticket) + self.assertEqual("test", request.table_id) + + self.assertEqual("MyAsciiString", request.values[0][0]) + self.assertEqual("asciiStringValue", request.values[0][1]) + self.assertEqual("this is a record", request.values[0][2]) + + +if __name__ == "__main__": + unittest.main() diff --git a/src/frontends/tests/test_runner.py b/src/frontends/tests/test_runner.py new file mode 100644 index 000000000..69784e53e --- /dev/null +++ b/src/frontends/tests/test_runner.py @@ -0,0 +1,9 @@ +if __name__ == "__main__": + import unittest + # Create a test suite + loader = unittest.TestLoader() + suite = loader.discover(start_dir='./', pattern='*tests.py') + + # Run the tests + runner = unittest.TextTestRunner() + runner.run(suite) diff --git a/src/requirements.txt b/src/requirements.txt new file mode 100644 index 000000000..5e3e5a2fc --- /dev/null +++ b/src/requirements.txt @@ -0,0 +1,13 @@ +pyfiglet == 1.0.2 +prettytable == 3.11.0 +psycopg2-binary == 2.9.10 +sqlalchemy == 2.0.36 +email_validator == 2.1.1 +requests == 2.32.3 +fastapi[standard] == 0.115.4 +xmltodict == 0.14.2 +responses == 0.25.3 +redis == 5.2.0 +websockets == 15.0.1 +schedule == 1.2.2 +watchdog == 6.0.0 \ No newline at end of file diff --git a/src/test/Anno1701.cs b/src/test/Anno1701.cs deleted file mode 100644 index f4f891ca0..000000000 --- a/src/test/Anno1701.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Core.Abstraction.Interface; -using Xunit; - -namespace UniSpy.Server.Test -{ - public class Anno1701 - { - [Fact] - public void Test20221106() - { - var qrClient = QueryReport.V2.Test.MockObject.CreateClient("79.209.224.29", 21701); - var sbClient = ServerBrowser.V2.Test.MockObject.CreateClient("79.209.224.29", 51104); - - var clients = new Dictionary(){ - {"qr",qrClient}, - {"sb",sbClient} - }; - - var requests = new List>() - { - new KeyValuePair("qr",new byte[]{0x09,0x00,0x00,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}), - new KeyValuePair("qr",new byte[]{0x03,0xB2,0x1A,0xF9,0x05,0x6C,0x6F,0x63,0x61,0x6C,0x69,0x70,0x30,0x00,0x31,0x39,0x32,0x2E,0x31,0x36,0x38,0x2E,0x30,0x2E,0x35,0x30,0x00,0x6C,0x6F,0x63,0x61,0x6C,0x69,0x70,0x31,0x00,0x31,0x39,0x32,0x2E,0x31,0x36,0x38,0x2E,0x31,0x32,0x32,0x2E,0x31,0x00,0x6C,0x6F,0x63,0x61,0x6C,0x70,0x6F,0x72,0x74,0x00,0x32,0x31,0x37,0x30,0x31,0x00,0x6E,0x61,0x74,0x6E,0x65,0x67,0x00,0x31,0x00,0x73,0x74,0x61,0x74,0x65,0x63,0x68,0x61,0x6E,0x67,0x65,0x64,0x00,0x33,0x00,0x67,0x61,0x6D,0x65,0x6E,0x61,0x6D,0x65,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x69,0x70,0x00,0x30,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x70,0x6F,0x72,0x74,0x00,0x30,0x00,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x00,0x74,0x65,0x73,0x74,0x00,0x67,0x61,0x6D,0x65,0x6D,0x6F,0x64,0x65,0x00,0x6F,0x70,0x65,0x6E,0x73,0x74,0x61,0x67,0x69,0x6E,0x67,0x00,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x31,0x00,0x6D,0x61,0x78,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x34,0x00,0x67,0x61,0x6D,0x65,0x76,0x65,0x72,0x00,0x32,0x31,0x39,0x30,0x33,0x00,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x00,0x52,0x61,0x6E,0x64,0x6F,0x6D,0x20,0x6D,0x61,0x70,0x00,0x67,0x61,0x6D,0x65,0x74,0x79,0x70,0x65,0x00,0x45,0x61,0x73,0x79,0x00,0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64,0x00,0x30,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x6F,0x70,0x74,0x69,0x6F,0x6E,0x73,0x00,0x33,0x36,0x39,0x31,0x37,0x34,0x34,0x36,0x38,0x00,0x6E,0x75,0x6D,0x61,0x69,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x31,0x00,0x6F,0x70,0x65,0x6E,0x73,0x6C,0x6F,0x74,0x73,0x00,0x34,0x00,0x67,0x61,0x6D,0x65,0x76,0x61,0x72,0x69,0x61,0x6E,0x74,0x00,0x50,0x76,0x50,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x77,0x69,0x6E,0x63,0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x00,0x30,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x75,0x73,0x65,0x72,0x63,0x6F,0x6E,0x74,0x65,0x6E,0x74,0x5F,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x00,0x00,0x00,0x00,0x01,0x70,0x6C,0x61,0x79,0x65,0x72,0x5F,0x00,0x70,0x69,0x6E,0x67,0x5F,0x00,0x70,0x69,0x6E,0x67,0x5F,0x00,0x00,0x73,0x70,0x6F,0x72,0x65,0x73,0x69,0x72,0x69,0x75,0x73,0x00,0x30,0x00,0x30,0x00,0x00,0x01,0x00}), - new KeyValuePair("sb",new byte[]{0x00,0x9A,0x00,0x01,0x03,0x8F,0x55,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x4C,0x3E,0x7C,0x42,0x54,0x26,0x56,0x26,0x67,0x72,0x6F,0x75,0x70,0x69,0x64,0x20,0x69,0x73,0x20,0x6E,0x75,0x6C,0x6C,0x00,0x5C,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x5C,0x67,0x61,0x6D,0x65,0x6D,0x6F,0x64,0x65,0x5C,0x67,0x61,0x6D,0x65,0x76,0x65,0x72,0x5C,0x67,0x61,0x6D,0x65,0x74,0x79,0x70,0x65,0x5C,0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64,0x5C,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x5C,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x5C,0x6E,0x75,0x6D,0x61,0x69,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x5C,0x6F,0x70,0x65,0x6E,0x73,0x6C,0x6F,0x74,0x73,0x5C,0x67,0x61,0x6D,0x65,0x76,0x61,0x72,0x69,0x61,0x6E,0x74,0x00,0x00,0x00,0x00,0x04}), - new KeyValuePair("sb",new byte[]{0x00,0x9A,0x00,0x01,0x03,0x8F,0x55,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x37,0x42,0x26,0x5C,0x24,0x44,0x4A,0x51,0x67,0x72,0x6F,0x75,0x70,0x69,0x64,0x20,0x69,0x73,0x20,0x6E,0x75,0x6C,0x6C,0x00,0x5C,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x5C,0x67,0x61,0x6D,0x65,0x6D,0x6F,0x64,0x65,0x5C,0x67,0x61,0x6D,0x65,0x76,0x65,0x72,0x5C,0x67,0x61,0x6D,0x65,0x74,0x79,0x70,0x65,0x5C,0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64,0x5C,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x5C,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x5C,0x6E,0x75,0x6D,0x61,0x69,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x5C,0x6F,0x70,0x65,0x6E,0x73,0x6C,0x6F,0x74,0x73,0x5C,0x67,0x61,0x6D,0x65,0x76,0x61,0x72,0x69,0x61,0x6E,0x74,0x00,0x00,0x00,0x00,0x04}), - new KeyValuePair("sb",new byte[] {0x00,0x9A,0x00,0x01,0x03,0x8F,0x55,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x75,0x4D,0x32,0x73,0x72,0x35,0x24,0x71,0x67,0x72,0x6F,0x75,0x70,0x69,0x64,0x20,0x69,0x73,0x20,0x6E,0x75,0x6C,0x6C,0x00,0x5C,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x5C,0x67,0x61,0x6D,0x65,0x6D,0x6F,0x64,0x65,0x5C,0x67,0x61,0x6D,0x65,0x76,0x65,0x72,0x5C,0x67,0x61,0x6D,0x65,0x74,0x79,0x70,0x65,0x5C,0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64,0x5C,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x5C,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x5C,0x6E,0x75,0x6D,0x61,0x69,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x5C,0x6F,0x70,0x65,0x6E,0x73,0x6C,0x6F,0x74,0x73,0x5C,0x67,0x61,0x6D,0x65,0x76,0x61,0x72,0x69,0x61,0x6E,0x74,0x00,0x00,0x00,0x00,0x04}), - // send message request - new KeyValuePair("sb",new byte[]{0x00,0x13,0x02,0x4F,0xD1,0xE0,0x1D,0x54,0xC5}), - // natneg message request - new KeyValuePair("sb",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x00,0x00,0x2C,0xFD}) - }; - // When - TestClasses.ServersSimulation(requests, clients); - - // Then - } - [Fact] - public void Test20221104() - { - var qrClient1 = QueryReport.V2.Test.MockObject.CreateClient("79.209.224.29", 21701); - var qrClient2 = QueryReport.V2.Test.MockObject.CreateClient("31.18.120.193", 21701); - var sbClient1 = ServerBrowser.V2.Test.MockObject.CreateClient("79.209.224.29", 45340); - var sbClient2 = ServerBrowser.V2.Test.MockObject.CreateClient("31.18.120.193", 50587); - var natClient1 = NatNegotiation.Test.MockObject.CreateClient("79.209.224.29", 123); - var natClient2 = NatNegotiation.Test.MockObject.CreateClient("31.18.120.193", 123); - - var clients = new Dictionary(){ - {"qr1",qrClient1}, - {"qr2",qrClient2}, - {"sb1",sbClient1}, - {"sb2",sbClient2}, - {"nat1",natClient1}, - {"nat2",natClient2} - }; - var requests = new List>() - { - new KeyValuePair("qr1",new byte[] {0x09,0x00,0x00,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x0}), - new KeyValuePair("qr1",new byte[] {0x03,0x98,0x92,0x25,0xA0,0x6C,0x6F,0x63,0x61,0x6C,0x69,0x70,0x30,0x00,0x31,0x39,0x32,0x2E,0x31,0x36,0x38,0x2E,0x30,0x2E,0x35,0x30,0x00,0x6C,0x6F,0x63,0x61,0x6C,0x69,0x70,0x31,0x00,0x31,0x39,0x32,0x2E,0x31,0x36,0x38,0x2E,0x31,0x32,0x32,0x2E,0x31,0x00,0x6C,0x6F,0x63,0x61,0x6C,0x70,0x6F,0x72,0x74,0x00,0x32,0x31,0x37,0x30,0x31,0x00,0x6E,0x61,0x74,0x6E,0x65,0x67,0x00,0x31,0x00,0x73,0x74,0x61,0x74,0x65,0x63,0x68,0x61,0x6E,0x67,0x65,0x64,0x00,0x33,0x00,0x67,0x61,0x6D,0x65,0x6E,0x61,0x6D,0x65,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x69,0x70,0x00,0x30,0x00,0x70,0x75,0x62,0x6C,0x69,0x63,0x70,0x6F,0x72,0x74,0x00,0x30,0x00,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x00,0x28,0x75,0x6E,0x6B,0x6E,0x6F,0x77,0x6E,0x20,0x67,0x61,0x6D,0x65,0x29,0x00,0x67,0x61,0x6D,0x65,0x6D,0x6F,0x64,0x65,0x00,0x6F,0x70,0x65,0x6E,0x73,0x74,0x61,0x67,0x69,0x6E,0x67,0x00,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x31,0x00,0x6D,0x61,0x78,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x34,0x00,0x67,0x61,0x6D,0x65,0x76,0x65,0x72,0x00,0x32,0x31,0x39,0x30,0x33,0x00,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x00,0x52,0x61,0x6E,0x64,0x6F,0x6D,0x20,0x6D,0x61,0x70,0x00,0x67,0x61,0x6D,0x65,0x74,0x79,0x70,0x65,0x00,0x45,0x61,0x73,0x79,0x00,0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64,0x00,0x30,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x6F,0x70,0x74,0x69,0x6F,0x6E,0x73,0x00,0x33,0x36,0x39,0x31,0x37,0x34,0x34,0x36,0x38,0x00,0x6E,0x75,0x6D,0x61,0x69,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x00,0x00,0x6F,0x70,0x65,0x6E,0x73,0x6C,0x6F,0x74,0x73,0x00,0x00,0x67,0x61,0x6D,0x65,0x76,0x61,0x72,0x69,0x61,0x6E,0x74,0x00,0x50,0x76,0x50,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x77,0x69,0x6E,0x63,0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x00,0x30,0x00,0x73,0x65,0x74,0x74,0x69,0x6E,0x67,0x73,0x5F,0x75,0x73,0x65,0x72,0x63,0x6F,0x6E,0x74,0x65,0x6E,0x74,0x5F,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x00,0x00,0x00,0x00,0x01,0x70,0x6C,0x61,0x79,0x65,0x72,0x5F,0x00,0x70,0x69,0x6E,0x67,0x5F,0x00,0x70,0x69,0x6E,0x67,0x5F,0x00,0x00,0x73,0x70,0x6F,0x72,0x65,0x73,0x69,0x72,0x69,0x75,0x73,0x00,0x30,0x00,0x30,0x00,0x00,0x01,0x00}), - new KeyValuePair("sb1",new byte[] {0x00,0x9A,0x00,0x01,0x03,0x8F,0x55,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00,0x52,0x63,0x58,0x3B,0x4D,0x28,0x7B,0x47,0x67,0x72,0x6F,0x75,0x70,0x69,0x64,0x20,0x69,0x73,0x20,0x6E,0x75,0x6C,0x6C,0x00,0x5C,0x68,0x6F,0x73,0x74,0x6E,0x61,0x6D,0x65,0x5C,0x67,0x61,0x6D,0x65,0x6D,0x6F,0x64,0x65,0x5C,0x67,0x61,0x6D,0x65,0x76,0x65,0x72,0x5C,0x67,0x61,0x6D,0x65,0x74,0x79,0x70,0x65,0x5C,0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64,0x5C,0x6D,0x61,0x70,0x6E,0x61,0x6D,0x65,0x5C,0x6E,0x75,0x6D,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x5C,0x6E,0x75,0x6D,0x61,0x69,0x70,0x6C,0x61,0x79,0x65,0x72,0x73,0x5C,0x6F,0x70,0x65,0x6E,0x73,0x6C,0x6F,0x74,0x73,0x5C,0x67,0x61,0x6D,0x65,0x76,0x61,0x72,0x69,0x61,0x6E,0x74,0x00,0x00,0x00,0x00,0x04}), - new KeyValuePair("qr2",new byte[] {0x07,0x98,0x92,0x25,0xA0,0x00,0x00,0x00,0x00}), - }; - - - TestClasses.ServersSimulation(requests, clients); - } - /// - /// Natneg fail - /// - [Fact] - public void Anno1701Test20201109() - { - // Given - var requests = new List>() - { - new KeyValuePair("client1",new byte[] {0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0x00,0x00,0x2D,0xA5,0x00,0x00,0x01,0xC0,0xA8,0x00,0x8D,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}), - new KeyValuePair("client2",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0x00,0x00,0x2D,0xA5,0x02,0x00,0x01,0xC0,0xA8,0x00,0x8D,0x54,0xC5,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}), - new KeyValuePair("client2",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0x00,0x00,0x2D,0xA5,0x03,0x00,0x01,0xC0,0xA8,0x00,0x8D,0x54,0xC5,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}), - new KeyValuePair("client2",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0x00,0x00,0x2D,0xA5,0x01,0x00,0x01,0xC0,0xA8,0x00,0x8D,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}), - new KeyValuePair("client3",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0x00,0x00,0x2D,0xA5,0x00,0x01,0x01,0xC0,0xA8,0x00,0x32,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}), - new KeyValuePair("client4",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0x00,0x00,0x2D,0xA5,0x01,0x01,0x01,0xC0,0xA8,0x00,0x32,0x00,0x00,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}), - new KeyValuePair("client4",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0x00,0x00,0x2D,0xA5,0x02,0x01,0x01,0xC0,0xA8,0x00,0x32,0x54,0xC5,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}), - new KeyValuePair("client4",new byte[]{0xFD,0xFC,0x1E,0x66,0x6A,0xB2,0x03,0x00,0x00,0x00,0x2D,0xA5,0x03,0x01,0x01,0xC0,0xA8,0x00,0x32,0x54,0xC5,0x61,0x6E,0x6E,0x6F,0x31,0x37,0x30,0x31,0x00}) - }; - var client1 = NatNegotiation.Test.MockObject.CreateClient("79.209.224.29", 21701); - var client2 = NatNegotiation.Test.MockObject.CreateClient("79.209.224.29", 51298); - var client3 = NatNegotiation.Test.MockObject.CreateClient("79.209.224.29", 1024); - var client4 = NatNegotiation.Test.MockObject.CreateClient("79.209.224.29", 41218); - - - var clients = new Dictionary() - { - {"client1",client1}, - {"client2",client2}, - {"client3",client3}, - {"client4",client4}, - }; - TestClasses.ServersSimulation(requests, clients); - // because the process is running in background we need to wait it finish, so we can debug - // Thread.Sleep(10000); - } - } -} \ No newline at end of file diff --git a/src/test/TestClasses.cs b/src/test/TestClasses.cs deleted file mode 100644 index bfb19d818..000000000 --- a/src/test/TestClasses.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Collections.Generic; -using UniSpy.Server.Core.Abstraction.Interface; - -namespace UniSpy.Server.Test -{ - public static class TestClasses - { - public static void ServersSimulation(List> requests, Dictionary clients) - { - foreach (var req in requests) - { - ((ITestClient)clients[req.Key]).TestReceived(req.Value); - } - } - } -} \ No newline at end of file diff --git a/src/test/UniSpy.Server.Test.csproj b/src/test/UniSpy.Server.Test.csproj deleted file mode 100644 index 32d422d28..000000000 --- a/src/test/UniSpy.Server.Test.csproj +++ /dev/null @@ -1,38 +0,0 @@ - - - - net6.0 - false - ..\..\common\Icon\UniSpy_Logo.ico - - - AnyCPU - ..\..\build\$(Configuration) - - - ..\..\build\$(Configuration) - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/tests/__init__.py b/src/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/tests/redis_test.py b/src/tests/redis_test.py new file mode 100644 index 000000000..4fb912d7a --- /dev/null +++ b/src/tests/redis_test.py @@ -0,0 +1,32 @@ + +# import redis +# from frontends.gamespy.library.configs import CONFIG + + +# # SESSION = redis.Redis.from_url(CONFIG.redis.url) + +# client = redis.from_url(CONFIG.redis.url) +# pubsub = client.pubsub() +# pubsub.subscribe("test") + +# for message in pubsub.listen(): +# if message['type'] == 'message': +# print(f"Received: {message['data'].decode('utf-8')}") + +# client.set("hello", "hi") +# data = client.get("hello") +# pass +# import socket + +# SERVER_IP = "127.0.0.1" # change to target IP if needed +# SERVER_PORT = 27901 +# MESSAGE = b"hello" + +# sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + +# try: +# for _ in range(10): +# sock.sendto(MESSAGE, (SERVER_IP, SERVER_PORT)) +# print(f"Sent {MESSAGE!r} to {SERVER_IP}:{SERVER_PORT}") +# finally: +# sock.close() \ No newline at end of file