diff --git a/.github/workflows/network-pressure.yml b/.github/workflows/network-pressure.yml deleted file mode 100644 index def9761df..000000000 --- a/.github/workflows/network-pressure.yml +++ /dev/null @@ -1,61 +0,0 @@ -name: Network Pressure Test - -on: - pull_request: - branches: - - main - -jobs: - network-pressure-10-clients-ubuntu-rel: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Setup .NET Core - uses: actions/setup-dotnet@v1 - with: - dotnet-version: '6.0.x' - - - name: Restore NuGet packages - run: | - dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" - dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj - - - name: Run tests - run: cd Tests/KcpTests/KcpPerformanceTest ; dotnet run --configuration Release -- --packet-size 3500 --packet-repeat-time 5000 --packet-interval 50 --github-actions --clients-count 10 - - - name: Archive logs - uses: actions/upload-artifact@v2 - with: - name: Report & logs (ubuntu-rel-pressure-x10) - ${{ github.sha }} - path: Tests/KcpTests/KcpPerformanceTest/logs - retention-days: 21 - - network-pressure-20-clients-ubuntu-rel: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Setup .NET Core - uses: actions/setup-dotnet@v1 - with: - dotnet-version: '6.0.x' - - - name: Restore NuGet packages - run: | - dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" - dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj - - - name: Run tests - run: cd Tests/KcpTests/KcpPerformanceTest ; dotnet run --configuration Release -- --packet-size 3500 --packet-repeat-time 5000 --packet-interval 50 --github-actions --clients-count 20 - - - name: Archive logs - uses: actions/upload-artifact@v2 - with: - name: Report & logs (ubuntu-rel-pressure-x20) - ${{ github.sha }} - path: Tests/KcpTests/KcpPerformanceTest/logs - retention-days: 21 \ No newline at end of file diff --git a/.github/workflows/network-test.yml b/.github/workflows/network-test.yml deleted file mode 100644 index c1c6fbde9..000000000 --- a/.github/workflows/network-test.yml +++ /dev/null @@ -1,118 +0,0 @@ -# Generated By ChatGPT -name: Network Test - -on: - pull_request: - branches: - - main - -jobs: - network-proxy-benchmark-windows-rel: - runs-on: windows-latest - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Setup .NET Core - uses: actions/setup-dotnet@v1 - with: - dotnet-version: '6.0.x' - - - name: Restore NuGet packages - run: | - dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" - dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj - - - name: Run tests - run: cd Tests/KcpTests/KcpPerformanceTest ; dotnet run --configuration Release -- --packet-size 3500 --packet-repeat-time 5000 --packet-interval 40 --github-actions --clients-count 2 --packet-delay-log - - - name: Archive logs - uses: actions/upload-artifact@v2 - with: - name: Report & logs (proxy-windows-rel) - ${{ github.sha }} - path: Tests/KcpTests/KcpPerformanceTest/logs - retention-days: 21 - - network-proxy-benchmark-ubuntu-rel: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Setup .NET Core - uses: actions/setup-dotnet@v1 - with: - dotnet-version: '6.0.x' - - - name: Restore NuGet packages - run: | - dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" - dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj - - - name: Run tests - run: cd Tests/KcpTests/KcpPerformanceTest ; dotnet run --configuration Release -- --packet-size 3500 --packet-repeat-time 5000 --packet-interval 40 --github-actions --clients-count 2 --packet-delay-log - - - name: Archive logs - uses: actions/upload-artifact@v2 - with: - name: Report & logs (proxy-ubuntu-rel) - ${{ github.sha }} - path: Tests/KcpTests/KcpPerformanceTest/logs - retention-days: 21 - - network-directly-connect-benchmark-windows-rel: - runs-on: windows-latest - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Setup .NET Core - uses: actions/setup-dotnet@v1 - with: - dotnet-version: '6.0.x' - - - name: Restore NuGet packages - run: | - dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" - dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj - - - name: Run tests - # Generated by ChatGPT - run: cd Tests/KcpTests/KcpPerformanceTest ; dotnet run --configuration Release --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bCONNECT_SERVERONLY -- --packet-size 3500 --packet-repeat-time 5000 --packet-interval 40 --github-actions --clients-count 2 --packet-delay-log - - - name: Archive logs - uses: actions/upload-artifact@v2 - with: - name: Report & logs (directly-windows-rel) - ${{ github.sha }} - path: Tests/KcpTests/KcpPerformanceTest/logs - retention-days: 21 - - network-directly-connect-benchmark-ubuntu-rel: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Setup .NET Core - uses: actions/setup-dotnet@v1 - with: - dotnet-version: '6.0.x' - - - name: Restore NuGet packages - run: | - dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" - dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj - - - name: Run tests - # Generated by ChatGPT - run: cd Tests/KcpTests/KcpPerformanceTest ; dotnet run --configuration Release --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bCONNECT_SERVERONLY -- --packet-size 3500 --packet-repeat-time 5000 --packet-interval 40 --github-actions --clients-count 2 --packet-delay-log - - - name: Archive logs - uses: actions/upload-artifact@v2 - with: - name: Report & logs (directly-ubuntu-rel) - ${{ github.sha }} - path: Tests/KcpTests/KcpPerformanceTest/logs - retention-days: 21 diff --git a/.github/workflows/network-tests.yml b/.github/workflows/network-tests.yml new file mode 100644 index 000000000..352c46c02 --- /dev/null +++ b/.github/workflows/network-tests.yml @@ -0,0 +1,1315 @@ +# Generated By ChatGPT +name: Network Test + +on: + pull_request: + branches: + - main + - development + push: + branches: + - main + - development + - byte-check-mode + +jobs: + + # Quick Check + + net-debug-direct-ubuntu: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Debug + --property:DefineConstants=TRACE%3bDEBUG%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bCONNECT_SERVERONLY -- + --packet-size 3500 + --packet-repeat-time 200 + --packet-interval 40 + --github-actions + --clients-count 1 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (directly-ubuntu-debug) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-debug-direct-bytecheck-ubuntu: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Debug + --property:DefineConstants=TRACE%3bDEBUG%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bCONNECT_SERVERONLYP%3bBYTE_CHECK_MODE -- + --packet-size 3500 + --packet-repeat-time 200 + --packet-interval 40 + --github-actions + --clients-count 1 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (direct-ubuntu-debug, BYTE_CHECK_MODE) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-debug-direct-corrupt-bytecheck-ubuntu: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Debug + --property:DefineConstants=TRACE%3bDEBUG%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bBYTE_CHECK_MODE%3bCONNECT_SERVERONLY%3bCORRUPT_PACKET -- + --packet-size 3500 + --packet-repeat-time 200 + --packet-interval 40 + --github-actions + --clients-count 1 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (direct-ubuntu-debug, BYTE_CHECK_MODE, CORRUPT_PACKET) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-debug-proxy-ubuntu: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Debug + --property:DefineConstants=TRACE%3bDEBUG%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b -- + --packet-size 3500 + --packet-repeat-time 200 + --packet-interval 40 + --github-actions + --clients-count 1 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (proxy-ubuntu-debug) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-debug-proxy-bytecheck-ubuntu: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Debug + --property:DefineConstants=TRACE%3bDEBUG%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bBYTE_CHECK_MODE -- + --packet-size 3500 + --packet-repeat-time 200 + --packet-interval 40 + --github-actions + --clients-count 1 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (proxy-ubuntu-debug, BYTE_CHECK_MODE) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-debug-proxy-corrupt-bytecheck-ubuntu: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Debug + --property:DefineConstants=TRACE%3bDEBUG%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bBYTE_CHECK_MODE%3bCORRUPT_PACKET -- + --packet-size 3500 + --packet-repeat-time 200 + --packet-interval 40 + --github-actions + --clients-count 1 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (proxy-ubuntu-debug, BYTE_CHECK_MODE, CORRUPT_PACKET) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + # Basic (rel) + + net-rel-direct-ubuntu: + runs-on: ubuntu-latest + + needs: + - net-debug-direct-ubuntu + - net-debug-direct-bytecheck-ubuntu + - net-debug-proxy-ubuntu + - net-debug-proxy-bytecheck-ubuntu + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bCONNECT_SERVERONLY -- + --packet-size 3500 + --packet-repeat-time 5000 + --packet-interval 40 + --github-actions + --clients-count 2 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (directly-ubuntu-rel) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-rel-direct-windows: + runs-on: windows-latest + + needs: + - net-debug-direct-ubuntu + - net-debug-direct-bytecheck-ubuntu + - net-debug-proxy-ubuntu + - net-debug-proxy-bytecheck-ubuntu + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bCONNECT_SERVERONLY -- + --packet-size 3500 + --packet-repeat-time 5000 + --packet-interval 40 + --github-actions + --clients-count 2 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (directly-windows-rel) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-rel-proxy-ubuntu: + runs-on: ubuntu-latest + + needs: + - net-debug-direct-ubuntu + - net-debug-direct-bytecheck-ubuntu + - net-debug-proxy-ubuntu + - net-debug-proxy-bytecheck-ubuntu + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b -- + --packet-size 3500 + --packet-repeat-time 5000 + --packet-interval 40 + --github-actions + --clients-count 2 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (proxy-ubuntu-rel) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-rel-proxy-windows: + runs-on: windows-latest + + needs: + - net-debug-direct-ubuntu + - net-debug-direct-bytecheck-ubuntu + - net-debug-proxy-ubuntu + - net-debug-proxy-bytecheck-ubuntu + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b -- + --packet-size 3500 + --packet-repeat-time 5000 + --packet-interval 40 + --github-actions + --clients-count 2 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (proxy-windows-rel) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + # Byte Check Mode (rel) + + net-rel-direct-bytecheck-ubuntu: + runs-on: ubuntu-latest + + needs: + - net-debug-direct-ubuntu + - net-debug-direct-bytecheck-ubuntu + - net-debug-proxy-ubuntu + - net-debug-proxy-bytecheck-ubuntu + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bCONNECT_SERVERONLY%3bBYTE_CHECK_MODE -- + --packet-size 3500 + --packet-repeat-time 5000 + --packet-interval 40 + --github-actions + --clients-count 2 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (directly-ubuntu-rel, BYTE_CHECK_MODE) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-rel-direct-bytecheck-windows: + runs-on: windows-latest + + needs: + - net-debug-direct-ubuntu + - net-debug-direct-bytecheck-ubuntu + - net-debug-proxy-ubuntu + - net-debug-proxy-bytecheck-ubuntu + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bCONNECT_SERVERONLY%3bBYTE_CHECK_MODE -- + --packet-size 3500 + --packet-repeat-time 5000 + --packet-interval 40 + --github-actions + --clients-count 2 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (directly-windows-rel, BYTE_CHECK_MODE) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-rel-proxy-bytecheck-ubuntu: + runs-on: ubuntu-latest + + needs: + - net-debug-direct-ubuntu + - net-debug-direct-bytecheck-ubuntu + - net-debug-proxy-ubuntu + - net-debug-proxy-bytecheck-ubuntu + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bBYTE_CHECK_MODE -- + --packet-size 3500 + --packet-repeat-time 5000 + --packet-interval 40 + --github-actions + --clients-count 2 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (proxy-ubuntu-rel, BYTE_CHECK_MODE) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-rel-proxy-bytecheck-windows: + runs-on: windows-latest + + needs: + - net-debug-direct-ubuntu + - net-debug-direct-bytecheck-ubuntu + - net-debug-proxy-ubuntu + - net-debug-proxy-bytecheck-ubuntu + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bBYTE_CHECK_MODE -- + --packet-size 3500 + --packet-repeat-time 5000 + --packet-interval 40 + --github-actions + --clients-count 2 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (proxy-windows-rel, BYTE_CHECK_MODE) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-rel-direct-corrupt-bytecheck-ubuntu: + runs-on: ubuntu-latest + + needs: + - net-debug-direct-ubuntu + - net-debug-direct-bytecheck-ubuntu + - net-debug-direct-corrupt-bytecheck-ubuntu + - net-debug-proxy-ubuntu + - net-debug-proxy-bytecheck-ubuntu + - net-debug-proxy-corrupt-bytecheck-ubuntu + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bCONNECT_SERVERONLY%3bBYTE_CHECK_MODE%3bCORRUPT_PACKET -- + --packet-size 3500 + --packet-repeat-time 5000 + --packet-interval 40 + --github-actions + --clients-count 2 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (directly-ubuntu-rel, BYTE_CHECK_MODE, CORRUPT_PACKET) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-rel-direct-corrupt-bytecheck-windows: + runs-on: windows-latest + + needs: + - net-debug-direct-ubuntu + - net-debug-direct-bytecheck-ubuntu + - net-debug-direct-corrupt-bytecheck-ubuntu + - net-debug-proxy-ubuntu + - net-debug-proxy-bytecheck-ubuntu + - net-debug-proxy-corrupt-bytecheck-ubuntu + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bCONNECT_SERVERONLY%3bBYTE_CHECK_MODE%3bCORRUPT_PACKET -- + --packet-size 3500 + --packet-repeat-time 5000 + --packet-interval 40 + --github-actions + --clients-count 2 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (directly-windows-rel, BYTE_CHECK_MODE, CORRUPT_PACKET) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-rel-proxy-corrupt-bytecheck-ubuntu: + runs-on: ubuntu-latest + + needs: + - net-debug-direct-ubuntu + - net-debug-direct-bytecheck-ubuntu + - net-debug-direct-corrupt-bytecheck-ubuntu + - net-debug-proxy-ubuntu + - net-debug-proxy-bytecheck-ubuntu + - net-debug-proxy-corrupt-bytecheck-ubuntu + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bBYTE_CHECK_MODE%3bCORRUPT_PACKET -- + --packet-size 3500 + --packet-repeat-time 5000 + --packet-interval 40 + --github-actions + --clients-count 2 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (proxy-ubuntu-rel, BYTE_CHECK_MODE, CORRUPT_PACKET) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-rel-proxy-corrupt-bytecheck-windows: + runs-on: windows-latest + + needs: + - net-debug-direct-ubuntu + - net-debug-direct-bytecheck-ubuntu + - net-debug-direct-corrupt-bytecheck-ubuntu + - net-debug-proxy-ubuntu + - net-debug-proxy-bytecheck-ubuntu + - net-debug-proxy-corrupt-bytecheck-ubuntu + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bBYTE_CHECK_MODE%3bCORRUPT_PACKET -- + --packet-size 3500 + --packet-repeat-time 5000 + --packet-interval 40 + --github-actions + --clients-count 2 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (proxy-windows-rel, BYTE_CHECK_MODE, CORRUPT_PACKET) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + # Byte Check Mode Extended Test + + net-rel-direct-bigdata-bytecheck-ubuntu: + runs-on: ubuntu-latest + + needs: + - net-rel-direct-bytecheck-ubuntu + - net-rel-direct-bytecheck-windows + - net-rel-proxy-bytecheck-ubuntu + - net-rel-proxy-bytecheck-windows + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bCONNECT_SERVERONLY%3bBYTE_CHECK_MODE -- + --packet-size 30000 + --packet-repeat-time 5000 + --packet-interval 40 + --github-actions + --clients-count 2 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (directly-ubuntu-rel, BYTE_CHECK_MODE, big packet) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-rel-direct-bigdata-bytecheck-windows: + runs-on: windows-latest + + needs: + - net-rel-direct-bytecheck-ubuntu + - net-rel-direct-bytecheck-windows + - net-rel-proxy-bytecheck-ubuntu + - net-rel-proxy-bytecheck-windows + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bCONNECT_SERVERONLY%3bBYTE_CHECK_MODE -- + --packet-size 30000 + --packet-repeat-time 5000 + --packet-interval 40 + --github-actions + --clients-count 2 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (directly-windows-rel, BYTE_CHECK_MODE, big packet) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-rel-proxy-bigdata-bytecheck-ubuntu: + runs-on: ubuntu-latest + + needs: + - net-rel-direct-bytecheck-ubuntu + - net-rel-direct-bytecheck-windows + - net-rel-proxy-bytecheck-ubuntu + - net-rel-proxy-bytecheck-windows + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bBYTE_CHECK_MODE -- + --packet-size 30000 + --packet-repeat-time 5000 + --packet-interval 40 + --github-actions + --clients-count 2 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (proxy-ubuntu-rel, BYTE_CHECK_MODE, big packet) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-rel-proxy-bigdata-bytecheck-windows: + runs-on: windows-latest + + needs: + - net-rel-direct-bytecheck-ubuntu + - net-rel-direct-bytecheck-windows + - net-rel-proxy-bytecheck-ubuntu + - net-rel-proxy-bytecheck-windows + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bBYTE_CHECK_MODE -- + --packet-size 30000 + --packet-repeat-time 5000 + --packet-interval 40 + --github-actions + --clients-count 2 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (proxy-windows-rel, BYTE_CHECK_MODE, big packet) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-rel-direct-corrupt-bigdata-bytecheck-ubuntu: + runs-on: ubuntu-latest + + needs: + - net-rel-direct-bytecheck-ubuntu + - net-rel-direct-bytecheck-windows + - net-rel-proxy-bytecheck-ubuntu + - net-rel-proxy-bytecheck-windows + - net-rel-direct-corrupt-bytecheck-ubuntu + - net-rel-direct-corrupt-bytecheck-windows + - net-rel-proxy-corrupt-bytecheck-ubuntu + - net-rel-proxy-corrupt-bytecheck-windows + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bCONNECT_SERVERONLY%3bBYTE_CHECK_MODE%3bCORRUPT_PACKET -- + --packet-size 3500 + --packet-repeat-time 5000 + --packet-interval 40 + --github-actions + --clients-count 2 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (directly-ubuntu-rel, BYTE_CHECK_MODE, CORRUPT_PACKET, big packet) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-rel-direct-corrupt-bigdata-bytecheck-windows: + runs-on: windows-latest + + needs: + - net-rel-direct-bytecheck-ubuntu + - net-rel-direct-bytecheck-windows + - net-rel-proxy-bytecheck-ubuntu + - net-rel-proxy-bytecheck-windows + - net-rel-direct-corrupt-bytecheck-ubuntu + - net-rel-direct-corrupt-bytecheck-windows + - net-rel-proxy-corrupt-bytecheck-ubuntu + - net-rel-proxy-corrupt-bytecheck-windows + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bCONNECT_SERVERONLY%3bBYTE_CHECK_MODE%3bCORRUPT_PACKET -- + --packet-size 3500 + --packet-repeat-time 5000 + --packet-interval 40 + --github-actions + --clients-count 2 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (directly-windows-rel, BYTE_CHECK_MODE, CORRUPT_PACKET, big packet) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-rel-proxy-corrupt-bigdata-bytecheck-ubuntu: + runs-on: ubuntu-latest + + needs: + - net-rel-direct-bytecheck-ubuntu + - net-rel-direct-bytecheck-windows + - net-rel-proxy-bytecheck-ubuntu + - net-rel-proxy-bytecheck-windows + - net-rel-direct-corrupt-bytecheck-ubuntu + - net-rel-direct-corrupt-bytecheck-windows + - net-rel-proxy-corrupt-bytecheck-ubuntu + - net-rel-proxy-corrupt-bytecheck-windows + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bBYTE_CHECK_MODE%3bCORRUPT_PACKET -- + --packet-size 3500 + --packet-repeat-time 5000 + --packet-interval 40 + --github-actions + --clients-count 2 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (proxy-ubuntu-rel, BYTE_CHECK_MODE, CORRUPT_PACKET, big packet) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-rel-proxy-corrupt-bigdata-bytecheck-windows: + runs-on: windows-latest + + needs: + - net-rel-direct-bytecheck-ubuntu + - net-rel-direct-bytecheck-windows + - net-rel-proxy-bytecheck-ubuntu + - net-rel-proxy-bytecheck-windows + - net-rel-direct-corrupt-bytecheck-ubuntu + - net-rel-direct-corrupt-bytecheck-windows + - net-rel-proxy-corrupt-bytecheck-ubuntu + - net-rel-proxy-corrupt-bytecheck-windows + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bBYTE_CHECK_MODE%3bCORRUPT_PACKET -- + --packet-size 3500 + --packet-repeat-time 5000 + --packet-interval 40 + --github-actions + --clients-count 2 + --packet-delay-log + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (proxy-windows-rel, BYTE_CHECK_MODE, CORRUPT_PACKET, big packet) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + # Pressure Test + + net-rel-pressure-10-clients-ubuntu: + runs-on: ubuntu-latest + + needs: + - net-rel-direct-ubuntu + - net-rel-direct-windows + - net-rel-proxy-ubuntu + - net-rel-proxy-windows + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b -- + --packet-size 3500 + --packet-repeat-time 5000 + --packet-interval 50 + --github-actions + --clients-count 10 + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (ubuntu-rel-pressure-x10) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-rel-pressure-20-clients-ubuntu: + runs-on: ubuntu-latest + + needs: + - net-rel-direct-ubuntu + - net-rel-direct-windows + - net-rel-proxy-ubuntu + - net-rel-proxy-windows + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b -- + --packet-size 3500 + --packet-repeat-time 5000 + --packet-interval 50 + --github-actions + --clients-count 10 + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (ubuntu-rel-pressure-x20) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-rel-pressure-bytecheck-10-clients-ubuntu: + runs-on: ubuntu-latest + + needs: + - net-rel-direct-ubuntu + - net-rel-direct-windows + - net-rel-proxy-ubuntu + - net-rel-proxy-windows + - net-rel-direct-bytecheck-ubuntu + - net-rel-direct-bytecheck-windows + - net-rel-proxy-bytecheck-ubuntu + - net-rel-proxy-bytecheck-windows + - net-rel-direct-bigdata-bytecheck-ubuntu + - net-rel-direct-bigdata-bytecheck-windows + - net-rel-proxy-bigdata-bytecheck-ubuntu + - net-rel-proxy-bigdata-bytecheck-windows + - net-rel-direct-corrupt-bigdata-bytecheck-ubuntu + - net-rel-direct-corrupt-bigdata-bytecheck-windows + - net-rel-proxy-corrupt-bigdata-bytecheck-ubuntu + - net-rel-proxy-corrupt-bigdata-bytecheck-windows + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bBYTE_CHECK_MODE -- + --packet-size 3500 + --packet-repeat-time 5000 + --packet-interval 50 + --github-actions + --clients-count 10 + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (ubuntu-rel-pressure-x10, BYTE_CHECK_MODE) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 + + net-rel-pressure-bytecheck-20-clients-ubuntu: + runs-on: ubuntu-latest + + needs: + - net-rel-direct-bigdata-bytecheck-ubuntu + - net-rel-direct-bigdata-bytecheck-windows + - net-rel-proxy-bigdata-bytecheck-ubuntu + - net-rel-proxy-bigdata-bytecheck-windows + - net-rel-direct-corrupt-bigdata-bytecheck-ubuntu + - net-rel-direct-corrupt-bigdata-bytecheck-windows + - net-rel-proxy-corrupt-bigdata-bytecheck-ubuntu + - net-rel-proxy-corrupt-bigdata-bytecheck-windows + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' + + - name: Restore NuGet packages + run: | + dotnet nuget add source https://apiint.nugettest.org/v3/index.json -n "nuget.org (Integration)" + dotnet restore Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj + + - name: Run tests + run: > + cd Tests/KcpTests/KcpPerformanceTest ; + dotnet run --configuration Release + --property:DefineConstants=TRACE%3bRELEASE%3bNET%3bNET6_0%3bNETCOREAPP%3bMIHOMO_KCP%3bKCP_INNER_LOG%3bKCP_PERFORMANCE_TEST%3b%3bBYTE_CHECK_MODE -- + --packet-size 3500 + --packet-repeat-time 5000 + --packet-interval 50 + --github-actions + --clients-count 10 + + - name: Archive logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: Report & logs (ubuntu-rel-pressure-x20, BYTE_CHECK_MODE) + path: Tests/KcpTests/KcpPerformanceTest/logs + retention-days: 21 \ No newline at end of file diff --git a/HandlerGenerator/HandlerGenerator.csproj b/HandlerGenerator/HandlerGenerator.csproj index dbc98d755..ffe6080e5 100644 --- a/HandlerGenerator/HandlerGenerator.csproj +++ b/HandlerGenerator/HandlerGenerator.csproj @@ -14,7 +14,7 @@ - + diff --git a/HandlerGenerator/ProtoshiftEx/CompiledEnumStringPoolManager.cs b/HandlerGenerator/ProtoshiftEx/CompiledEnumStringPoolManager.cs index 8b73f9505..c5ad13a55 100644 --- a/HandlerGenerator/ProtoshiftEx/CompiledEnumStringPoolManager.cs +++ b/HandlerGenerator/ProtoshiftEx/CompiledEnumStringPoolManager.cs @@ -1,4 +1,5 @@ using System.Collections.ObjectModel; +using System.Collections.Concurrent; using System.Diagnostics; using YYHEggEgg.Logger; @@ -91,7 +92,7 @@ public CompiledEnumStringPoolManager(string[] compiled_enumproto_lines, public class CompiledEnumsStringPoolCollection { - private Dictionary collection = new(); + private ConcurrentDictionary collection = new(); /// /// Query a string pool with compiled enum name. @@ -113,7 +114,7 @@ public void AddCodeFile(string code_fullPath) var enumCodes = fullTree.GetPathsByType(CodeTreeQueryType.Enum); foreach (var enumCode in enumCodes) { - collection.Add(enumCode.FullPath, + collection.TryAdd(enumCode.FullPath, new(lines, enumCode.StartLine, enumCode.EndLine)); } } diff --git a/KCP/Kcp/IKcpInterface.cs b/KCP/Kcp/IKcpInterface.cs index 7a15623e6..334643d20 100644 --- a/KCP/Kcp/IKcpInterface.cs +++ b/KCP/Kcp/IKcpInterface.cs @@ -13,8 +13,9 @@ public interface IKcpCallback /// /// kcp 发送方向输出 /// - /// kcp 交出发送缓冲区控制权,缓冲区来自 + /// kcp 交出发送缓冲区控制权,缓冲区来自 /// 数据的有效长度 + /// 是否为 KCP 协议发出的包 /// 不需要返回值 /// 通过增加 avalidLength 能够在协议栈中有效的减少数据拷贝 void Output(BufferOwner buffer, int avalidLength, bool isKcpPacket = true); @@ -76,6 +77,9 @@ public interface IKcpSetting /// 如果没有必要请不要修改。注意确保接收窗口必须大于最大分片数。 /// int WndSize(int sndwnd = 32, int rcvwnd = 128); +#if BYTE_CHECK_MODE + int SetByteCheck(uint byteCheckMode, bool corrupt); +#endif } public interface IKcpUpdate diff --git a/KCP/Kcp/IKcpSegment.cs b/KCP/Kcp/IKcpSegment.cs index caefd4e24..5ba265109 100644 --- a/KCP/Kcp/IKcpSegment.cs +++ b/KCP/Kcp/IKcpSegment.cs @@ -51,6 +51,16 @@ public interface IKcpHeader /// 数据内容长度 /// uint len { get; } +#if BYTE_CHECK_MODE + /// + /// 用于对包 data 进行完整性校验的数据。可能为 CRC32 或 xxHash 结果。 + /// + uint byteCheckCode { get; } + /// + /// 用以供外部写入 后手动更新 byteCheckCode. + /// + void ComputeByteCheckCodeFromData(); +#endif } public interface IKcpSegment : IKcpHeader { @@ -70,6 +80,12 @@ public interface IKcpSegment : IKcpHeader /// 重传次数 /// uint xmit { get; set; } +#if BYTE_CHECK_MODE + /// + /// 应使用的 checksum 算法。1 使用 CRC32;2 使用 xxHash. + /// + uint byteCheckMode { get; set; } +#endif /// /// 数据内容 diff --git a/KCP/Kcp/Kcp.cs b/KCP/Kcp/Kcp.cs index 3c527559e..67d6d6d96 100644 --- a/KCP/Kcp/Kcp.cs +++ b/KCP/Kcp/Kcp.cs @@ -13,12 +13,10 @@ public class Kcp : KcpCore /// from the same connection. /// /// -#if MIHOMO_KCP /// /// miHoMo KCP modify: +IUINT32 token, + /// Change line(s) in file compare: ikcp.h, -346 +347; ikcp.c, -234 +234 /// -#endif /// /// 可租用内存的回调 #if !MIHOMO_KCP @@ -301,14 +299,7 @@ int UncheckRecv(Span buffer) #endregion -#if BUGFIX_TRIAL_20230610_001 - lock (rcv_bufLock) - { -#endif - Move_Rcv_buf_2_Rcv_queue(); -#if BUGFIX_TRIAL_20230610_001 - } -#endif + Move_Rcv_buf_2_Rcv_queue(); #region fast recover /// fast recover @@ -379,14 +370,7 @@ int UncheckRecv(IBufferWriter writer) #endregion -#if BUGFIX_TRIAL_20230610_001 - lock (rcv_bufLock) - { -#endif - Move_Rcv_buf_2_Rcv_queue(); -#if BUGFIX_TRIAL_20230610_001 - } -#endif + Move_Rcv_buf_2_Rcv_queue(); #region fast recover /// fast recover diff --git a/KCP/Kcp/Kcp.csproj b/KCP/Kcp/Kcp.csproj index 93c979fd1..ecd73b45f 100644 --- a/KCP/Kcp/Kcp.csproj +++ b/KCP/Kcp/Kcp.csproj @@ -79,18 +79,19 @@ - + + - TRACE;DEBUG;MIHOMO_KCP;ASSERT_STAINVOKE_DISABLE;KCP_PERFORMANCE_TEST_DISABLE;BUGFIX_TRIAL_20230609_001_DISABLE;BUGFIX_TRIAL_20230610_001_DISABLE;BUGFIX_TRIAL_20230610_002_DISABLE;BUGFIX_TRIAL_20230611_001_DISABLE + TRACE;DEBUG;MIHOMO_KCP;DISABLED_BYTE_CHECK_MODE;ASSERT_STAINVOKE_DISABLE true false - TRACE;MIHOMO_KCP + TRACE;MIHOMO_KCP;DISABLED_BYTE_CHECK_MODE true true diff --git a/KCP/Kcp/KcpCore.cs b/KCP/Kcp/KcpCore.cs index e6de3697b..4418a536e 100644 --- a/KCP/Kcp/KcpCore.cs +++ b/KCP/Kcp/KcpCore.cs @@ -3,6 +3,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; +using System.IO.Hashing; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using static System.Math; @@ -94,13 +95,16 @@ output udp发送消息的回调函数 public const int IKCP_MTU_DEF = 1400; public const int IKCP_ACK_FAST = 3; public const int IKCP_INTERVAL = 100; + public const int IKCP_OVERHEAD = 24 +#if MIHOMO_KCP // miHoMo KCP modify: IKCP_OVERHEAD = 28 // Change line(s) in file compare: ikcp.c, -40 +40 -#if !MIHOMO_KCP - public const int IKCP_OVERHEAD = 24; -#else - public const int IKCP_OVERHEAD = 28; + + 4 #endif +#if BYTE_CHECK_MODE + + 4 +#endif + ; public const int IKCP_DEADLINK = 20; public const int IKCP_THRESH_INIT = 2; public const int IKCP_THRESH_MIN = 2; @@ -269,6 +273,17 @@ protected int BufferNeedSize public int stream; protected BufferOwner buffer; +#if BYTE_CHECK_MODE + /// + /// 应使用的 checksum 算法。1 使用 CRC32;2 使用 xxHash. + /// + protected uint byteCheckMode; + /// + /// 是否对包进行随机损坏。2B 功能。 + /// + protected bool corrupt; +#endif + #endregion #region 锁和容器 @@ -283,7 +298,7 @@ protected int BufferNeedSize protected readonly object rcv_queueLock = new object(); /// - /// 发送 ack 队列 + /// 发送 ack 队列 /// protected ConcurrentQueue<(uint sn, uint ts)> acklist = new ConcurrentQueue<(uint sn, uint ts)>(); /// @@ -298,7 +313,7 @@ protected int BufferNeedSize /// 正在等待触发接收回调函数消息列表 /// 需要执行的操作 添加 遍历 删除 /// -#if !KCP_PERFORMANCE_TEST +#if true internal List rcv_queue = new List(); #else internal OuterCode.SegmentTraceList rcv_queue = new(); @@ -356,6 +371,11 @@ public KcpCore(uint conv_) #else _updateassert = new($"{nameof(KcpCore)}_{nameof(Update)}(conv:{conv}, token:{token})"); #endif +#endif + +#if BYTE_CHECK_MODE + byteCheckMode = 1; + corrupt = false; #endif } @@ -621,19 +641,17 @@ public DateTimeOffset Check(in DateTimeOffset time) /// protected void Move_Rcv_buf_2_Rcv_queue() { -#if !BUGFIX_TRIAL_20230610_001 lock (rcv_bufLock) { -#endif while (rcv_buf.Count > 0) { var seg = rcv_buf.First.Value; -#if KCP_PERFORMANCE_TEST +#if false LogWriteLine($"rcv_nxt Trace: {rcv_nxt}", KcpLogMask.IKCP_LOG_INPUT.ToString()); #endif if (seg.sn == rcv_nxt && rcv_queue.Count < rcv_wnd) { -#if KCP_PERFORMANCE_TEST +#if false LogWriteLine($"moved to rcv_queue, rcv_nxt: {rcv_nxt}, seg: {seg.ToLogString(false)}", KcpLogMask.IKCP_LOG_INPUT.ToString()); #endif rcv_buf.RemoveFirst(); @@ -649,9 +667,7 @@ protected void Move_Rcv_buf_2_Rcv_queue() break; } } -#if !BUGFIX_TRIAL_20230610_001 } -#endif } /// @@ -690,14 +706,10 @@ protected void Update_ack(int rtt) protected void Shrink_buf() { -#if !BUGFIX_TRIAL_20230609_001 lock (snd_bufLock) { -#endif snd_una = snd_buf.Count > 0 ? snd_buf.First.Value.sn : snd_nxt; -#if !BUGFIX_TRIAL_20230609_001 } -#endif } protected void Parse_ack(uint sn) @@ -730,10 +742,8 @@ protected void Parse_ack(uint sn) protected void Parse_una(uint una) { /// 删除给定时间之前的片段。保留之后的片段 -#if !BUGFIX_TRIAL_20230609_001 lock (snd_bufLock) { -#endif while (snd_buf.First != null) { var seg = snd_buf.First.Value; @@ -747,9 +757,7 @@ protected void Parse_una(uint una) break; } } -#if !BUGFIX_TRIAL_20230609_001 } -#endif } @@ -848,14 +856,9 @@ internal virtual void Parse_data(Segment newseg) { SegmentManager.Free(newseg); } -#if !BUGFIX_TRIAL_20230610_001 } -#endif - Move_Rcv_buf_2_Rcv_queue(); -#if BUGFIX_TRIAL_20230610_001 - } -#endif + Move_Rcv_buf_2_Rcv_queue(); } protected ushort Wnd_unused() @@ -920,6 +923,9 @@ protected void Flush() //seg.len = 0; //seg.sn = 0; //seg.ts = 0; +#if BYTE_CHECK_MODE + seg.byteCheckMode = byteCheckMode; +#endif #region flush acknowledges @@ -1027,51 +1033,40 @@ protected void Flush() cwnd_ = Min(cwnd, cwnd_); } -#if BUGFIX_TRIAL_20230610_002 - lock (snd_queueLock) + while (Itimediff(snd_nxt, snd_una + cwnd_) < 0) { -#endif -#if KCP_PERFORMANCE_TEST - byte pre_frg = 255; -#endif - while (Itimediff(snd_nxt, snd_una + cwnd_) < 0) + if (snd_queue.TryDequeue(out var newseg)) { - if (snd_queue.TryDequeue(out var newseg)) - { -#if KCP_PERFORMANCE_TEST - if (pre_frg != 255) Debug.Assert(((newseg.frg - pre_frg + 1) % 3) == 0); - pre_frg = newseg.frg; -#endif - newseg.conv = conv; + newseg.conv = conv; #if MIHOMO_KCP - // miHoMo KCP modify: IUINT32 token - // Change line(s) in file compare: ikcp.c, +1040 - newseg.token = token; + // miHoMo KCP modify: IUINT32 token + // Change line(s) in file compare: ikcp.c, +1040 + newseg.token = token; #endif - newseg.cmd = IKCP_CMD_PUSH; - newseg.wnd = wnd_; - newseg.ts = current_; - newseg.sn = snd_nxt; - snd_nxt++; - newseg.una = rcv_nxt; - newseg.resendts = current_; - newseg.rto = rx_rto; - newseg.fastack = 0; - newseg.xmit = 0; - lock (snd_bufLock) - { - snd_buf.AddLast(newseg); - } - } - else + newseg.cmd = IKCP_CMD_PUSH; + newseg.wnd = wnd_; + newseg.ts = current_; + newseg.sn = snd_nxt; + snd_nxt++; + newseg.una = rcv_nxt; + newseg.resendts = current_; + newseg.rto = rx_rto; + newseg.fastack = 0; + newseg.xmit = 0; +#if BYTE_CHECK_MODE + newseg.byteCheckMode = byteCheckMode; +#endif + lock (snd_bufLock) { - break; + snd_buf.AddLast(newseg); } } -#if BUGFIX_TRIAL_20230610_002 + else + { + break; + } } -#endif #endregion #region 刷新 发送列表,调用Output @@ -1144,6 +1139,30 @@ protected void Flush() } offset += segment.Encode(buffer.Memory.Span.Slice(offset)); +#if BYTE_CHECK_MODE + if (corrupt && segment.cmd == IKCP_CMD_PUSH && segment.len > 0 && segment.sn > 500) + { + if (segment.xmit < 2) + { + lock (Random.Shared) + { + var segmem = buffer.Memory.Span.Slice(offset - (int)segment.len); + segmem[Random.Shared.Next(0, (int)segment.len)] = 0; + } + if (CanLog(KcpLogMask.IKCP_LOG_OUT_DATA)) + { + LogWriteLine($"Segment sn={segment.sn}: corrupted packet", KcpLogMask.IKCP_LOG_OUT_DATA.ToString()); + } + } + else + { + if (CanLog(KcpLogMask.IKCP_LOG_OUT_DATA)) + { + LogWriteLine($"Segment sn={segment.sn}: skip corrupt", KcpLogMask.IKCP_LOG_OUT_DATA.ToString()); + } + } + } +#endif if (CanLog(KcpLogMask.IKCP_LOG_NEED_SEND)) { @@ -1214,7 +1233,7 @@ protected void Flush() } protected virtual void OnDeadlink() - { + { } @@ -1222,6 +1241,7 @@ protected virtual void OnDeadlink() /// Test OutputWriter /// Unuseable now for not applied miHoMo KCP modify. /// + [Obsolete("Unuseable now for not applied miHoMo KCP modify.", true)] protected void Flush2() { var current_ = current; @@ -1585,7 +1605,7 @@ public int SetMtu(int mtu = IKCP_MTU_DEF) } /// - /// + /// /// /// /// @@ -1649,6 +1669,26 @@ public int WndSize(int sndwnd = IKCP_WND_SND, int rcvwnd = IKCP_WND_RCV) return 0; } +#if BYTE_CHECK_MODE + public int SetByteCheck(uint byteCheckMode, bool corrupt) + { + switch (byteCheckMode) + { + case 1: + case 2: + case 0: + break; + default: + return -1; + } + + this.byteCheckMode = byteCheckMode; + this.corrupt = corrupt; + + return 0; + } +#endif + #endregion @@ -1685,7 +1725,7 @@ public int Send(ReadOnlySpan span, object options = null) #region append to previous segment in streaming mode (if possible) /// 基于线程安全和数据结构的等原因,移除了追加数据到最后一个包行为。 - + /// C语言版本snd_queue使用双向链表,可以修改最后一个包。 /// C#当前snd_queue使用ConcurrentQueue,无法修改最后一个包。所以无法实现流模式。 #endregion @@ -1701,10 +1741,6 @@ public int Send(ReadOnlySpan span, object options = null) count = (int)(span.Length + mss - 1) / (int)mss; } -#if KCP_PERFORMANCE_TEST - Debug.Assert(count == (int)Ceiling((double)(3500 + 16) / mss)); -#endif - if (count > IKCP_WND_RCV) { return -2; @@ -1849,6 +1885,7 @@ public int Input(ReadOnlySpan span) int flag = 0; uint maxack = 0; uint latest_ts = 0; + Span header = stackalloc byte[IKCP_OVERHEAD]; while (true) { uint ts = 0; @@ -1864,6 +1901,9 @@ public int Input(ReadOnlySpan span) ushort wnd = 0; byte cmd = 0; byte frg = 0; +#if BYTE_CHECK_MODE + uint byteCheckCode = 0; +#endif if (span.Length - offset < IKCP_OVERHEAD) { @@ -1872,13 +1912,7 @@ public int Input(ReadOnlySpan span) // miHoMo KCP modify: data = ikcp_decode32u(data, &token); // Change line(s) in file compare: ikcp.c, +773 -#if !MIHOMO_KCP - Span header = stackalloc byte[24]; - span.Slice(offset, 24).CopyTo(header); -#else - Span header = stackalloc byte[28]; - span.Slice(offset, 28).CopyTo(header); -#endif + span.Slice(offset, IKCP_OVERHEAD).CopyTo(header); offset += ReadHeader(header, ref conv_, // miHoMo KCP modify: data = ikcp_decode32u(data, &token); @@ -1892,7 +1926,11 @@ public int Input(ReadOnlySpan span) ref ts, ref sn, ref una, - ref length); + ref length +#if BYTE_CHECK_MODE + ,ref byteCheckCode +#endif + ); if (conv != conv_) { @@ -1925,31 +1963,17 @@ public int Input(ReadOnlySpan span) } rmt_wnd = wnd; -#if BUGFIX_TRIAL_20230609_001 - lock (snd_bufLock) - { -#endif - Parse_una(una); - Shrink_buf(); -#if BUGFIX_TRIAL_20230609_001 - } -#endif + Parse_una(una); + Shrink_buf(); if (IKCP_CMD_ACK == cmd) { if (Itimediff(current, ts) >= 0) { Update_ack(Itimediff(current, ts)); } -#if BUGFIX_TRIAL_20230609_001 - lock (snd_bufLock) - { -#endif - Parse_ack(sn); - Shrink_buf(); + Parse_ack(sn); + Shrink_buf(); -#if BUGFIX_TRIAL_20230609_001 - } -#endif if (flag == 0) { flag = 1; @@ -1984,6 +2008,17 @@ public int Input(ReadOnlySpan span) if (Itimediff(sn, rcv_nxt + rcv_wnd) < 0) { +#if BYTE_CHECK_MODE + if (!byteCheck(span.Slice(offset, (int)length), byteCheckMode, byteCheckCode)) + { + if (CanLog(KcpLogMask.IKCP_LOG_IN_DATA)) + { + LogWriteLine($"input psh dropped (checksum failed): sn={sn} ts={ts}", KcpLogMask.IKCP_LOG_IN_DATA.ToString()); + } + offset += (int)length; + continue; + } +#endif ///instead of ikcp_ack_push acklist.Enqueue((sn, ts)); @@ -2109,6 +2144,7 @@ public int Input(ReadOnlySequence span) int flag = 0; uint maxack = 0; uint latest_ts = 0; + Span header = stackalloc byte[IKCP_OVERHEAD]; while (true) { uint ts = 0; @@ -2124,6 +2160,9 @@ public int Input(ReadOnlySequence span) ushort wnd = 0; byte cmd = 0; byte frg = 0; +#if BYTE_CHECK_MODE + uint byteCheckCode = 0; +#endif if (span.Length - offset < IKCP_OVERHEAD) { @@ -2132,13 +2171,7 @@ public int Input(ReadOnlySequence span) // miHoMo KCP modify: data = ikcp_decode32u(data, &token); // Change line(s) in file compare: ikcp.c, +773 -#if !MIHOMO_KCP - Span header = stackalloc byte[24]; - span.Slice(offset, 24).CopyTo(header); -#else - Span header = stackalloc byte[28]; - span.Slice(offset, 28).CopyTo(header); -#endif + span.Slice(offset, IKCP_OVERHEAD).CopyTo(header); offset += ReadHeader(header, ref conv_, // miHoMo KCP modify: data = ikcp_decode32u(data, &token); @@ -2152,7 +2185,11 @@ public int Input(ReadOnlySequence span) ref ts, ref sn, ref una, - ref length); + ref length +#if BYTE_CHECK_MODE + ,ref byteCheckCode +#endif + ); if (conv != conv_) { @@ -2185,15 +2222,8 @@ public int Input(ReadOnlySequence span) } rmt_wnd = wnd; -#if BUGFIX_TRIAL_20230609_001 - lock (snd_bufLock) - { -#endif - Parse_una(una); - Shrink_buf(); -#if BUGFIX_TRIAL_20230609_001 - } -#endif + Parse_una(una); + Shrink_buf(); if (IKCP_CMD_ACK == cmd) { @@ -2201,15 +2231,8 @@ public int Input(ReadOnlySequence span) { Update_ack(Itimediff(current, ts)); } -#if BUGFIX_TRIAL_20230609_001 - lock (snd_bufLock) - { -#endif - Parse_ack(sn); - Shrink_buf(); -#if BUGFIX_TRIAL_20230609_001 - } -#endif + Parse_ack(sn); + Shrink_buf(); if (flag == 0) { @@ -2246,6 +2269,17 @@ public int Input(ReadOnlySequence span) if (Itimediff(sn, rcv_nxt + rcv_wnd) < 0) { +#if BYTE_CHECK_MODE + if (!byteCheck(span.Slice(offset, (int)length), byteCheckMode, byteCheckCode)) + { + if (CanLog(KcpLogMask.IKCP_LOG_IN_DATA)) + { + LogWriteLine($"input psh dropped (checksum failed): sn={sn} ts={ts}", KcpLogMask.IKCP_LOG_IN_DATA.ToString()); + } + offset += (int)length; + continue; + } +#endif ///instead of ikcp_ack_push acklist.Enqueue((sn, ts)); @@ -2356,7 +2390,11 @@ public static int ReadHeader(ReadOnlySpan header, ref uint ts, ref uint sn, ref uint una, - ref uint length) + ref uint length +#if BYTE_CHECK_MODE + ,ref uint byteCheckCode +#endif + ) { var offset = 0; if (IsLittleEndian) @@ -2385,6 +2423,10 @@ public static int ReadHeader(ReadOnlySpan header, offset += 4; length = BinaryPrimitives.ReadUInt32LittleEndian(header.Slice(offset)); offset += 4; +#if BYTE_CHECK_MODE + byteCheckCode = BinaryPrimitives.ReadUInt32LittleEndian(header.Slice(offset)); + offset += 4; +#endif } else { @@ -2412,10 +2454,62 @@ public static int ReadHeader(ReadOnlySpan header, offset += 4; length = BinaryPrimitives.ReadUInt32BigEndian(header.Slice(offset)); offset += 4; +#if BYTE_CHECK_MODE + byteCheckCode = BinaryPrimitives.ReadUInt32BigEndian(header.Slice(offset)); + offset += 4; +#endif } return offset; } + +#if BYTE_CHECK_MODE + public static bool byteCheck(ReadOnlySpan data, uint byteCheckMode, uint byteCheckCode) + { + uint newByteCheckCode = 0; + switch (byteCheckMode) + { + case 1: + newByteCheckCode = Crc32.HashToUInt32(data); + break; + case 2: + newByteCheckCode = (uint)XxHash3.HashToUInt64(data); + break; + default: + newByteCheckCode = byteCheckCode; + break; + } + return byteCheckCode == newByteCheckCode; + } + + public static bool byteCheck(ReadOnlySequence data, uint byteCheckMode, uint byteCheckCode) + { + uint newByteCheckCode; + switch (byteCheckMode) + { + case 1: + var crc = new Crc32(); + foreach (var mem in data) + { + crc.Append(mem.Span); + } + newByteCheckCode = crc.GetCurrentHashAsUInt32(); + break; + case 2: + var xxhash3_64 = new XxHash3(); + foreach (var mem in data) + { + xxhash3_64.Append(mem.Span); + } + newByteCheckCode = (uint)xxhash3_64.GetCurrentHashAsUInt64(); + break; + default: + newByteCheckCode = byteCheckCode; + break; + } + return byteCheckCode == newByteCheckCode; + } +#endif } } diff --git a/KCP/Kcp/KcpIO.cs b/KCP/Kcp/KcpIO.cs index cecda325d..f8a6f5d22 100644 --- a/KCP/Kcp/KcpIO.cs +++ b/KCP/Kcp/KcpIO.cs @@ -6,7 +6,7 @@ namespace System.Net.Sockets.Kcp { /// - /// + /// IPipe{T} /// 这是个简单的实现,更复杂使用微软官方实现 /// /// diff --git a/KCP/Kcp/KcpSegment.cs b/KCP/Kcp/KcpSegment.cs index a1fde0129..a2d13c2cb 100644 --- a/KCP/Kcp/KcpSegment.cs +++ b/KCP/Kcp/KcpSegment.cs @@ -1,6 +1,7 @@ using System.Buffers; using System.Buffers.Binary; using System.Diagnostics; +using System.IO.Hashing; using System.Runtime.InteropServices; using YYHEggEgg.Logger; @@ -15,7 +16,7 @@ namespace System.Net.Sockets.Kcp /// public struct KcpSegment : IKcpSegment { -#if KCP_PERFORMANCE_TEST +#if false private string Invoker() { StackTrace stackTrace = new StackTrace(); @@ -24,9 +25,6 @@ private string Invoker() } #endif -#if BUGFIX_TRIAL_20230611_001 - private static object marshal_lck = new object(); -#endif internal readonly unsafe byte* ptr; public unsafe KcpSegment(byte* intPtr, uint appendDateSize) { @@ -42,16 +40,9 @@ public unsafe KcpSegment(byte* intPtr, uint appendDateSize) public static KcpSegment AllocHGlobal(int appendDateSize) { var total = LocalOffset + HeadOffset + appendDateSize; -#if BUGFIX_TRIAL_20230611_001 - IntPtr intPtr; - lock (marshal_lck) - { - intPtr = Marshal.AllocHGlobal(total); - } -#else + IntPtr intPtr = Marshal.AllocHGlobal(total); -#endif -#if KCP_PERFORMANCE_TEST +#if false Log.Verb($"KcpSegment memory alloc: 0x{intPtr:x}", nameof(KcpSegment)); #endif unsafe @@ -72,15 +63,8 @@ public static void FreeHGlobal(KcpSegment seg) { unsafe { -#if BUGFIX_TRIAL_20230611_001 - lock (marshal_lck) - { -#endif - Marshal.FreeHGlobal((IntPtr)seg.ptr); -#if BUGFIX_TRIAL_20230611_001 - } -#endif -#if KCP_PERFORMANCE_TEST + Marshal.FreeHGlobal((IntPtr)seg.ptr); +#if false Log.Verb($"KcpSegment memory free: 0x{(IntPtr)seg.ptr:x}", nameof(KcpSegment)); #endif } @@ -171,8 +155,36 @@ public uint xmit } } +#if BYTE_CHECK_MODE + + /// + /// offset = 16 + /// + public uint byteCheckMode + { + get + { + unsafe + { + return *(uint*)(ptr + 16); + } + } + set + { + unsafe + { + *(uint*)(ptr + 16) = value; + } + } + } +#endif + ///以下为需要网络传输的参数 +#if BYTE_CHECK_MODE + public const int LocalOffset = 4 * 5; +#else public const int LocalOffset = 4 * 4; +#endif public const int HeadOffset = KcpConst.IKCP_OVERHEAD; /// @@ -291,7 +303,7 @@ public byte frg } set { -#if KCP_PERFORMANCE_TEST +#if false Log.Verb($"Invoker: [{Invoker()}] assigned frg:{value} for KcpSegment: {this.ToLogString(false)}", nameof(KcpSegment)); #endif unsafe @@ -418,7 +430,7 @@ public uint sn } set { -#if KCP_PERFORMANCE_TEST +#if false Log.Verb($"Invoker: [{Invoker()}] assigned sn:{value} for KcpSegment: {this.ToLogString(false)}", nameof(KcpSegment)); #endif unsafe @@ -517,8 +529,52 @@ private set } } +#if BYTE_CHECK_MODE + // miHoMo KCP modify: IUINT32 token + // Change line(s) in file compare: ikcp.h, +271 +#if !MIHOMO_KCP + /// + /// AppendDateSize + /// offset = + 24 + /// +#else + /// + /// offset = + 28 + /// +#endif + public uint byteCheckCode + { + get + { + unsafe + { + // miHoMo KCP modify: IUINT32 token + // Change line(s) in file compare: ikcp.h, +271 +#if !MIHOMO_KCP + return *(uint*)(LocalOffset + 24 + ptr); +#else + return *(uint*)(LocalOffset + 28 + ptr); +#endif + } + } + private set + { + unsafe + { + // miHoMo KCP modify: IUINT32 token + // Change line(s) in file compare: ikcp.h, +271 +#if !MIHOMO_KCP + *(uint*)(LocalOffset + 24 + ptr) = value; +#else + *(uint*)(LocalOffset + 28 + ptr) = value; +#endif + } + } + } +#endif + /// - /// + /// /// /// https://github.com/skywind3000/kcp/issues/35#issuecomment-263770736 public Span data @@ -532,7 +588,25 @@ public Span data } } - +#if BYTE_CHECK_MODE + public void ComputeByteCheckCodeFromData() + { + switch (byteCheckMode) + { + case 1: + var buffer = data; + byteCheckCode = Crc32.HashToUInt32(buffer); + break; + case 2: + var buffer2 = data; + byteCheckCode = (uint)XxHash3.HashToUInt64(buffer2); + break; + default: + byteCheckCode = 0; + break; + } + } +#endif /// /// 将片段中的要发送的数据拷贝到指定缓冲区 @@ -542,6 +616,9 @@ public Span data public int Encode(Span buffer) { var datelen = (int)(HeadOffset + len); +#if BYTE_CHECK_MODE + if (byteCheckCode == 0) ComputeByteCheckCodeFromData(); +#endif ///备用偏移值 现阶段没有使用 const int offset = 0; @@ -573,6 +650,9 @@ public int Encode(Span buffer) BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 12), sn); BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 16), una); BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 20), len); +#if BYTE_CHECK_MODE + BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 24), byteCheckCode); +#endif #else BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset), conv); BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset), token); @@ -584,6 +664,9 @@ public int Encode(Span buffer) BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 16), sn); BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 20), una); BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 24), len); +#if BYTE_CHECK_MODE + BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 28), byteCheckCode); +#endif #endif data.CopyTo(buffer.Slice(HeadOffset)); } @@ -604,6 +687,9 @@ public int Encode(Span buffer) BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 12), sn); BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 16), una); BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 20), len); +#if BYTE_CHECK_MODE + BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 24), byteCheckCode); +#endif #else BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset), conv); BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset), token); @@ -615,6 +701,9 @@ public int Encode(Span buffer) BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 16), sn); BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 20), una); BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 24), len); +#if BYTE_CHECK_MODE + BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 28), byteCheckCode); +#endif #endif data.CopyTo(buffer.Slice(HeadOffset)); } diff --git a/KCP/Kcp/SegManager.cs b/KCP/Kcp/SegManager.cs index 278d21305..976dbf210 100644 --- a/KCP/Kcp/SegManager.cs +++ b/KCP/Kcp/SegManager.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Collections.Concurrent; using System.Buffers.Binary; +using System.IO.Hashing; namespace System.Net.Sockets.Kcp { @@ -216,10 +217,35 @@ public Seg(int blockSize) public uint una { get; set; } public ushort wnd { get; set; } public uint xmit { get; set; } +#if BYTE_CHECK_MODE + public uint byteCheckMode { get; set; } + public uint byteCheckCode { get; internal set; } + + public void ComputeByteCheckCodeFromData() + { + switch (byteCheckMode) + { + case 1: + var buffer = data; + byteCheckCode = Crc32.HashToUInt32(buffer); + break; + case 2: + var buffer2 = data; + byteCheckCode = (uint)XxHash64.HashToUInt64(buffer2); + break; + default: + byteCheckCode = 0; + break; + } + } +#endif public int Encode(Span buffer) { var datelen = (int)(HeadOffset + len); +#if BYTE_CHECK_MODE + if (byteCheckCode == 0) ComputeByteCheckCodeFromData(); +#endif ///备用偏移值 现阶段没有使用 const int offset = 0; @@ -238,6 +264,9 @@ public int Encode(Span buffer) BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 12), sn); BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 16), una); BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 20), len); +#if BYTE_CHECK_MODE + BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 24), byteCheckCode); +#endif #else BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset), conv); BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset), token); @@ -249,6 +278,9 @@ public int Encode(Span buffer) BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 16), sn); BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 20), una); BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 24), len); +#if BYTE_CHECK_MODE + BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 28), byteCheckCode); +#endif #endif data.CopyTo(buffer.Slice(HeadOffset)); } @@ -266,6 +298,9 @@ public int Encode(Span buffer) BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 12), sn); BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 16), una); BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 20), len); +#if BYTE_CHECK_MODE + BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 24), byteCheckCode); +#endif #else BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset), conv); BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset), token); @@ -277,6 +312,9 @@ public int Encode(Span buffer) BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 16), sn); BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 20), una); BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 24), len); +#if BYTE_CHECK_MODE + BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(offset + 28), byteCheckCode); +#endif #endif data.CopyTo(buffer.Slice(HeadOffset)); @@ -307,6 +345,9 @@ public void Free(Seg seg) { seg.cmd = 0; seg.conv = 0; +#if MIHOMO_KCP + seg.token = 0; +#endif seg.fastack = 0; seg.frg = 0; seg.len = 0; @@ -317,6 +358,10 @@ public void Free(Seg seg) seg.una = 0; seg.wnd = 0; seg.xmit = 0; +#if BYTE_CHECK_MODE + seg.byteCheckMode = 0; + seg.byteCheckCode = 0; +#endif Pool.Push(seg); } diff --git a/KCP/Kcp/SimpleKcpClient.cs b/KCP/Kcp/SimpleKcpClient.cs index 7f6e889d4..0654c95c7 100644 --- a/KCP/Kcp/SimpleKcpClient.cs +++ b/KCP/Kcp/SimpleKcpClient.cs @@ -47,6 +47,7 @@ public void Output(IMemoryOwner buffer, int avalidLength, bool isKcpPacket public async void SendAsync(byte[] datagram, int bytes) { kcp.Send(datagram.AsSpan().Slice(0, bytes)); + await Task.CompletedTask; } public async ValueTask ReceiveAsync() diff --git a/KCP/Kcp/Utility.cs b/KCP/Kcp/Utility.cs index 64ac5084f..265322b41 100644 --- a/KCP/Kcp/Utility.cs +++ b/KCP/Kcp/Utility.cs @@ -50,7 +50,7 @@ public static uint ConvertTime(this in DateTimeOffset time) public static string ToLogString(this T segment, bool local = false) where T : IKcpSegment { -#if !KCP_PERFORMANCE_TEST +#if true if (local) { return $"sn:{segment.sn,2} una:{segment.una,2} frg:{segment.frg,2} cmd:{segment.cmd,2} len:{segment.len,2} wnd:{segment.wnd} [ LocalValue: xmit:{segment.xmit} fastack:{segment.fastack} rto:{segment.rto} ]"; diff --git a/NewProtoHandlers/NewProtoHandlers.csproj b/NewProtoHandlers/NewProtoHandlers.csproj index a6d14ff79..dd88f3c97 100644 --- a/NewProtoHandlers/NewProtoHandlers.csproj +++ b/NewProtoHandlers/NewProtoHandlers.csproj @@ -19,7 +19,7 @@ - + diff --git a/OldProtoHandlers/OldProtoHandlers.csproj b/OldProtoHandlers/OldProtoHandlers.csproj index 75e9a96e7..847c7eb6f 100644 --- a/OldProtoHandlers/OldProtoHandlers.csproj +++ b/OldProtoHandlers/OldProtoHandlers.csproj @@ -19,7 +19,7 @@ - + diff --git a/ProtoshiftHandlers/ProtoshiftHandlers.csproj b/ProtoshiftHandlers/ProtoshiftHandlers.csproj index 1483d808d..36f6e37f7 100644 --- a/ProtoshiftHandlers/ProtoshiftHandlers.csproj +++ b/ProtoshiftHandlers/ProtoshiftHandlers.csproj @@ -27,7 +27,7 @@ - + diff --git a/Tests/KcpTests/KcpPerformanceTest/Analysis/MainAnalysis.cs b/Tests/KcpTests/KcpPerformanceTest/Analysis/MainAnalysis.cs index 2b49c4539..f7e676395 100644 --- a/Tests/KcpTests/KcpPerformanceTest/Analysis/MainAnalysis.cs +++ b/Tests/KcpTests/KcpPerformanceTest/Analysis/MainAnalysis.cs @@ -10,6 +10,7 @@ namespace csharp_Protoshift.MhyKCP.Test.Analysis internal static class MainAnalysis { public static bool TestsFinished { get; private set; } = false; + public static int ProgramExitCode { get; private set; } = 0; /// /// 客户端发出全部包后调用,在10s后锁定,并停止Proxy与Server的数据收集并创建副本 @@ -52,6 +53,7 @@ public static async Task ClientFinished() TestsFinished = true; } +#pragma warning disable CS0168 static ReadOnlyBasePacketRecord[]? client_sent, client_recved, #if CONNECT_SERVERONLY @@ -61,6 +63,7 @@ static ReadOnlyBasePacketRecord[]? server_recved, server_sent, proxy_server_recved, proxy_server_sent; #endif +#pragma warning restore CS0168 private static async Task HandleData() { @@ -204,6 +207,8 @@ private static async Task HandleData() acklist += $"{loss}; "; } acklist += "]"; + if (Cs_proxy_failed.lost_ack.Any()) + ProgramExitCode = 114514; Output(stringRes, acklist); #endregion Output(stringRes); @@ -216,6 +221,8 @@ private static async Task HandleData() acklist += $"{loss}; "; } acklist += "]"; + if (Sc_proxy_failed.lost_ack.Any()) + ProgramExitCode = 114514; Output(stringRes, acklist); #endregion Output(stringRes); @@ -333,6 +340,7 @@ private static void OutputLossAck(StringBuilder target, PacketLossResult lossRes } else { + ProgramExitCode = 114514; Output(target, $"{from_friendlyName} -> {to_friendlyName} 丢包情况:"); Output(target, $" 出现了 {lossResult.lost_ack.Length} 个包丢失。ack 列表:"); #region Lost packet @@ -365,6 +373,7 @@ private static void OutputInvertedPacket(StringBuilder target, PacketDelayResult { if (delay.inverted_ack_list.Length != 0) { + ProgramExitCode = 114514; Output(target, $"{from_friendlyName} -> {to_friendlyName}: 出现了 {delay.inverted_ack_list.Length} 次乱序现象。"); foreach (var inverted_pkt in delay.inverted_ack_list) { diff --git a/Tests/KcpTests/KcpPerformanceTest/Client/ClientApp.cs b/Tests/KcpTests/KcpPerformanceTest/Client/ClientApp.cs index 67527c02b..53a1c85ca 100644 --- a/Tests/KcpTests/KcpPerformanceTest/Client/ClientApp.cs +++ b/Tests/KcpTests/KcpPerformanceTest/Client/ClientApp.cs @@ -21,9 +21,9 @@ public ClientApp(uint clientId) public async Task Start() { #if CONNECT_SERVERONLY - KCPClient kcpClient = new(new(IPAddress.Loopback, Constants.UDP_SERVER_PORT)); + KCPClient kcpClient = new(new IPEndPoint(IPAddress.Loopback, Constants.UDP_SERVER_PORT)); #else - KCPClient kcpClient = new(new(IPAddress.Loopback, Constants.UDP_PROXY_PORT)); + KCPClient kcpClient = new(new IPEndPoint(IPAddress.Loopback, Constants.UDP_PROXY_PORT)); #endif await kcpClient.ConnectAsync(); #if CONNECT_SERVERONLY @@ -31,7 +31,7 @@ public async Task Start() #else Log.Info($"KCPClient connected to localhost:{Constants.UDP_PROXY_PORT}.", nameof(ClientApp)); #endif - _ = Task.Run(async () => + Util.RunBackground(async () => { int sum_wait_ms = 0; uint ack = (uint)(Constants.packet_repeat_time * 2 * clientId + 1); @@ -52,7 +52,7 @@ public async Task Start() { BasePacket pkt = BasePacket.Generate(ack, (uint)Constants.each_packet_size); kcpClient.Send(pkt.GetBytes()); - Log.Verb($"Client sent ack: {ack}", "ClientSender"); + Log.Verb($"Client sent ack: {ack} (id: {pkt.Unique_ID})", "ClientSender"); ClientDataChannel.PushSentPacket(pkt); pkt.Dispose(); sum_wait_ms += Constants.packet_interval_ms; @@ -70,9 +70,9 @@ public async Task Start() ack += 2; } _finished = true; - }); + }, $"The sender of Client {clientId} has met a fatal error. ", "ClientSender"); - _ = Task.Run(() => + Util.RunBackground(() => { while (true) { @@ -81,7 +81,7 @@ public async Task Start() var data = kcpClient.Receive(); var packet = new BasePacket(data); ClientDataChannel.PushReceivedPacket(packet); - Log.Verb($"Client recved packet: isStructureValid:{packet.isStructureValid}, isBodyValid:{packet.isBodyValid}, ack:{packet.ack}, bodyLen:{packet.bodyLen}"); + Log.Verb($"Client recved packet: isStructureValid:{packet.isStructureValid}, isBodyValid:{packet.isBodyValid}, ack:{packet.ack}, id:{packet.Unique_ID}, bodyLen:{packet.bodyLen}", "ClientReceiver"); packet.Dispose(); } catch (Exception ex) @@ -89,7 +89,7 @@ public async Task Start() Log.Erro($"Client receiving packet meets exception: {ex}", "ClientReceiver_AsyncTask"); } } - }); + }, $"The receiver of Client {clientId} has met a fatal error. ", "ClientReceiver"); } internal static async Task WaitForAllClients() diff --git a/Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj b/Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj index faaca28bd..e96732dfa 100644 --- a/Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj +++ b/Tests/KcpTests/KcpPerformanceTest/KcpPerformanceTest.csproj @@ -9,19 +9,19 @@ - - $(DefineConstants) + + $(DefineConstants);DISABLED_BYTE_CHECK_MODE - - $(DefineConstants) + + $(DefineConstants);DISABLED_BYTE_CHECK_MODE - + diff --git a/Tests/KcpTests/KcpPerformanceTest/Program.cs b/Tests/KcpTests/KcpPerformanceTest/Program.cs index 09223fdb5..7f93071da 100644 --- a/Tests/KcpTests/KcpPerformanceTest/Program.cs +++ b/Tests/KcpTests/KcpPerformanceTest/Program.cs @@ -1,5 +1,6 @@ using CommandLine; using CommandLine.Text; +using csharp_Protoshift.MhyKCP.Test; using csharp_Protoshift.MhyKCP.Test.Analysis; using csharp_Protoshift.MhyKCP.Test.App; using csharp_Protoshift.resLoader; @@ -15,13 +16,8 @@ private static async Task Main(string[] args) max_Output_Char_Count: 16 * 1024, use_Console_Wrapper: false, use_Working_Directory: true, -#if DEBUG global_Minimum_LogLevel: LogLevel.Verbose, console_Minimum_LogLevel: LogLevel.Information, -#else - global_Minimum_LogLevel: LogLevel.Information, - console_Minimum_LogLevel: LogLevel.Information, -#endif debug_LogWriter_AutoFlush: true )); ExcelPackage.LicenseContext = LicenseContext.NonCommercial; @@ -45,7 +41,7 @@ private static async Task Main(string[] args) Environment.Exit(1); }); - await ServerApp.Start(); + ServerApp.Start(); #if !CONNECT_SERVERONLY ProxyApp.Start(); #endif @@ -60,13 +56,13 @@ private static async Task Main(string[] args) while (true) { if (!MainAnalysis.TestsFinished) await Task.Delay(10000); - else Environment.Exit(0); + else Environment.Exit(MainAnalysis.ProgramExitCode); } } else { Console.ReadLine(); - Environment.Exit(0); + Environment.Exit(MainAnalysis.ProgramExitCode); } } diff --git a/Tests/KcpTests/KcpPerformanceTest/Protocol/Mihomonet.cs b/Tests/KcpTests/KcpPerformanceTest/Protocol/Mihomonet.cs index d8ff8b418..2123fa947 100644 --- a/Tests/KcpTests/KcpPerformanceTest/Protocol/Mihomonet.cs +++ b/Tests/KcpTests/KcpPerformanceTest/Protocol/Mihomonet.cs @@ -72,7 +72,9 @@ private void InitBuffer(int length, string? invoker_log = null) } #region 发送端 造包相关代码 +#pragma warning disable CS8618 // InitBuffer private BasePacket(int length) +#pragma warning restore CS8618 { lock (increasing_id_lock) Unique_ID = increasing_id++; InitBuffer(length, $"{nameof(BasePacket)}({Unique_ID})_Ctor(len)"); @@ -134,7 +136,9 @@ public BasePacket(byte[]? packet) return; } InitBuffer(packet.Length, $"{nameof(BasePacket)}({Unique_ID})_Ctor(arr)"); +#pragma warning disable CS8604 // InitBuffer Buffer.BlockCopy(packet, 0, _baseBuffer, 0, packet.Length); +#pragma warning restore CS8604 XorDecrypt(ref _baseBuffer); #if DEBUG Log.Verb($"Created BasePacket from array (decrypted): {Convert.ToHexString(_baseBuffer, 0, Math.Min(_baseBuffer.Length, (int)CalculateLength((uint)Constants.each_packet_size)))}", $"{nameof(BasePacket)}({Unique_ID})_Ctor(arr)"); diff --git a/Tests/KcpTests/KcpPerformanceTest/Proxy/GameSession/GameSessionDispatch.cs b/Tests/KcpTests/KcpPerformanceTest/Proxy/GameSession/GameSessionDispatch.cs index f2e83387d..87fdec2cb 100644 --- a/Tests/KcpTests/KcpPerformanceTest/Proxy/GameSession/GameSessionDispatch.cs +++ b/Tests/KcpTests/KcpPerformanceTest/Proxy/GameSession/GameSessionDispatch.cs @@ -96,28 +96,30 @@ public static bool ClientPacketOrdered(byte[] data, uint conv) #endregion #region Packet Record Saver - public static async Task DestroySession(uint conv) + private static object clearup_running_lck = "miHomo Save The World"; + public static void DestroySession(uint conv) { - if (!sessions.ContainsKey(conv)) return; - sessions.TryRemove(conv, out HandlerSession? session); - cancelledSessions.Add(conv); - - if (session == null) + lock (clearup_running_lck) { - Log.Erro($"Session {conv} destroyed but null, probably not recorded!", "GameSessionDispatch"); - return; + if (!sessions.ContainsKey(conv)) return; + sessions.TryRemove(conv, out HandlerSession? session); + cancelledSessions.Add(conv); + + if (session == null) + { + Log.Erro($"Session {conv} destroyed but null, probably not recorded!", "GameSessionDispatch"); + return; + } } } public static void CloseServer() { Closed = true; - List tasks = new(); foreach (var conv in sessions.Keys) { - tasks.Add(DestroySession(conv)); + DestroySession(conv); } - Task.WaitAll(tasks.ToArray()); } #endregion diff --git a/Tests/KcpTests/KcpPerformanceTest/Proxy/GameSession/HandlerSession.cs b/Tests/KcpTests/KcpPerformanceTest/Proxy/GameSession/HandlerSession.cs index 4e3f0f7fc..5d2d7cf12 100644 --- a/Tests/KcpTests/KcpPerformanceTest/Proxy/GameSession/HandlerSession.cs +++ b/Tests/KcpTests/KcpPerformanceTest/Proxy/GameSession/HandlerSession.cs @@ -70,34 +70,6 @@ public byte[] HandlePacket(byte[] packet, bool isNewCmdid) public bool PacketOrdered(byte[] packet, bool isNewCmdid) { - /* Due to current researches, after the urgent packet split was added, - * nothing about network but the Ping value shown in the game has improved, - * and the worst thing is that Protoshift became no longer stable, - * including the same bug as YuFanXing/Protoshift randomly appear at 60% of time. - * That's unbearable but exchanged not much efficiency increase, - * as the base KCP implement is synchronous -- by bussy locks. - * It makes UrgentPacket implement nearly unnecessary at all - * -- as nearly most of packets are sent syncronous actually. - * But the disadvantages are preserved. Some important packets are sent asyncronously, - * but because UdpClient isn't thread-safe, they are possibly dropped or cracked. - * So, considered all the factors, I decided to give up the UrgentPacket implement. - * - * For actual performance improve solutions, some of following ways should be considered: - * - KcpProxy sub clients. - * Though the KcpProxy and KCPServer are designed for multiple clients, - * the KCP base and UdpClient base aren't. Therefore, the most ideal conditions are that - * there's one KcpServer instance for each client. - * - Approach the Java Protoshift implement. - * The most important Protoshift means in this project is deserialize the message - * from one protocol to a general inner json content, and serialize it to another protocol. - * Compared to this, YuFanXing/Protoshift directly transfers variables from protocols - * by generated codes, so it was surely more efficient. - * According to tests, handling a 224KB PlayerLoginRsp packet costs (in HandlerSession only) - * about 68ms in total. - * - Change the base UDP and KCP implements. - * The reason has been mentioned repeatedly above, but notice that - * it works only when UDP and KCP implements are both thread-safe. - */ // return true; if (packet == null) throw new ArgumentNullException(nameof(packet)); XorDecrypt(ref packet, 0, 2); diff --git a/Tests/KcpTests/KcpPerformanceTest/Proxy/ProxyApp.cs b/Tests/KcpTests/KcpPerformanceTest/Proxy/ProxyApp.cs index 28f33d5aa..21bf8ba1c 100644 --- a/Tests/KcpTests/KcpPerformanceTest/Proxy/ProxyApp.cs +++ b/Tests/KcpTests/KcpPerformanceTest/Proxy/ProxyApp.cs @@ -12,8 +12,8 @@ public static void Start() #if CONNECT_SERVERONLY throw new NotImplementedException("Proxy should not be launched in CONNECT_SERVERONLY mode."); #else - KcpProxyServer proxy = new(new(IPAddress.Loopback, Constants.UDP_PROXY_PORT), - new(IPAddress.Loopback, Constants.UDP_SERVER_PORT)); + KcpProxyServer proxy = new(new IPEndPoint(IPAddress.Loopback, Constants.UDP_PROXY_PORT), + new IPEndPoint(IPAddress.Loopback, Constants.UDP_SERVER_PORT)); ProxyHandlers handlers = new ProxyHandlers { OnServerPacketArrival = GameSessionDispatch.HandleServerPacket, @@ -21,7 +21,7 @@ public static void Start() ServerPacketOrdered = GameSessionDispatch.ServerPacketOrdered, ClientPacketOrdered = GameSessionDispatch.ClientPacketOrdered }; - _ = Task.Run(() => proxy.StartProxy(handlers)); + Util.RunBackground(() => proxy.StartProxy(handlers), "ProxyApp has met a fatal error. ", nameof(ProxyApp)); Log.Info($"KcpProxyServer started on 127.0.0.1:{Constants.UDP_PROXY_PORT}", nameof(ProxyApp)); #endif } diff --git a/Tests/KcpTests/KcpPerformanceTest/Server/ServerApp.cs b/Tests/KcpTests/KcpPerformanceTest/Server/ServerApp.cs index 43f373ac5..440868664 100644 --- a/Tests/KcpTests/KcpPerformanceTest/Server/ServerApp.cs +++ b/Tests/KcpTests/KcpPerformanceTest/Server/ServerApp.cs @@ -7,12 +7,12 @@ namespace csharp_Protoshift.MhyKCP.Test.App { public static class ServerApp { - public static async Task Start() + public static void Start() { - KCPServer kcpServer = new(new(IPAddress.Loopback, Constants.UDP_SERVER_PORT)); + KCPServer kcpServer = new(new IPEndPoint(IPAddress.Loopback, Constants.UDP_SERVER_PORT)); Log.Info($"KCPServer listening on localhost:{Constants.UDP_SERVER_PORT}.", nameof(ServerApp)); - _ = Task.Run(() => + Util.RunBackground(() => { while (true) { @@ -20,7 +20,7 @@ public static async Task Start() Log.Info($"New connection from {accepted.RemoteEndpoint}.", "ServerListening_AsyncTask"); var conn = accepted.Connection; // TODO: Push state to analysis - _ = Task.Run(() => + Util.RunBackground(() => { while (true) { @@ -47,7 +47,7 @@ public static async Task Start() continue; } ServerDataChannel.PushReceivedPacket(pkt); - Log.Verb($"Server received packet: length:{data?.Length}, isStructureValid:{pkt.isStructureValid}, isBodyValid:{pkt.isBodyValid}, ack:{pkt.ack}, bodyLen:{pkt.bodyLen}", "ServerReceiver"); + Log.Verb($"Server received packet: length:{data?.Length}, isStructureValid:{pkt.isStructureValid}, isBodyValid:{pkt.isBodyValid}, ack:{pkt.ack}, id:{pkt.Unique_ID}, bodyLen:{pkt.bodyLen}", "ServerReceiver"); if (pkt.isStructureValid) { try @@ -63,10 +63,15 @@ public static async Task Start() continue; } } + else + { + Log.Warn($"致命错误:服务端收到包(ID:{pkt.Unique_ID})结构错误。", "BasePacket"); + Log.Warn($"BasePacket ID:{pkt.Unique_ID}'s Hexdump: {Convert.ToHexString(data ?? Array.Empty())}"); + } } - }); + }, $"The receiver of packet from {accepted.RemoteEndpoint} has met a fatal error.", nameof(ServerApp)); } - }); + }, "ServerApp (Accept) has met a fatal error.", nameof(ServerApp)); } } } \ No newline at end of file diff --git a/Tests/KcpTests/KcpPerformanceTest/Util.cs b/Tests/KcpTests/KcpPerformanceTest/Util.cs index bc7467ee8..41a6f0b89 100644 --- a/Tests/KcpTests/KcpPerformanceTest/Util.cs +++ b/Tests/KcpTests/KcpPerformanceTest/Util.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using YYHEggEgg.Logger; namespace csharp_Protoshift.MhyKCP.Test { @@ -41,7 +42,41 @@ public static string GetInvoker() { StackTrace stackTrace = new StackTrace(); StackFrame? frame = stackTrace.GetFrame(2); - return frame.ToString(); + return frame?.ToString() ?? ""; + } + + /// + /// 创建一个任务,将指定委托置于后台运行。 + /// + /// 要运行的无参委托。 + /// 当委托出现未处理的异常时,传递给 信息的一部分。一般是一个完整的句子,其后接异常信息。 + /// 当委托出现未处理的异常时,传递给 信息的日志 sender。 + public static void RunBackground(Action action, string fatal_notice, string log_sender = $"{nameof(Util)}_{nameof(RunBackground)}") + { + _ = Task.Run(action).ContinueWith(t => + { + if (t.IsFaulted) + { + Log.Erro($"{fatal_notice} {t.Exception}", log_sender); + } + }, TaskContinuationOptions.OnlyOnFaulted); + } + + /// + /// 创建一个任务,将指定委托置于后台运行。 + /// + /// 要运行的无参委托。 + /// 当委托出现未处理的异常时,传递给 信息的一部分。一般是一个完整的句子,其后接异常信息。 + /// 当委托出现未处理的异常时,传递给 信息的日志 sender。 + public static void RunBackground(Func action, string fatal_notice, string log_sender = $"{nameof(Util)}_{nameof(RunBackground)}") + { + _ = Task.Run(action).ContinueWith(t => + { + if (t.IsFaulted) + { + Log.Erro($"{fatal_notice} {t.Exception}", log_sender); + } + }, TaskContinuationOptions.OnlyOnFaulted); } /// @@ -61,7 +96,7 @@ public static string AddNumberedSuffixToPath(string filePath) */ if (File.Exists(filePath)) { - string directory = Path.GetDirectoryName(filePath); + string directory = Path.GetDirectoryName(filePath) ?? string.Empty; string fileName = Path.GetFileNameWithoutExtension(filePath); string extension = Path.GetExtension(filePath); string newFilePath = filePath; @@ -77,7 +112,7 @@ public static string AddNumberedSuffixToPath(string filePath) } else if (Directory.Exists(filePath)) { - string directoryName = Path.GetDirectoryName(filePath); + string directoryName = Path.GetDirectoryName(filePath) ?? string.Empty; string directory = Path.Combine(directoryName, Path.GetFileName(filePath)); string newDirectory = directory; int suffix = 1; diff --git a/Tests/KcpTests/SharedLib/KCP/KcpProxy/KcpProxyBase.cs b/Tests/KcpTests/SharedLib/KCP/KcpProxy/KcpProxyBase.cs index 1ff46c7b0..6f5d312ce 100644 --- a/Tests/KcpTests/SharedLib/KCP/KcpProxy/KcpProxyBase.cs +++ b/Tests/KcpTests/SharedLib/KCP/KcpProxy/KcpProxyBase.cs @@ -1,5 +1,6 @@ -// #define KCP_PROXY_VERBOSE +// #define KCP_PROXY_VERBOSE +using Newtonsoft.Json.Linq; using System.Net; using System.Net.Sockets; using YSFreedom.Common.Util; @@ -13,11 +14,12 @@ namespace csharp_Protoshift.MhyKCP.Proxy public class KcpProxyBase : MhyKcpBase { public KcpProxyClient? sendClient; - public IPEndPoint sendToAddress; + public EndPoint sendToAddress; + protected static LoggerChannel? _kcpstatlogchan = KcpProxyServer._kcpstatlogger?.GetChannel(null); private object handshake_lock = "Tighnari beloved"; - public KcpProxyBase(IPEndPoint sendToAddress, uint conv = 0, uint token = 0, + public KcpProxyBase(EndPoint sendToAddress, uint conv = 0, uint token = 0, Func? PacketHandler = null) : base(conv, token) { @@ -62,6 +64,7 @@ private int InnerInput(byte[] buffer) disconn.Decode(buffer, Handshake.MAGIC_DISCONNECT); _State = ConnectionState.CLOSED; Log.Info($"Client (conv: {_Conv}) requested disconnect (reason: {disconn.Data}), so send disconnect to server", nameof(KcpProxyBase)); + _kcpstatlogchan?.LogInfo($"0|kcp|disconnect|from_client|token={disconn.Token}|reason={disconn.Data}"); sendClient?.Disconnect(disconn.Conv, disconn.Token, disconn.Data); return 0; @@ -70,7 +73,7 @@ private int InnerInput(byte[] buffer) { // Reconnect disconn.Decode(buffer, Handshake.MAGIC_CONNECT); - Log.Info("Client requested reconnect, set to WAIT", nameof(KcpProxyBase)); + Log.Dbug("Client requested reconnect, set to WAIT", nameof(KcpProxyBase)); goto case ConnectionState.HANDSHAKE_WAIT; } @@ -109,14 +112,18 @@ private int InnerInput(byte[] buffer) // Debug.Assert(sendClient == null); sendClient = new(sendToAddress, handshake.Conv, handshake.Token, handshake.Data); - sendClient.ConnectAsync().Wait(); + sendClient.ConnectAsync().Wait(); + + var sendBackConv = sendClient.GetSendbackHandshake(); + if (_kcpstatlogchan != null) + _kcpstatlogchan.LogSender = sendBackConv.Conv.ToString(); sendClient.StartDisconnected += (conv, token, data) => { - Log.Warn($"Server (conv: {_Conv}) requested to disconnect (reason: {data}), so send disconnect to client", nameof(KcpProxyBase)); + Log.Info($"Server (conv: {_Conv}) requested to disconnect (reason: {data}), so send disconnect to client", nameof(KcpProxyBase)); + _kcpstatlogchan?.LogInfo($"0|kcp|disconnect|from_server|token={token}|reason={data}"); Disconnect(conv, token, data); }; - - var sendBackConv = sendClient.GetSendbackHandshake(); + var sendBackData = sendBackConv.AsBytes(); OutputCallback?.Output(new KcpInnerBuffer(sendBackData), sendBackData.Length, false); _Conv = sendBackConv.Conv; @@ -133,7 +140,7 @@ private int InnerInput(byte[] buffer) } case ConnectionState.HANDSHAKE_CONNECT: { - Log.Erro("KcpProxy is not a client but reached HANDSHAKE_CONNECT", nameof(KcpProxyBase)); + Log.Dbug("KcpProxy is not a client but reached HANDSHAKE_CONNECT", nameof(KcpProxyBase)); break; /*var handshake = new Handshake(); try diff --git a/Tests/KcpTests/SharedLib/KCP/KcpProxy/KcpProxyClient.cs b/Tests/KcpTests/SharedLib/KCP/KcpProxy/KcpProxyClient.cs index d114c39f8..140cbbbbe 100644 --- a/Tests/KcpTests/SharedLib/KCP/KcpProxy/KcpProxyClient.cs +++ b/Tests/KcpTests/SharedLib/KCP/KcpProxy/KcpProxyClient.cs @@ -1,11 +1,11 @@ -using System.Diagnostics; +using System.Diagnostics; using System.Net; namespace csharp_Protoshift.MhyKCP.Proxy { public class KcpProxyClient : KCPClient { - public KcpProxyClient(IPEndPoint ipEp, uint conv = 0, uint token = 0, uint connectData = 0x499602D2) + public KcpProxyClient(EndPoint ipEp, uint conv = 0, uint token = 0, uint connectData = 0x499602D2) : base(ipEp) { server = new(conv, token, connectData); diff --git a/Tests/KcpTests/SharedLib/KCP/KcpProxy/KcpProxyServer.cs b/Tests/KcpTests/SharedLib/KCP/KcpProxy/KcpProxyServer.cs index 1f07b520e..6fa3846ca 100644 --- a/Tests/KcpTests/SharedLib/KCP/KcpProxy/KcpProxyServer.cs +++ b/Tests/KcpTests/SharedLib/KCP/KcpProxy/KcpProxyServer.cs @@ -1,4 +1,4 @@ -// #define KCP_PROXY_VERBOSE // not avaliable currently +// #define KCP_PROXY_VERBOSE // not avaliable currently using System.Net; using YYHEggEgg.Logger; @@ -10,9 +10,43 @@ namespace csharp_Protoshift.MhyKCP.Proxy { public class KcpProxyServer : KCPServer { - public IPEndPoint SendToEndpoint { get; } + public EndPoint SendToEndpoint { get; } + internal static BaseLogger? _kcpstatlogger; - public KcpProxyServer(IPEndPoint bindToAddress, IPEndPoint sendToAddress) +#if !PROTOSHIFT_BENCHMARK + static KcpProxyServer() + { +#if !KCP_PERFORMANCE_TEST + if (BaseLogger.LogFileExists("player.stat")) + { +#endif + var customconf = Log.GlobalConfig; +#if DEBUG + customconf.Global_Minimum_LogLevel = LogLevel.Debug; +#else + customconf.Global_Minimum_LogLevel = LogLevel.Information; +#endif + customconf.Console_Minimum_LogLevel = LogLevel.None; + _kcpstatlogger = new BaseLogger(customconf, new LogFileConfig + { + AutoFlushWriter = true, + IsPipeSeparatedFile = true, + MaximumLogLevel = LogLevel.Error, +#if DEBUG + MinimumLogLevel = LogLevel.Debug, +#else + MinimumLogLevel = LogLevel.Information, +#endif + FileIdentifier = "player.stat", + AllowAutoFallback = true, + }); +#if !KCP_PERFORMANCE_TEST + } +#endif + } +#endif + + public KcpProxyServer(IPEndPoint bindToAddress, EndPoint sendToAddress) { udpSock = new SocketUdpClient(bindToAddress, true); SendToEndpoint = sendToAddress; @@ -33,7 +67,7 @@ protected override async Task BackgroundUpdate() } catch (Exception ex) { - Log.Dbug($"BackgroundUpdate receiving packet meets error and restart: {ex}", nameof(KcpProxyServer)); + LogTrace.DbugTrace(ex, nameof(KcpProxyServer), $"BackgroundUpdate receiving packet meets error and restart. "); continue; } if (packet.Buffer.Length == Handshake.LEN) @@ -52,7 +86,8 @@ protected override async Task BackgroundUpdate() } catch (Exception ex) { - Log.Dbug($"BackgroundUpdate:Connected reached exception {ex}", nameof(KcpProxyServer)); + LogTrace.DbugTrace(ex, nameof(KcpProxyServer), + $"BackgroundUpdate:Connected reached exception. "); if (connected_conn.State != MhyKcpBase.ConnectionState.CONNECTED) { connected_clients.TryRemove(connected_conn.Conv, out _); @@ -68,9 +103,8 @@ protected override async Task BackgroundUpdate() continue; } // ip dispatch - string remoteIpString = packet.RemoteEndPoint.ToString(); KcpProxyBase conn; - if (!connecting_clients.TryGetValue(remoteIpString, out var _outconn)) + if (!connecting_clients.TryGetValue(packet.RemoteEndPoint, out var _outconn)) { // Don't allow a disconnected session if (removed_sessions.Contains(handshake.Conv)) @@ -81,9 +115,9 @@ protected override async Task BackgroundUpdate() // Oh boy! A new connection! conn = new KcpProxyBase(sendToAddress: SendToEndpoint); conn.OutputCallback = new SocketUdpKcpCallback(udpSock, packet.RemoteEndPoint); - Log.Dbug($"New connection established, remote endpoint={remoteIpString}"); + Log.Dbug($"New connection established, remote endpoint={packet.RemoteEndPoint}", nameof(KcpProxyServer)); conn.AcceptNonblock(); - connecting_clients[remoteIpString] = conn; + connecting_clients[packet.RemoteEndPoint] = conn; _ = Task.Run(async () => { try @@ -92,7 +126,7 @@ protected override async Task BackgroundUpdate() } catch { - connecting_clients.TryRemove(remoteIpString, out _); + connecting_clients.TryRemove(packet.RemoteEndPoint, out _); } }); } @@ -107,7 +141,8 @@ protected override async Task BackgroundUpdate() } catch (Exception ex) { - Log.Dbug($"BackgroundUpdate:NewConnection reached exception {ex}", nameof(KcpProxyServer)); + LogTrace.DbugTrace(ex, nameof(KcpProxyServer), + $"BackgroundUpdate:NewConnection reached exception. "); } } else if (packet.Buffer.Length >= KcpConst.IKCP_OVERHEAD) // conv dispatch @@ -142,6 +177,7 @@ public void StartProxy(ProxyHandlers handlers) { var ret = Accept(); Log.Info($"New connection (conv={ret.Connection.Conv}, token={ret.Connection.Token}) from {ret.RemoteEndpoint}.", nameof(KcpProxyServer)); + _kcpstatlogger?.Info($"0|kcp|connect|token={ret.Connection.Token}|ip={ret.RemoteEndpoint}", ret.Connection.Conv.ToString()); handlers.SessionCreated?.Invoke(ret.Connection.Conv, ret.RemoteEndpoint); _ = Task.Run(() => HandleServer((KcpProxyBase)ret.Connection, handlers)); @@ -149,7 +185,7 @@ public void StartProxy(ProxyHandlers handlers) } catch (Exception ex) { - Log.Erro($"Internal error: {ex}", nameof(StartProxy)); + LogTrace.ErroTrace(ex, nameof(StartProxy), $"Internal error. "); } } } @@ -298,6 +334,28 @@ public void SendPacketToServer(uint conv, byte[] content) conn.sendClient.Send(content); #pragma warning restore CS8602 // 解引用可能出现空引用。 } + + /// + /// Kick a specified session and send disconnect packet to client & server. + /// + /// + /// The disconnect reason that will be sent to client. Default is ENET_SERVER_KICK (The connection to the server has been lost). + /// The disconnect reason that will be sent to server. Default is ENET_CLIENT_CLOSE. + /// + public void KickSession(uint conv, uint client_reason = 5, uint server_reason = 1) + { + if (!connected_clients.ContainsKey(conv)) + { + throw new KeyNotFoundException($"The specified session (conv: {conv}) does not exist."); + } + var conn_client = (KcpProxyBase)connected_clients[conv]; + var conn_server = conn_client.sendClient; + + _kcpstatlogger?.Info($"0|kcp|disconnect|proxy_kick(client)|reason={client_reason}", conv.ToString()); + _kcpstatlogger?.Info($"0|kcp|disconnect|proxy_kick(server)|reason={server_reason}", conv.ToString()); + conn_client.Disconnect(data: client_reason); + conn_server?.Disconnect(data: server_reason); + } #endregion } } diff --git a/Tests/KcpTests/SharedLib/KCP/KcpProxy/ProxyHandlers.cs b/Tests/KcpTests/SharedLib/KCP/KcpProxy/ProxyHandlers.cs index 42a82ebb2..91f274b63 100644 --- a/Tests/KcpTests/SharedLib/KCP/KcpProxy/ProxyHandlers.cs +++ b/Tests/KcpTests/SharedLib/KCP/KcpProxy/ProxyHandlers.cs @@ -1,18 +1,18 @@ -using System.Net; - -namespace csharp_Protoshift.MhyKCP.Proxy -{ - public class ProxyHandlers - { - public Action? SessionCreated; - public Action? SessionDestroyed; - public Func OnServerPacketArrival - = (data, conv) => data; - public Func OnClientPacketArrival - = (data, conv) => data; - public Func ServerPacketOrdered - = (_, _) => true; - public Func ClientPacketOrdered - = (_, _) => true; - } +using System.Net; + +namespace csharp_Protoshift.MhyKCP.Proxy +{ + public class ProxyHandlers + { + public Action? SessionCreated; + public Action? SessionDestroyed; + public Func OnServerPacketArrival + = (data, conv) => data; + public Func OnClientPacketArrival + = (data, conv) => data; + public Func ServerPacketOrdered + = (_, _) => true; + public Func ClientPacketOrdered + = (_, _) => true; + } } \ No newline at end of file diff --git a/Tests/KcpTests/SharedLib/KCP/MhyKCP/KCPClient.cs b/Tests/KcpTests/SharedLib/KCP/MhyKCP/KCPClient.cs index 77065effd..49e477f6d 100644 --- a/Tests/KcpTests/SharedLib/KCP/MhyKCP/KCPClient.cs +++ b/Tests/KcpTests/SharedLib/KCP/MhyKCP/KCPClient.cs @@ -1,6 +1,6 @@ using System.Net; -using YYHEggEgg.Logger; using csharp_Protoshift.SpecialUdp; +using YYHEggEgg.Logger; namespace csharp_Protoshift.MhyKCP { @@ -11,12 +11,12 @@ public class KCPClient : IDisposable protected SocketUdpClient udpSock; private bool _Closed = false; protected MhyKcpBase server; - protected IPEndPoint remoteAddress; + protected EndPoint remoteAddress; protected SingleThreadAssert _recvlock = new($"{nameof(KCPClient)}_{nameof(Receive)}"), _updatelock = new($"{nameof(KCPClient)}_{nameof(BackgroundUpdate)}"); - public KCPClient(IPEndPoint ipEp) + public KCPClient(EndPoint ipEp) { udpSock = new SocketUdpClient(true); //udpSock = new(); @@ -76,7 +76,7 @@ protected virtual async Task BackgroundUpdate() } catch (Exception ex) { - Log.Erro($"Update fail: {ex}", nameof(KCPClient)); + LogTrace.ErroTrace(ex, nameof(KCPClient), $"Update fail. "); _Closed = true; server.Dispose(); } diff --git a/Tests/KcpTests/SharedLib/KCP/MhyKCP/KCPServer.cs b/Tests/KcpTests/SharedLib/KCP/MhyKCP/KCPServer.cs index cd5b356c6..5e6975a5c 100644 --- a/Tests/KcpTests/SharedLib/KCP/MhyKCP/KCPServer.cs +++ b/Tests/KcpTests/SharedLib/KCP/MhyKCP/KCPServer.cs @@ -12,8 +12,7 @@ public class KCPServer : IDisposable protected SocketUdpClient udpSock; protected bool _Closed = false; - // string is the ToString() form of IPEndPoint - protected ConcurrentDictionary connecting_clients; + protected ConcurrentDictionary connecting_clients; protected ConcurrentDictionary connected_clients; protected ConcurrentQueue newConnections; protected ConcurrentBag removed_sessions; @@ -83,9 +82,8 @@ protected virtual async Task BackgroundUpdate() continue; } // ip dispatch - string remoteIpString = packet.RemoteEndPoint.ToString(); MhyKcpBase conn; - if (!connecting_clients.TryGetValue(remoteIpString, out var _outconn)) + if (!connecting_clients.TryGetValue(packet.RemoteEndPoint, out var _outconn)) { // Don't allow a disconnected session if (removed_sessions.Contains(handshake.Conv)) continue; @@ -93,7 +91,7 @@ protected virtual async Task BackgroundUpdate() conn = new MhyKcpBase(); conn.OutputCallback = new SocketUdpKcpCallback(udpSock, packet.RemoteEndPoint); conn.AcceptNonblock(); - connecting_clients[remoteIpString] = conn; + connecting_clients[packet.RemoteEndPoint] = conn; _ = Task.Run(async () => { try @@ -102,7 +100,7 @@ protected virtual async Task BackgroundUpdate() } catch { - connecting_clients.TryRemove(remoteIpString, out _); + connecting_clients.TryRemove(packet.RemoteEndPoint, out _); } }); } diff --git a/Tests/KcpTests/SharedLib/KCP/MhyKCP/KcpInnerBuffer.cs b/Tests/KcpTests/SharedLib/KCP/MhyKCP/KcpInnerBuffer.cs index e1799eb12..20756fe95 100644 --- a/Tests/KcpTests/SharedLib/KCP/MhyKCP/KcpInnerBuffer.cs +++ b/Tests/KcpTests/SharedLib/KCP/MhyKCP/KcpInnerBuffer.cs @@ -1,4 +1,4 @@ -using System.Buffers; +using System.Buffers; namespace csharp_Protoshift.MhyKCP { diff --git a/Tests/KcpTests/SharedLib/KCP/MhyKCP/KcpPacketAudit.cs b/Tests/KcpTests/SharedLib/KCP/MhyKCP/KcpPacketAudit.cs index 9d4d2f3cd..9c3f1e2aa 100644 --- a/Tests/KcpTests/SharedLib/KCP/MhyKCP/KcpPacketAudit.cs +++ b/Tests/KcpTests/SharedLib/KCP/MhyKCP/KcpPacketAudit.cs @@ -1,9 +1,10 @@ -#define MIHOMO_KCP +#define MIHOMO_KCP using System.Buffers; using System.Buffers.Binary; using System.Collections.Concurrent; using System.Diagnostics; +using System.IO.Hashing; using System.Net.Sockets.Kcp; using System.Text; using YYHEggEgg.Logger; @@ -98,6 +99,10 @@ private static void BackgroundUpdate() offset += sizeof(byte) + sizeof(ushort) + sizeof(uint) * 3; uint len = BinaryPrimitives.ReadUInt32LittleEndian(segment.Slice(offset)); offset += sizeof(uint); +#if BYTE_CHECK_MODE + uint byteCheckCode = BinaryPrimitives.ReadUInt32LittleEndian(segment.Slice(offset)); + offset += sizeof(uint); +#endif Debug.Assert(offset == KcpConst.IKCP_OVERHEAD); #endregion #region Content Length Check @@ -115,6 +120,16 @@ private static void BackgroundUpdate() Convert.ToHexString(segment.Slice( (int)(offset + len), (int)(contentLen - len)))); } +#if BYTE_CHECK_MODE && !CORRUPT_PACKET + else + { + var checksum = Crc32.HashToUInt32(segment.Slice(offset)); + if (byteCheckCode != checksum) + { + exceptions.Add($"Segment {i} byte check (CRC32) failed, expected: {byteCheckCode}, actual: {checksum}."); + } + } +#endif #endregion } } @@ -149,7 +164,7 @@ private static void BackgroundUpdate() #if MIHOMO_KCP offset += sizeof(uint) * 2; #else - offset += sizeof(uint); + offset += sizeof(uint); #endif byte cmd = segment[offset]; offset += sizeof(byte); @@ -165,6 +180,10 @@ private static void BackgroundUpdate() offset += sizeof(uint); uint len = BinaryPrimitives.ReadUInt32LittleEndian(segment.Slice(offset)); offset += sizeof(uint); +#if BYTE_CHECK_MODE + uint byteCheckCode = BinaryPrimitives.ReadUInt32LittleEndian(segment.Slice(offset)); + offset += sizeof(uint); +#endif Debug.Assert(offset == KcpConst.IKCP_OVERHEAD); #endregion #region Output segment @@ -181,7 +200,8 @@ private static void BackgroundUpdate() } catch (Exception ex) { - Log.Erro($"Error occured when handling audit kcp packet: {ex}", nameof(KcpPacketAudit)); + LogTrace.ErroTrace(ex, nameof(KcpPacketAudit), + $"Error occured when handling audit kcp packet. "); } } } diff --git a/Tests/KcpTests/SharedLib/KCP/MhyKCP/MhyKcpBase.cs b/Tests/KcpTests/SharedLib/KCP/MhyKCP/MhyKcpBase.cs index 5c5c357a3..ab530c3e2 100644 --- a/Tests/KcpTests/SharedLib/KCP/MhyKCP/MhyKcpBase.cs +++ b/Tests/KcpTests/SharedLib/KCP/MhyKCP/MhyKcpBase.cs @@ -1,4 +1,4 @@ -// #define KCP_INNER_LOG +// #define KCP_INNER_LOG // #define KCP_EXPORT_PACKET_RECORD using System.Net.Sockets; @@ -54,6 +54,11 @@ public enum ConnectionState protected object cskcp_recvLock = "R.I.P YSFreedom"; protected object cskcp_sndLock = "Yolmiya"; protected long startTime; + /// + /// Used for assigning conv for new connections. + /// Use to operate with it. + /// + protected static uint _currentConv = 1000; public uint ConnectData { get; protected set; } public OuterCode.UniqueIDManager _uniqueID = new(nameof(MhyKcpBase)); @@ -75,6 +80,15 @@ public void Initialize() cskcpHandle = new(_Conv, _Token, OutputCallback); _State = ConnectionState.CONNECTED; +#if BYTE_CHECK_MODE +#if CORRUPT_PACKET + bool corrupt = true; +#else + bool corrupt = false; +#endif + cskcpHandle.SetByteCheck(2, corrupt); +#endif + // Added // IKCP.ikcp_nodelay(ikcpHandle, 1, 10, 2, 1); // modified because mhy is using far more aggressive code, or 力大砖飞 mode @@ -187,7 +201,7 @@ public virtual int Input(byte[] buffer) { // Log.Dbug($"HandShakeWaitNotify, buf = {Convert.ToHexString(buffer)}", nameof(MhyKcpBase)); handshake.Decode(buffer, Handshake.MAGIC_CONNECT); - _Conv = (uint)(MonotonicTime.Now & 0xFFFFFFFF); + _Conv = Interlocked.Increment(ref _currentConv); _Token = 0xFFCCEEBB ^ (uint)((MonotonicTime.Now >> 32) & 0xFFFFFFFF); var sendBackConv = new Handshake(Handshake.MAGIC_SEND_BACK_CONV, _Conv, _Token).AsBytes(); @@ -366,7 +380,8 @@ public async Task BackgroundUpdate() catch (Exception ex) { _updatelock.Exit(); - Log.Erro($"MhyKcpBase Background Check/Update exception and restart: {ex}", nameof(MhyKcpBase)); + LogTrace.ErroTrace(ex, nameof(MhyKcpBase), + $"MhyKcpBase Background Check/Update exception and restart. "); _ = Task.Run(BackgroundUpdate); } } diff --git a/Tests/KcpTests/SharedLib/KCP/MhyKCP/UdpKcpCallback.cs b/Tests/KcpTests/SharedLib/KCP/MhyKCP/UdpKcpCallback.cs index 5e63ccce1..a234190a9 100644 --- a/Tests/KcpTests/SharedLib/KCP/MhyKCP/UdpKcpCallback.cs +++ b/Tests/KcpTests/SharedLib/KCP/MhyKCP/UdpKcpCallback.cs @@ -1,6 +1,5 @@ -#define KCP_PACKET_AUDIT +// #define KCP_PACKET_AUDIT -using csharp_Protoshift.Obsoleted.SpecialUdp; using csharp_Protoshift.SpecialUdp; using System.Buffers; using System.Diagnostics; @@ -31,25 +30,6 @@ public void Output(IMemoryOwner buffer, int avalidLength, bool isKcpPacket } } - [Obsolete] - public class ConcurrentUdpKcpCallback : IKcpCallback - { - private readonly ConcurrentUdpClient udpSock; - private readonly IPEndPoint? ipEp; - - public ConcurrentUdpKcpCallback(ConcurrentUdpClient udpSock, IPEndPoint? ipEp = null) - { - this.udpSock = udpSock; - this.ipEp = ipEp; - } - - public async void Output(IMemoryOwner buffer, int avalidLength, bool isKcpPacket = true) - { - await udpSock.SendAsync(buffer.Memory.Slice(0, avalidLength), ipEp); - buffer.Dispose(); - } - } - public class SocketUdpKcpCallback : IKcpCallback { private readonly SocketUdpClient udpSock; @@ -64,11 +44,15 @@ public SocketUdpKcpCallback(SocketUdpClient udpSock, IPEndPoint? ipEp = null) public void Output(IMemoryOwner buffer, int avalidLength, bool isKcpPacket = true) { // Stopwatch udpwatch = Stopwatch.StartNew(); - // DateTime req_SendTime = DateTime.Now; +#if KCP_PACKET_AUDIT + DateTime req_SendTime = DateTime.Now; +#endif // udpSock.SendToAsync(buffer.Memory.Slice(0, avalidLength), ipEp).Wait(); udpSock.SendTo(buffer.Memory.Span.Slice(0, avalidLength), ipEp); - // if (isKcpPacket) - // KcpPacketAudit.PushPacket(req_SendTime, buffer.Memory, avalidLength); +#if KCP_PACKET_AUDIT + if (isKcpPacket) + KcpPacketAudit.PushPacket(req_SendTime, buffer.Memory, avalidLength); +#endif buffer.Dispose(); // udpwatch.Stop(); // Log.Dbug($"SocketUdpKcpCallback output elapsed {udpwatch.Elapsed.TotalMilliseconds}ms."); diff --git a/Tests/KcpTests/SharedLib/KCP/SingleThreadAssert.cs b/Tests/KcpTests/SharedLib/KCP/SingleThreadAssert.cs index 70d055d62..15037ea68 100644 --- a/Tests/KcpTests/SharedLib/KCP/SingleThreadAssert.cs +++ b/Tests/KcpTests/SharedLib/KCP/SingleThreadAssert.cs @@ -1,4 +1,4 @@ -using YYHEggEgg.Logger; +using YYHEggEgg.Logger; namespace csharp_Protoshift { diff --git a/Tests/KcpTests/SharedLib/KCP/SpecialUdp/Obsoleted/ConcurrentUdpClient.cs b/Tests/KcpTests/SharedLib/KCP/SpecialUdp/Obsoleted/ConcurrentUdpClient.cs deleted file mode 100644 index 47780ed4a..000000000 --- a/Tests/KcpTests/SharedLib/KCP/SpecialUdp/Obsoleted/ConcurrentUdpClient.cs +++ /dev/null @@ -1,495 +0,0 @@ -// Generated by ChatGPT -#define SPECIAL_UDP_VERBOSE -#define SPECIAL_UDP_WARNING - -#pragma warning disable CS8604 // 引用类型参数可能为 null。 -#pragma warning disable CS8629 // 可为 null 的值类型可为 null。 -#pragma warning disable CS8625 // 无法将 null 字面量转换为非 null 的引用类型。 - -using System.Collections.Concurrent; -using System.Diagnostics; -using System.Net; -using System.Net.Sockets; -using YYHEggEgg.Logger; - -// Obsoleted for bad performance -namespace csharp_Protoshift.Obsoleted.SpecialUdp -{ - public sealed class ConcurrentUdpClient : IDisposable - { - #region Packet Utils - private enum UdpInvoke - { - /// - /// Equal to . - /// - SendConnected = 1, - /// - /// Equal to . - /// - SendAnyEndpoint = 2, - /// - /// Equal to . - /// - SendAsyncConnected = 11, - /// - /// Equal to . - /// - SendAsyncAnyEndpoint = 12, - /// - /// Equal to . - /// - SendAsyncMemoryConnected = 13, - /// - /// Equal to . - /// - SendAsyncMemoryAnyEndpoint = 14, - /// - /// Equal to . - /// - Receive = 101, - /// - /// Equal to . - /// - ReceiveAsync = 111 - } - - private class UdpSendPacket - { - public byte[]? data; - public ReadOnlyMemory? memoryData; - public int? bytes; - public IPEndPoint? endpoint; - public Exception? ex; - public int? rtn; - public UdpInvoke invoke; - - public UdpSendPacket(byte[] data, int bytes, IPEndPoint? endpoint, UdpInvoke invoke) - { - this.data = data; - this.bytes = bytes; - this.endpoint = endpoint; - this.invoke = invoke; - } - - public UdpSendPacket(ReadOnlyMemory memoryData, IPEndPoint? endpoint, UdpInvoke invoke) - { - this.memoryData = memoryData; - this.endpoint = endpoint; - this.invoke = invoke; - } - } - - private class UdpReceivePacket - { - public UdpReceiveResult? receiveData; - public Exception? ex; - public UdpInvoke invoke; - - public UdpReceivePacket(UdpInvoke invoke) - { - this.invoke = invoke; - } - } - #endregion - - #region BeforeHand Initialize - // 构造函数 - public ConcurrentUdpClient() - { - // 初始化UdpClient实例 - baseClient = new UdpClient(); -#if SPECIAL_UDP_VERBOSE - Log.Info("baseClient initialized with normal paramters.", "ConcurrentUdpClient"); -#endif - // 启动后台更新任务 - Task.Run(BackgroundUpdate); - } - - public ConcurrentUdpClient(IPEndPoint bindAddress) - { - baseClient = new UdpClient(bindAddress); -#if SPECIAL_UDP_VERBOSE - Log.Info($"baseClient initialized with ipEp:{bindAddress}.", "ConcurrentUdpClient"); -#endif - Task.Run(BackgroundUpdate); - } - - public void Connect(IPEndPoint ipEp) - { - ConnectedAddress = ipEp; -#if SPECIAL_UDP_VERBOSE - Log.Info($"baseClient Connected to ipEp:{ipEp}.", "ConcurrentUdpClient"); -#endif - baseClient.Connect(ipEp); - } - #endregion - - // 发送队列 - private ConcurrentQueue qSend = new(); - // 接收队列 - private ConcurrentQueue qRecv = new(); - // 内部使用的UdpClient实例 - private UdpClient baseClient; - public IPEndPoint? ConnectedAddress { get; set; } - - public int RefreshMilliseconds = 10; - - #region Receive Packet - public byte[] Receive(ref IPEndPoint fromip) - { -#if SPECIAL_UDP_VERBOSE - Log.Info($"User tried to invoke Receive().", "ConcurrentUdpClient"); -#endif - var handle = new UdpReceivePacket(UdpInvoke.Receive); - qRecv.Enqueue(handle); - while (true) - { - if (handle.receiveData != null) - { -#if SPECIAL_UDP_VERBOSE - Log.Info($"Successfully received {((UdpReceiveResult)handle.receiveData).Buffer.Length} bytes in Receive().", "ConcurrentUdpClient"); -#endif - fromip = ((UdpReceiveResult)handle.receiveData).RemoteEndPoint; - return ((UdpReceiveResult)handle.receiveData).Buffer; - } - if (handle.ex != null) throw handle.ex; - Task.Delay(RefreshMilliseconds).Wait(); - } - } - - public async Task ReceiveAsync() - { -#if SPECIAL_UDP_VERBOSE - Log.Info($"User tried to invoke ReceiveAsync().", "ConcurrentUdpClient"); -#endif - var handle = new UdpReceivePacket(UdpInvoke.Receive); - qRecv.Enqueue(handle); - while (true) - { - if (handle.receiveData != null) - { -#if SPECIAL_UDP_VERBOSE - Log.Info($"Successfully received {((UdpReceiveResult)handle.receiveData).Buffer.Length} bytes in ReceiveAsync().", "ConcurrentUdpClient"); -#endif - return (UdpReceiveResult)handle.receiveData; - } - if (handle.ex != null) throw handle.ex; - await Task.Delay(RefreshMilliseconds); - } - } - #endregion - - #region Send Packet - public int Send(byte[] data, int? bytes = null, IPEndPoint? endpoint = null) - { -#if SPECIAL_UDP_VERBOSE - Log.Info($"User tried to invoke Send() with {data.Length} bytes to {endpoint}.", "ConcurrentUdpClient"); -#endif - if (endpoint == null && ConnectedAddress == null) - // WSAENOTCONN, socket not connected - throw new SocketException(10057); - bytes ??= data.Length; - var handle = new UdpSendPacket(data, (int)bytes, endpoint, - endpoint == null ? UdpInvoke.SendConnected : UdpInvoke.SendAnyEndpoint); - qSend.Enqueue(handle); - while (true) - { - if (handle.rtn != null) - { - if (handle.ex != null) - { -#if SPECIAL_UDP_VERBOSE - Log.Dbug("Invoke Send() throwed an exception.", "ConcurrentUdpClient"); -#endif - // 如果有异常则抛出 - throw handle.ex; - } -#if SPECIAL_UDP_VERBOSE - Log.Dbug($"Invoke Send() returned {handle.rtn}.", "ConcurrentUdpClient"); -#endif - return (int)handle.rtn; - } - Task.Delay(RefreshMilliseconds).Wait(); - } - } - - public async Task SendAsync(byte[] data, int? bytes = null, IPEndPoint? endpoint = null) - { -#if SPECIAL_UDP_VERBOSE - Log.Info($"User tried to invoke SendAsync() with {data.Length} bytes to {endpoint}.", "ConcurrentUdpClient"); -#endif - if (endpoint == null && ConnectedAddress == null) - // WSAENOTCONN, socket not connected - throw new SocketException(10057); - bytes ??= data.Length; - var handle = new UdpSendPacket(data, (int)bytes, endpoint, - endpoint == null ? UdpInvoke.SendAsyncConnected : UdpInvoke.SendAsyncAnyEndpoint); - qSend.Enqueue(handle); - while (true) - { - if (handle.rtn != null) - { - if (handle.ex != null) - { -#if SPECIAL_UDP_VERBOSE - Log.Dbug("Invoke SendAsync() throwed an exception.", "ConcurrentUdpClient"); -#endif - // 如果有异常则抛出 - throw handle.ex; - } -#if SPECIAL_UDP_VERBOSE - Log.Dbug($"Invoke SendAsync() returned {handle.rtn}.", "ConcurrentUdpClient"); -#endif - return (int)handle.rtn; - } - await Task.Delay(10); - } - } - - public async Task SendAsync(ReadOnlyMemory data, IPEndPoint? endpoint = null) - { -#if SPECIAL_UDP_VERBOSE - Log.Info($"User tried to invoke SendAsync() with {data.Length} bytes to {endpoint}.", "ConcurrentUdpClient"); -#endif - if (endpoint == null && ConnectedAddress == null) - // WSAENOTCONN, socket not connected - throw new SocketException(10057); - var handle = new UdpSendPacket(data, endpoint, - endpoint == null ? UdpInvoke.SendAsyncMemoryConnected : UdpInvoke.SendAsyncMemoryAnyEndpoint); - qSend.Enqueue(handle); - while (true) - { - if (handle.rtn != null) - { - if (handle.ex != null) - { -#if SPECIAL_UDP_VERBOSE - Log.Dbug("Invoke SendAsync() throwed an exception.", "ConcurrentUdpClient"); -#endif - // 如果有异常则抛出 - throw handle.ex; - } -#if SPECIAL_UDP_VERBOSE - Log.Dbug($"Invoke SendAsync() returned {handle.rtn}.", "ConcurrentUdpClient"); -#endif - return (int)handle.rtn; - } - await Task.Delay(10); - } - } - #endregion - - #region Background Handler - // 后台更新任务 - private async Task BackgroundUpdate() - { - if (qSend.TryDequeue(out UdpSendPacket? sendpacket)) - { -#if SPECIAL_UDP_VERBOSE - Stopwatch watch = new(); - bool exHappened = false; - watch.Start(); -#endif - try - { - // 发送数据 - switch (sendpacket.invoke) - { - case UdpInvoke.SendConnected: - sendpacket.rtn = baseClient.Send( - sendpacket.data, (int)sendpacket.bytes); - break; - case UdpInvoke.SendAnyEndpoint: - sendpacket.rtn = baseClient.Send( - sendpacket.data, (int)sendpacket.bytes, sendpacket.endpoint); - break; - case UdpInvoke.SendAsyncConnected: - sendpacket.rtn = await baseClient.SendAsync( - sendpacket.data, (int)sendpacket.bytes); - break; - case UdpInvoke.SendAsyncAnyEndpoint: - sendpacket.rtn = await baseClient.SendAsync( - sendpacket.data, (int)sendpacket.bytes, sendpacket.endpoint); - break; - case UdpInvoke.SendAsyncMemoryConnected: - sendpacket.rtn = await baseClient.SendAsync( - (ReadOnlyMemory)sendpacket.memoryData); - break; - case UdpInvoke.SendAsyncMemoryAnyEndpoint: - sendpacket.rtn = await baseClient.SendAsync( - (ReadOnlyMemory)sendpacket.memoryData, sendpacket.endpoint); - break; - default: - Log.Erro($"Receive packet accidently ran into send queue," + - $"Invoke:{sendpacket.invoke}, packet[{sendpacket.bytes}]:" + - Convert.ToHexString(sendpacket.data), "ConcurrentUdpClient"); - break; - } - } - catch (Exception ex) - { - sendpacket.ex = ex; - sendpacket.rtn = -1; -#if SPECIAL_UDP_VERBOSE - exHappened = true; -#endif - } -#if SPECIAL_UDP_VERBOSE - watch.Stop(); - Log.Dbug($"Handle qSend {(exHappened ? "(Exception)" : string.Empty)} " + - $"costed {watch.ElapsedMilliseconds}ms.", "ConcurrentUdpClient"); -#endif - } - else if (baseClient.Available > 0 - && qRecv.TryPeek(out UdpReceivePacket? receivepacket)) - { -#if SPECIAL_UDP_VERBOSE - Stopwatch watch = new(); - bool exHappened = false; - bool timeout = false; - watch.Start(); -#endif - switch (receivepacket.invoke) - { - case UdpInvoke.Receive: - try - { - IPEndPoint ipEp = new(IPAddress.Loopback, 0); -#if SPECIAL_UDP_WARNING || SPECIAL_UDP_VERBOSE - Stopwatch cancelwatch = new(); - cancelwatch.Start(); -#endif - byte[] buf = baseClient.Receive(ref ipEp); -#if SPECIAL_UDP_WARNING || SPECIAL_UDP_VERBOSE - cancelwatch.Stop(); - if (cancelwatch.ElapsedMilliseconds > 40) - { - Log.Warn("Syncronous Receive() stuck for " + - $"{cancelwatch.ElapsedMilliseconds}ms!", "ConcurrentUdpClient"); -#endif -#if SPECIAL_UDP_VERBOSE - timeout = true; -#endif -#if SPECIAL_UDP_WARNING || SPECIAL_UDP_VERBOSE - } -#endif - receivepacket.receiveData = new(buf, ipEp); - qRecv.TryDequeue(out _); -#if SPECIAL_UDP_VERBOSE - Log.Dbug($"Background qRecv handle received {buf.Length} bytes.", "ConcurrentUdpClient"); -#endif - } - catch (Exception ex) - { - receivepacket.ex = ex; - qRecv.TryDequeue(out _); -#if SPECIAL_UDP_VERBOSE - exHappened = true; -#endif - } - break; - case UdpInvoke.ReceiveAsync: - var cancellationTokenSource = new CancellationTokenSource(); - var captureToken = cancellationTokenSource.Token; - try - { - cancellationTokenSource.CancelAfter(50); - UdpReceiveResult res = await baseClient.ReceiveAsync(captureToken); - receivepacket.receiveData = res; - qRecv.TryDequeue(out _); -#if SPECIAL_UDP_VERBOSE - Log.Dbug($"Background qRecv handle(async) received {res.Buffer.Length} bytes.", "ConcurrentUdpClient"); -#endif - } - catch (OperationCanceledException) - { -#if SPECIAL_UDP_WARNING || SPECIAL_UDP_VERBOSE - Log.Warn("Asyncronous ReceiveAsync() timeout of 50ms and canceled!", "ConcurrentUdpClient"); -#endif -#if SPECIAL_UDP_VERBOSE - timeout = true; -#endif - } - catch (Exception ex) - { - receivepacket.ex = ex; - qRecv.TryDequeue(out _); -#if SPECIAL_UDP_VERBOSE - exHappened = true; -#endif - } - break; - default: - Log.Erro("Send packet accidently ran into receive queue," + - $"Invoke:{receivepacket.invoke}", "ConcurrentUdpClient"); - qRecv.TryDequeue(out _); - break; - } -#if SPECIAL_UDP_VERBOSE - watch.Stop(); - Log.Dbug($"Handle qRecv {(exHappened ? "(Exception)" : string.Empty)} " + - $"costed {watch.ElapsedMilliseconds}ms." + - (timeout ? " (timed out) " : string.Empty), "ConcurrentUdpClient"); -#endif - } - else - { - // 等待一段时间,降低CPU占用 - await Task.Delay(5); - } - await Task.Run(BackgroundUpdate); - } - #endregion - - #region IDisposeable - /* Generated by ChatGPT - * 在上面的代码中,我们实现了Close()、Dispose()和Protected Dispose(bool)方法,并且实现了IDisposeable接口。 - * 它们的作用如下: - - * - Close()方法:关闭基础UDP客户端。 - * - Dispose()方法:释放托管资源和非托管资源。 - * 这个方法由垃圾回收器调用,也可以由开发人员主动调用。 - * 在这里,我们在调用Dispose()方法时通过调用Dispose(true)方法释放托管资源, - * 并抑制GC.SuppressFinalize(this)来防止使用Finalizer。 - * - Protected Dispose(bool)方法:释放非托管资源。 - * 如果disposing为true,则还会释放托管资源。 - - * 需要注意的是,我们在类定义中还定义了一个Finalizer(也就是析构函数)。 - * 这个Finalizer中调用了Dispose(false)方法,以释放非托管资源。 - * 这样做是为了确保即使开发人员没有调用Dispose()方法,也能在对象被垃圾回收前释放非托管资源。 - */ - public void Close() - { - baseClient.Close(); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - private void Dispose(bool disposing) - { - if (disposing) - { - if (baseClient != null) - { - baseClient.Dispose(); - baseClient = null; - } - } - } - - ~ConcurrentUdpClient() - { - Dispose(false); - } - #endregion - } -} - -#pragma warning restore CS8604 // 引用类型参数可能为 null。 -#pragma warning restore CS8629 // 可为 null 的值类型可为 null。 -#pragma warning restore CS8625 // 无法将 null 字面量转换为非 null 的引用类型。 \ No newline at end of file diff --git a/Tests/KcpTests/SharedLib/KCP/SpecialUdp/SocketUdpClient.cs b/Tests/KcpTests/SharedLib/KCP/SpecialUdp/SocketUdpClient.cs index 0b52ab6e1..2e8dfc862 100644 --- a/Tests/KcpTests/SharedLib/KCP/SpecialUdp/SocketUdpClient.cs +++ b/Tests/KcpTests/SharedLib/KCP/SpecialUdp/SocketUdpClient.cs @@ -1,4 +1,4 @@ -// #define SOCKET_UDP_VERBOSE +// #define SOCKET_UDP_VERBOSE // #define SOCKET_UDP_PACKET_CONTENT_VERBOSE // #define SOCKET_UDP_PACKET_CONTENT_VERBOSE_SYNCRONOUS @@ -13,7 +13,7 @@ namespace csharp_Protoshift.SpecialUdp public class SocketUdpClient : IDisposable { private readonly Socket _socket; - private IPEndPoint? _defaultEndpoint; + private EndPoint? _defaultEndpoint; private string? _defaultEndpointString; public const int UDP_MAX_PACKET_SIZE = 65507; @@ -23,14 +23,17 @@ public class SocketUdpClient : IDisposable private byte[]? STABuffer; private SingleThreadAssert? _rcvSTAAssert; + private readonly bool isIpv6Socket; + /// /// Initializer. /// /// means you confirm that you're invoking the in only one thread. If you give it true but not ensure that, terrible thing will happen. - public SocketUdpClient(bool singlethread_receiving = false) + public SocketUdpClient(bool singlethread_receiving = false, bool isIpv6Socket = false) { _socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - _socket.Bind(new IPEndPoint(IPAddress.Any, 0)); + this.isIpv6Socket = isIpv6Socket; + _socket.Bind(DefaultEndPoint); _arrayPool = ArrayPool.Shared; _isSTABuffer = singlethread_receiving; if (_isSTABuffer) @@ -38,16 +41,23 @@ public SocketUdpClient(bool singlethread_receiving = false) STABuffer = new byte[UDP_MAX_PACKET_SIZE]; _rcvSTAAssert = new($"{nameof(SocketUdpClient)}_{ReceiveFrom}"); } + } public SocketUdpClient(IPEndPoint ipEndPoint, bool singlethread_receiving = false) { if (ipEndPoint.AddressFamily == AddressFamily.InterNetwork) + { _socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + isIpv6Socket = false; + } else if (ipEndPoint.AddressFamily == AddressFamily.InterNetworkV6) + { _socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp); + isIpv6Socket = true; + } else throw new ArgumentException( - "IPEndPoint is probably not a valid IP address or used, please check the input", + "IPEndPoint is probably not a valid IP address or used, please check the input", nameof(ipEndPoint)); _socket.Bind(ipEndPoint); _arrayPool = ArrayPool.Shared; @@ -59,9 +69,11 @@ public SocketUdpClient(IPEndPoint ipEndPoint, bool singlethread_receiving = fals } } - public void Connect(IPEndPoint ipEndPoint) + private IPEndPoint DefaultEndPoint => new IPEndPoint(isIpv6Socket ? IPAddress.IPv6Any : IPAddress.Any, 0); + + public void Connect(EndPoint endPoint) { - _defaultEndpoint = ipEndPoint; + _defaultEndpoint = endPoint; _defaultEndpointString = _defaultEndpoint.ToString(); } @@ -85,7 +97,7 @@ public SocketUdpReceiveResult ReceiveFrom() var stopwatch = new System.Diagnostics.Stopwatch(); stopwatch.Start(); #endif - EndPoint _tmpendp = new IPEndPoint(IPAddress.Any, 0); + EndPoint _tmpendp = DefaultEndPoint; var avalidlength = _socket.ReceiveFrom(buffer, SocketFlags.None, ref _tmpendp); @@ -132,7 +144,7 @@ public SocketUdpReceiveResult ReceiveFrom() } catch (Exception ex) { - Log.Warn($"Failed to receive packet: {ex}", nameof(SocketUdpClient)); + LogTrace.WarnTrace(ex, nameof(SocketUdpClient), $"Failed to receive packet. "); throw; } finally @@ -155,7 +167,7 @@ public async Task ReceiveFromAsync() #pragma warning restore CS8600, CS8602 } else buffer = _arrayPool.Rent(UDP_MAX_PACKET_SIZE); - SocketUdpReceiveResult receiveResult = new(); + SocketUdpReceiveResult receiveResult = new() { RemoteEndPoint = DefaultEndPoint }; try { @@ -210,7 +222,7 @@ public async Task ReceiveFromAsync() } catch (Exception ex) { - Log.Warn($"Failed to receive packet: {ex}", nameof(SocketUdpClient)); + LogTrace.WarnTrace(ex, nameof(SocketUdpClient), $"Failed to receive packet. "); throw; } finally @@ -224,7 +236,7 @@ public async Task ReceiveFromAsync() #endregion #region SendTo - public int SendTo(byte[] buffer, IPEndPoint? ipEndPoint = null) + public int SendTo(byte[] buffer, EndPoint? ipEndPoint = null) { if (ipEndPoint == null && _defaultEndpoint == null) { @@ -264,12 +276,12 @@ public int SendTo(byte[] buffer, IPEndPoint? ipEndPoint = null) } catch (Exception ex) { - Log.Erro($"Failed to send packet: {ex.Message}", nameof(SocketUdpClient)); + LogTrace.InfoTrace(ex, nameof(SocketUdpClient), $"Failed to send packet. "); throw; } } - public int SendTo(ReadOnlySpan buffer, IPEndPoint? ipEndPoint = null) + public int SendTo(ReadOnlySpan buffer, EndPoint? ipEndPoint = null) { if (ipEndPoint == null && _defaultEndpoint == null) { @@ -304,14 +316,14 @@ public int SendTo(ReadOnlySpan buffer, IPEndPoint? ipEndPoint = null) } catch (Exception ex) { - Log.Erro($"Failed to send packet: {ex.Message}", nameof(SocketUdpClient)); + LogTrace.InfoTrace(ex, nameof(SocketUdpClient), $"Failed to send packet. "); throw; } } #endregion #region SendToAsync - public async Task SendToAsync(ReadOnlyMemory buffer, IPEndPoint? ipEndPoint = null) + public async Task SendToAsync(ReadOnlyMemory buffer, EndPoint? ipEndPoint = null) { if (ipEndPoint == null && _defaultEndpoint == null) { @@ -351,12 +363,12 @@ public async Task SendToAsync(ReadOnlyMemory buffer, IPEndPoint? ipEn } catch (Exception ex) { - Log.Erro($"Failed to send packet: {ex.Message}", nameof(SocketUdpClient)); + LogTrace.InfoTrace(ex, nameof(SocketUdpClient), $"Failed to send packet. "); throw; } } - public async Task SendToAsync(byte[] buffer, IPEndPoint? ipEndPoint = null) + public async Task SendToAsync(byte[] buffer, EndPoint? ipEndPoint = null) { if (ipEndPoint == null && _defaultEndpoint == null) { @@ -396,7 +408,7 @@ public async Task SendToAsync(byte[] buffer, IPEndPoint? ipEndPoint = null) } catch (Exception ex) { - Log.Erro($"Failed to send packet: {ex.Message}", nameof(SocketUdpClient)); + LogTrace.InfoTrace(ex, nameof(SocketUdpClient), $"Failed to send packet. "); throw; } } @@ -429,12 +441,10 @@ public void Close() public class SocketUdpReceiveResult { - private static IPEndPoint defaultIpEp = new IPEndPoint(IPAddress.Any, 0); - #pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。 public byte[] Buffer; -#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。 public int ReceivedBytes; - public IPEndPoint RemoteEndPoint = defaultIpEp; + public IPEndPoint RemoteEndPoint; +#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。 } } \ No newline at end of file diff --git a/Tests/KcpTests/SharedLib/SharedLib.csproj b/Tests/KcpTests/SharedLib/SharedLib.csproj index 79a9ba15a..a5fe4e4fd 100644 --- a/Tests/KcpTests/SharedLib/SharedLib.csproj +++ b/Tests/KcpTests/SharedLib/SharedLib.csproj @@ -7,17 +7,18 @@ - $(DefineConstants);KCP_PERFORMANCE_TEST;STA_ASSERT_DISABLED + $(DefineConstants);KCP_PERFORMANCE_TEST;DISABLED_BYTE_CHECK_MODE;STA_ASSERT_DISABLED - $(DefineConstants);KCP_PERFORMANCE_TEST;STA_ASSERT_DISABLED + $(DefineConstants);KCP_PERFORMANCE_TEST;DISABLED_BYTE_CHECK_MODE;STA_ASSERT_DISABLED - + + diff --git a/Tests/ProtoshiftBenchmark/ProtoshiftBenchmark.csproj b/Tests/ProtoshiftBenchmark/ProtoshiftBenchmark.csproj index 921936af7..2d29db842 100644 --- a/Tests/ProtoshiftBenchmark/ProtoshiftBenchmark.csproj +++ b/Tests/ProtoshiftBenchmark/ProtoshiftBenchmark.csproj @@ -18,7 +18,7 @@ - + diff --git a/Tests/csharp-Protoshift-Replay/csharp-Protoshift-Replay.csproj b/Tests/csharp-Protoshift-Replay/csharp-Protoshift-Replay.csproj index 125627098..91642f56e 100644 --- a/Tests/csharp-Protoshift-Replay/csharp-Protoshift-Replay.csproj +++ b/Tests/csharp-Protoshift-Replay/csharp-Protoshift-Replay.csproj @@ -11,7 +11,7 @@ - + diff --git a/csharp-Protoshift/Commands/Utils/Dispatch/CurrRegionCmd.cs b/csharp-Protoshift/Commands/Utils/Dispatch/CurrRegionCmd.cs index 82140df7d..95d00ce57 100644 --- a/csharp-Protoshift/Commands/Utils/Dispatch/CurrRegionCmd.cs +++ b/csharp-Protoshift/Commands/Utils/Dispatch/CurrRegionCmd.cs @@ -2,6 +2,7 @@ using csharp_Protoshift.resLoader; using Google.Protobuf; using Newtonsoft.Json; +using YYHEggEgg.Logger; namespace csharp_Protoshift.Commands.Utils { diff --git a/csharp-Protoshift/GameSession/GameSessionDispatch.cs b/csharp-Protoshift/GameSession/GameSessionDispatch.cs index 2d30514a6..7726d2841 100644 --- a/csharp-Protoshift/GameSession/GameSessionDispatch.cs +++ b/csharp-Protoshift/GameSession/GameSessionDispatch.cs @@ -28,7 +28,7 @@ public static void SessionCreated(uint conv, IPEndPoint ipEp) } else sessions[conv].remoteIp = ipEp; } - BackgroundInjectOnlineExecuteWindys(conv, + BackgroundInjectOnlineExecuteWindys(conv, OnlineExecWindyMode_v1_0_0.OnKcpConnect, "windyOnKcpConnect"); } @@ -147,7 +147,7 @@ public static async Task InjectOnlineExecuteWindys(uint conv, OnlineExecWindyMod public static void BackgroundInjectOnlineExecuteWindys(uint conv, OnlineExecWindyMode_v1_0_0 condition, string? sender) { - _ = Task.Run(async () => + _ = Task.Run(async () => { await Task.Delay(1500); await InjectOnlineExecuteWindys(conv, condition, $"{sender}_AsyncTask"); @@ -203,47 +203,41 @@ static GameSessionDispatch() { if (Config.Global.EnableFullPacketLog) { - PacketLogger = new BaseLogger(new LoggerConfig( - max_Output_Char_Count: 16 * 1024, - use_Console_Wrapper: true, - use_Working_Directory: true, - global_Minimum_LogLevel: LogLevel.Information, - console_Minimum_LogLevel: LogLevel.None, - debug_LogWriter_AutoFlush: false, - enable_Detailed_Time: true), new LogFileConfig - { - AutoFlushWriter = true, - IsPipeSeparatedFile = true, - MaximumLogLevel = LogLevel.Information, - MinimumLogLevel = LogLevel.Information, - FileIdentifier = "packet" - }); + var customconf = Log.GlobalConfig; + customconf.Global_Minimum_LogLevel = LogLevel.Information; + customconf.Console_Minimum_LogLevel = LogLevel.None; + PacketLogger = new BaseLogger(customconf, new LogFileConfig + { + AutoFlushWriter = true, + IsPipeSeparatedFile = true, + MaximumLogLevel = LogLevel.Information, + MinimumLogLevel = LogLevel.Information, + FileIdentifier = "packet", + AllowAutoFallback = true, + }); } if (Config.Global.EnablePlayerStatLog) { - PlayerStatLogger = new BaseLogger(new LoggerConfig( - max_Output_Char_Count: 16 * 1024, - use_Console_Wrapper: true, - use_Working_Directory: true, + var customconf = Log.GlobalConfig; #if DEBUG - global_Minimum_LogLevel: LogLevel.Debug, + customconf.Global_Minimum_LogLevel = LogLevel.Debug; #else - global_Minimum_LogLevel: LogLevel.Information, + customconf.Global_Minimum_LogLevel = LogLevel.Information; #endif - console_Minimum_LogLevel: LogLevel.None, - debug_LogWriter_AutoFlush: false, - enable_Detailed_Time: true), new LogFileConfig - { - AutoFlushWriter = true, - IsPipeSeparatedFile = true, - MaximumLogLevel = LogLevel.Error, + customconf.Console_Minimum_LogLevel = LogLevel.None; + PlayerStatLogger = new BaseLogger(customconf, new LogFileConfig + { + AutoFlushWriter = true, + IsPipeSeparatedFile = true, + MaximumLogLevel = LogLevel.Error, #if DEBUG - MinimumLogLevel = LogLevel.Debug, + MinimumLogLevel = LogLevel.Debug, #else - MinimumLogLevel = LogLevel.Information, + MinimumLogLevel = LogLevel.Information, #endif - FileIdentifier = "player.stat" - }); + FileIdentifier = "player.stat", + AllowAutoFallback = true, + }); PlayerStatLogger.Info($"UID|Status category|Description|--[Any other Data]--", "Conv ID"); } @@ -266,7 +260,7 @@ from info in Config.Global.WindyConfig.OnlineExecWindys /// /// Invoke the static initializer and create latest.packet.log and latest.player.stat.log. /// - public static void InitializeLogFiles() { } + public static void InitializeLogFiles() { } private static void AssertSessionExists(uint conv) { @@ -285,7 +279,7 @@ public static async Task ValidateWindyAutoExecute() return; foreach (var windyfile in from list in ExecuteWindyMap.Values from item in list - where item.OnlineExecMode != OnlineExecWindyMode_v1_0_0.Disabled + where item.OnlineExecMode != OnlineExecWindyMode_v1_0_0.Disabled && item.OnlineExecMode != OnlineExecWindyMode_v1_0_0.None select item.LuaFileName) { diff --git a/csharp-Protoshift/KCP/KcpProxy/KcpProxyBase.cs b/csharp-Protoshift/KCP/KcpProxy/KcpProxyBase.cs index b5ab44b10..6f5d312ce 100644 --- a/csharp-Protoshift/KCP/KcpProxy/KcpProxyBase.cs +++ b/csharp-Protoshift/KCP/KcpProxy/KcpProxyBase.cs @@ -1,6 +1,5 @@ -// #define KCP_PROXY_VERBOSE +// #define KCP_PROXY_VERBOSE -using csharp_Protoshift.GameSession; using Newtonsoft.Json.Linq; using System.Net; using System.Net.Sockets; diff --git a/csharp-Protoshift/KCP/KcpProxy/KcpProxyClient.cs b/csharp-Protoshift/KCP/KcpProxy/KcpProxyClient.cs index f4c54660d..140cbbbbe 100644 --- a/csharp-Protoshift/KCP/KcpProxy/KcpProxyClient.cs +++ b/csharp-Protoshift/KCP/KcpProxy/KcpProxyClient.cs @@ -1,4 +1,4 @@ -using System.Diagnostics; +using System.Diagnostics; using System.Net; namespace csharp_Protoshift.MhyKCP.Proxy diff --git a/csharp-Protoshift/KCP/KcpProxy/KcpProxyServer.cs b/csharp-Protoshift/KCP/KcpProxy/KcpProxyServer.cs index a94a03604..6fa3846ca 100644 --- a/csharp-Protoshift/KCP/KcpProxy/KcpProxyServer.cs +++ b/csharp-Protoshift/KCP/KcpProxy/KcpProxyServer.cs @@ -1,11 +1,10 @@ -// #define KCP_PROXY_VERBOSE // not avaliable currently +// #define KCP_PROXY_VERBOSE // not avaliable currently using System.Net; using YYHEggEgg.Logger; using csharp_Protoshift.SpecialUdp; using System.Buffers.Binary; using System.Net.Sockets.Kcp; -using csharp_Protoshift.GameSession; namespace csharp_Protoshift.MhyKCP.Proxy { @@ -17,18 +16,33 @@ public class KcpProxyServer : KCPServer #if !PROTOSHIFT_BENCHMARK static KcpProxyServer() { - _kcpstatlogger = new BaseLogger(new LoggerConfig( - max_Output_Char_Count: 16 * 1024, - use_Console_Wrapper: true, - use_Working_Directory: true, +#if !KCP_PERFORMANCE_TEST + if (BaseLogger.LogFileExists("player.stat")) + { +#endif + var customconf = Log.GlobalConfig; +#if DEBUG + customconf.Global_Minimum_LogLevel = LogLevel.Debug; +#else + customconf.Global_Minimum_LogLevel = LogLevel.Information; +#endif + customconf.Console_Minimum_LogLevel = LogLevel.None; + _kcpstatlogger = new BaseLogger(customconf, new LogFileConfig + { + AutoFlushWriter = true, + IsPipeSeparatedFile = true, + MaximumLogLevel = LogLevel.Error, #if DEBUG - global_Minimum_LogLevel: LogLevel.Debug, + MinimumLogLevel = LogLevel.Debug, #else - global_Minimum_LogLevel: LogLevel.Information, + MinimumLogLevel = LogLevel.Information, +#endif + FileIdentifier = "player.stat", + AllowAutoFallback = true, + }); +#if !KCP_PERFORMANCE_TEST + } #endif - console_Minimum_LogLevel: LogLevel.None, - debug_LogWriter_AutoFlush: false, - enable_Detailed_Time: true), "player.stat"); } #endif @@ -89,9 +103,8 @@ protected override async Task BackgroundUpdate() continue; } // ip dispatch - string remoteIpString = packet.RemoteEndPoint.ToString(); KcpProxyBase conn; - if (!connecting_clients.TryGetValue(remoteIpString, out var _outconn)) + if (!connecting_clients.TryGetValue(packet.RemoteEndPoint, out var _outconn)) { // Don't allow a disconnected session if (removed_sessions.Contains(handshake.Conv)) @@ -102,9 +115,9 @@ protected override async Task BackgroundUpdate() // Oh boy! A new connection! conn = new KcpProxyBase(sendToAddress: SendToEndpoint); conn.OutputCallback = new SocketUdpKcpCallback(udpSock, packet.RemoteEndPoint); - Log.Dbug($"New connection established, remote endpoint={remoteIpString}"); + Log.Dbug($"New connection established, remote endpoint={packet.RemoteEndPoint}", nameof(KcpProxyServer)); conn.AcceptNonblock(); - connecting_clients[remoteIpString] = conn; + connecting_clients[packet.RemoteEndPoint] = conn; _ = Task.Run(async () => { try @@ -113,7 +126,7 @@ protected override async Task BackgroundUpdate() } catch { - connecting_clients.TryRemove(remoteIpString, out _); + connecting_clients.TryRemove(packet.RemoteEndPoint, out _); } }); } diff --git a/csharp-Protoshift/KCP/MhyKCP/KCPClient.cs b/csharp-Protoshift/KCP/MhyKCP/KCPClient.cs index 4cd0cdb61..49e477f6d 100644 --- a/csharp-Protoshift/KCP/MhyKCP/KCPClient.cs +++ b/csharp-Protoshift/KCP/MhyKCP/KCPClient.cs @@ -1,5 +1,6 @@ using System.Net; using csharp_Protoshift.SpecialUdp; +using YYHEggEgg.Logger; namespace csharp_Protoshift.MhyKCP { diff --git a/csharp-Protoshift/KCP/MhyKCP/KCPServer.cs b/csharp-Protoshift/KCP/MhyKCP/KCPServer.cs index cd5b356c6..5e6975a5c 100644 --- a/csharp-Protoshift/KCP/MhyKCP/KCPServer.cs +++ b/csharp-Protoshift/KCP/MhyKCP/KCPServer.cs @@ -12,8 +12,7 @@ public class KCPServer : IDisposable protected SocketUdpClient udpSock; protected bool _Closed = false; - // string is the ToString() form of IPEndPoint - protected ConcurrentDictionary connecting_clients; + protected ConcurrentDictionary connecting_clients; protected ConcurrentDictionary connected_clients; protected ConcurrentQueue newConnections; protected ConcurrentBag removed_sessions; @@ -83,9 +82,8 @@ protected virtual async Task BackgroundUpdate() continue; } // ip dispatch - string remoteIpString = packet.RemoteEndPoint.ToString(); MhyKcpBase conn; - if (!connecting_clients.TryGetValue(remoteIpString, out var _outconn)) + if (!connecting_clients.TryGetValue(packet.RemoteEndPoint, out var _outconn)) { // Don't allow a disconnected session if (removed_sessions.Contains(handshake.Conv)) continue; @@ -93,7 +91,7 @@ protected virtual async Task BackgroundUpdate() conn = new MhyKcpBase(); conn.OutputCallback = new SocketUdpKcpCallback(udpSock, packet.RemoteEndPoint); conn.AcceptNonblock(); - connecting_clients[remoteIpString] = conn; + connecting_clients[packet.RemoteEndPoint] = conn; _ = Task.Run(async () => { try @@ -102,7 +100,7 @@ protected virtual async Task BackgroundUpdate() } catch { - connecting_clients.TryRemove(remoteIpString, out _); + connecting_clients.TryRemove(packet.RemoteEndPoint, out _); } }); } diff --git a/csharp-Protoshift/KCP/MhyKCP/KcpInnerBuffer.cs b/csharp-Protoshift/KCP/MhyKCP/KcpInnerBuffer.cs index e1799eb12..20756fe95 100644 --- a/csharp-Protoshift/KCP/MhyKCP/KcpInnerBuffer.cs +++ b/csharp-Protoshift/KCP/MhyKCP/KcpInnerBuffer.cs @@ -1,4 +1,4 @@ -using System.Buffers; +using System.Buffers; namespace csharp_Protoshift.MhyKCP { diff --git a/csharp-Protoshift/KCP/MhyKCP/KcpPacketAudit.cs b/csharp-Protoshift/KCP/MhyKCP/KcpPacketAudit.cs index eec4b3c34..9c3f1e2aa 100644 --- a/csharp-Protoshift/KCP/MhyKCP/KcpPacketAudit.cs +++ b/csharp-Protoshift/KCP/MhyKCP/KcpPacketAudit.cs @@ -1,9 +1,10 @@ -#define MIHOMO_KCP +#define MIHOMO_KCP using System.Buffers; using System.Buffers.Binary; using System.Collections.Concurrent; using System.Diagnostics; +using System.IO.Hashing; using System.Net.Sockets.Kcp; using System.Text; using YYHEggEgg.Logger; @@ -98,6 +99,10 @@ private static void BackgroundUpdate() offset += sizeof(byte) + sizeof(ushort) + sizeof(uint) * 3; uint len = BinaryPrimitives.ReadUInt32LittleEndian(segment.Slice(offset)); offset += sizeof(uint); +#if BYTE_CHECK_MODE + uint byteCheckCode = BinaryPrimitives.ReadUInt32LittleEndian(segment.Slice(offset)); + offset += sizeof(uint); +#endif Debug.Assert(offset == KcpConst.IKCP_OVERHEAD); #endregion #region Content Length Check @@ -115,6 +120,16 @@ private static void BackgroundUpdate() Convert.ToHexString(segment.Slice( (int)(offset + len), (int)(contentLen - len)))); } +#if BYTE_CHECK_MODE && !CORRUPT_PACKET + else + { + var checksum = Crc32.HashToUInt32(segment.Slice(offset)); + if (byteCheckCode != checksum) + { + exceptions.Add($"Segment {i} byte check (CRC32) failed, expected: {byteCheckCode}, actual: {checksum}."); + } + } +#endif #endregion } } @@ -149,7 +164,7 @@ private static void BackgroundUpdate() #if MIHOMO_KCP offset += sizeof(uint) * 2; #else - offset += sizeof(uint); + offset += sizeof(uint); #endif byte cmd = segment[offset]; offset += sizeof(byte); @@ -165,6 +180,10 @@ private static void BackgroundUpdate() offset += sizeof(uint); uint len = BinaryPrimitives.ReadUInt32LittleEndian(segment.Slice(offset)); offset += sizeof(uint); +#if BYTE_CHECK_MODE + uint byteCheckCode = BinaryPrimitives.ReadUInt32LittleEndian(segment.Slice(offset)); + offset += sizeof(uint); +#endif Debug.Assert(offset == KcpConst.IKCP_OVERHEAD); #endregion #region Output segment diff --git a/csharp-Protoshift/KCP/MhyKCP/MhyKcpBase.cs b/csharp-Protoshift/KCP/MhyKCP/MhyKcpBase.cs index f4cf66463..ab530c3e2 100644 --- a/csharp-Protoshift/KCP/MhyKCP/MhyKcpBase.cs +++ b/csharp-Protoshift/KCP/MhyKCP/MhyKcpBase.cs @@ -1,4 +1,4 @@ -// #define KCP_INNER_LOG +// #define KCP_INNER_LOG // #define KCP_EXPORT_PACKET_RECORD using System.Net.Sockets; @@ -54,6 +54,11 @@ public enum ConnectionState protected object cskcp_recvLock = "R.I.P YSFreedom"; protected object cskcp_sndLock = "Yolmiya"; protected long startTime; + /// + /// Used for assigning conv for new connections. + /// Use to operate with it. + /// + protected static uint _currentConv = 1000; public uint ConnectData { get; protected set; } public OuterCode.UniqueIDManager _uniqueID = new(nameof(MhyKcpBase)); @@ -75,6 +80,15 @@ public void Initialize() cskcpHandle = new(_Conv, _Token, OutputCallback); _State = ConnectionState.CONNECTED; +#if BYTE_CHECK_MODE +#if CORRUPT_PACKET + bool corrupt = true; +#else + bool corrupt = false; +#endif + cskcpHandle.SetByteCheck(2, corrupt); +#endif + // Added // IKCP.ikcp_nodelay(ikcpHandle, 1, 10, 2, 1); // modified because mhy is using far more aggressive code, or 力大砖飞 mode @@ -187,7 +201,7 @@ public virtual int Input(byte[] buffer) { // Log.Dbug($"HandShakeWaitNotify, buf = {Convert.ToHexString(buffer)}", nameof(MhyKcpBase)); handshake.Decode(buffer, Handshake.MAGIC_CONNECT); - _Conv = (uint)(MonotonicTime.Now & 0xFFFFFFFF); + _Conv = Interlocked.Increment(ref _currentConv); _Token = 0xFFCCEEBB ^ (uint)((MonotonicTime.Now >> 32) & 0xFFFFFFFF); var sendBackConv = new Handshake(Handshake.MAGIC_SEND_BACK_CONV, _Conv, _Token).AsBytes(); diff --git a/csharp-Protoshift/KCP/MhyKCP/UdpKcpCallback.cs b/csharp-Protoshift/KCP/MhyKCP/UdpKcpCallback.cs index 73b8fd9cc..a234190a9 100644 --- a/csharp-Protoshift/KCP/MhyKCP/UdpKcpCallback.cs +++ b/csharp-Protoshift/KCP/MhyKCP/UdpKcpCallback.cs @@ -1,10 +1,12 @@ -#define KCP_PACKET_AUDIT +// #define KCP_PACKET_AUDIT using csharp_Protoshift.SpecialUdp; using System.Buffers; +using System.Diagnostics; using System.Net; using System.Net.Sockets; using System.Net.Sockets.Kcp; +using YYHEggEgg.Logger; namespace csharp_Protoshift.MhyKCP { @@ -42,11 +44,15 @@ public SocketUdpKcpCallback(SocketUdpClient udpSock, IPEndPoint? ipEp = null) public void Output(IMemoryOwner buffer, int avalidLength, bool isKcpPacket = true) { // Stopwatch udpwatch = Stopwatch.StartNew(); - // DateTime req_SendTime = DateTime.Now; +#if KCP_PACKET_AUDIT + DateTime req_SendTime = DateTime.Now; +#endif // udpSock.SendToAsync(buffer.Memory.Slice(0, avalidLength), ipEp).Wait(); udpSock.SendTo(buffer.Memory.Span.Slice(0, avalidLength), ipEp); - // if (isKcpPacket) - // KcpPacketAudit.PushPacket(req_SendTime, buffer.Memory, avalidLength); +#if KCP_PACKET_AUDIT + if (isKcpPacket) + KcpPacketAudit.PushPacket(req_SendTime, buffer.Memory, avalidLength); +#endif buffer.Dispose(); // udpwatch.Stop(); // Log.Dbug($"SocketUdpKcpCallback output elapsed {udpwatch.Elapsed.TotalMilliseconds}ms."); diff --git a/csharp-Protoshift/KCP/SingleThreadAssert.cs b/csharp-Protoshift/KCP/SingleThreadAssert.cs index a598246d3..15037ea68 100644 --- a/csharp-Protoshift/KCP/SingleThreadAssert.cs +++ b/csharp-Protoshift/KCP/SingleThreadAssert.cs @@ -1,4 +1,5 @@ -using YYHEggEgg.Logger; +using YYHEggEgg.Logger; + namespace csharp_Protoshift { /// diff --git a/csharp-Protoshift/KCP/SpecialUdp/SocketUdpClient.cs b/csharp-Protoshift/KCP/SpecialUdp/SocketUdpClient.cs index ed84821c6..2e8dfc862 100644 --- a/csharp-Protoshift/KCP/SpecialUdp/SocketUdpClient.cs +++ b/csharp-Protoshift/KCP/SpecialUdp/SocketUdpClient.cs @@ -1,4 +1,4 @@ -// #define SOCKET_UDP_VERBOSE +// #define SOCKET_UDP_VERBOSE // #define SOCKET_UDP_PACKET_CONTENT_VERBOSE // #define SOCKET_UDP_PACKET_CONTENT_VERBOSE_SYNCRONOUS @@ -175,7 +175,7 @@ public async Task ReceiveFromAsync() var stopwatch = new System.Diagnostics.Stopwatch(); stopwatch.Start(); #endif - + var result = await _socket.ReceiveFromAsync(buffer, SocketFlags.None, receiveResult.RemoteEndPoint); @@ -441,7 +441,6 @@ public void Close() public class SocketUdpReceiveResult { - #pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。 public byte[] Buffer; public int ReceivedBytes; diff --git a/csharp-Protoshift/LoggerChannelTraceExtensions.cs b/csharp-Protoshift/LoggerChannelTraceExtensions.cs deleted file mode 100644 index 3df39a306..000000000 --- a/csharp-Protoshift/LoggerChannelTraceExtensions.cs +++ /dev/null @@ -1,328 +0,0 @@ -using YYHEggEgg.Logger; - -namespace csharp_Protoshift -{ - public static class LoggerChannelTraceExtensions - { - private static object _exception_lck = "<3 from miHomo Technology"; - private static Dictionary _trace_ids = new(); - private static int _total_characters = 0; - private const int MAXIMUM_MEMORY_CHARS = 4 * 1024 * 1024; // >= 4MB - private static bool _initialized = false; - private static BaseLogger? _tracelog; - - private static void Initialize() - { - lock (_exception_lck) - { - if (_initialized) return; - - _tracelog = new BaseLogger(new LoggerConfig( - max_Output_Char_Count: Log.GlobalConfig.Max_Output_Char_Count, - use_Console_Wrapper: Log.GlobalConfig.Use_Console_Wrapper, - use_Working_Directory: Log.GlobalConfig.Use_Working_Directory, - global_Minimum_LogLevel: LogLevel.Information, - console_Minimum_LogLevel: LogLevel.None, - debug_LogWriter_AutoFlush: true, - is_PipeSeparated_Format: false, - enable_Detailed_Time: Log.GlobalConfig.Enable_Detailed_Time - ), new LogFileConfig - { - MinimumLogLevel = LogLevel.Information, - MaximumLogLevel = LogLevel.Information, - AutoFlushWriter = true, - FileIdentifier = "errtrace", - IsPipeSeparatedFile = false, - }); - - _initialized = true; - } - } - - private static (Guid traceid, bool isnew) AssignTraceId(string ex_full_content) - { - (Guid traceid, bool isnew) rtn; - lock (_exception_lck) - { - if (!_trace_ids.TryGetValue(ex_full_content, out Guid id)) - { - rtn = (Guid.NewGuid(), true); - _trace_ids.Add(ex_full_content, rtn.traceid); - return rtn; - } - - _total_characters += ex_full_content.Length; - if (_total_characters > MAXIMUM_MEMORY_CHARS) - { - var tmp = _trace_ids[ex_full_content]; - _trace_ids.Clear(); - _trace_ids.Add(ex_full_content, tmp); - } - rtn = (id, false); - return rtn; - } - } - - /// - /// 以 - /// 与 输出至 , - /// 并将额外的异常堆栈跟踪信息输出到 latest.errtrace.log. - /// - /// 程序中发生的异常信息。 - /// 需要在控制台中输出的错误发生地点摘要。 - /// 查询或分配的 Trace ID. - public static Guid LogExceptionTrace(this LoggerChannel logger, - Exception? ex, LogLevel logLevel, string? prompt = null) - { - Initialize(); - var traceinfo = ex?.ToString() ?? string.Empty; - var extype = ex?.GetType().ToString() ?? ""; - var exmsg = ex?.Message ?? ""; - (Guid traceid, bool isnew) = AssignTraceId(traceinfo); - - logger.LogPush($"{prompt}{extype}: {exmsg} (Trace ID: {traceid})", - logLevel); - if (isnew) _tracelog?.Info($"Trace ID [{traceid}]: \n{traceinfo}", logger.LogSender); - return traceid; - } - - /// - /// Output with - /// to , - /// and output the extra detailed exception trace to - /// latest.errtrace.log. - /// - /// The exception caught in the program. - /// The summary of where the exception is caught. - /// 查询或分配的 Trace ID. - public static Guid LogErroTrace(this LoggerChannel logger, - Exception? ex, string? prompt = null) - => LogExceptionTrace(logger, ex, LogLevel.Error, prompt); - - /// - /// Output with - /// to , - /// and output the extra detailed exception trace to - /// latest.errtrace.log. - /// - /// The exception caught in the program. - /// The summary of where the exception is caught. - /// 查询或分配的 Trace ID. - public static Guid LogWarnTrace(this LoggerChannel logger, - Exception? ex, string? prompt = null) - => LogExceptionTrace(logger, ex, LogLevel.Warning, prompt); - - /// - /// Output with - /// to , - /// and output the extra detailed exception trace to - /// latest.errtrace.log. - /// - /// The exception caught in the program. - /// The summary of where the exception is caught. - /// 查询或分配的 Trace ID. - public static Guid LogInfoTrace(this LoggerChannel logger, - Exception? ex, string? prompt = null) - => LogExceptionTrace(logger, ex, LogLevel.Information, prompt); - - /// - /// Output with - /// to , - /// and output the extra detailed exception trace to - /// latest.errtrace.log. - /// - /// The exception caught in the program. - /// The summary of where the exception is caught. - /// 查询或分配的 Trace ID. - public static Guid LogDbugTrace(this LoggerChannel logger, - Exception? ex, string? prompt = null) - => LogExceptionTrace(logger, ex, LogLevel.Debug, prompt); - - /// - /// Output with - /// to , - /// and output the extra detailed exception trace to - /// latest.errtrace.log. - /// - /// The exception caught in the program. - /// The summary of where the exception is caught. - /// 查询或分配的 Trace ID. - public static Guid LogVerbTrace(this LoggerChannel logger, - Exception? ex, string? prompt = null) - => LogExceptionTrace(logger, ex, LogLevel.Verbose, prompt); - } - - public static class BaseLoggerTraceExtensions - { - /// - /// Output with - /// a given to the global main logger, - /// and output the extra detailed exception trace to - /// latest.errtrace.log. - /// - /// The exception caught in the program. - /// The summary of where the exception is caught. - /// The sender param used by logging. - /// 查询或分配的 Trace ID. - public static Guid ExceptionTrace(this BaseLogger logger, - Exception? ex, LogLevel logLevel, string? sender = null, string? prompt = null) - => logger.GetChannel(sender).LogExceptionTrace(ex, logLevel, prompt); - - /// - /// Output with - /// to the global main logger, - /// and output the extra detailed exception trace to - /// latest.errtrace.log. - /// - /// The exception caught in the program. - /// The summary of where the exception is caught. - /// The sender param used by logging. - /// 查询或分配的 Trace ID. - public static Guid ErroTrace(this BaseLogger logger, - Exception? ex, string? sender = null, string? prompt = null) - => logger.GetChannel(sender).LogErroTrace(ex, prompt); - - /// - /// Output with - /// to the global main logger, - /// and output the extra detailed exception trace to - /// latest.errtrace.log. - /// - /// The exception caught in the program. - /// The summary of where the exception is caught. - /// The sender param used by logging. - /// 查询或分配的 Trace ID. - public static Guid WarnTrace(this BaseLogger logger, - Exception? ex, string? sender = null, string? prompt = null) - => logger.GetChannel(sender).LogWarnTrace(ex, prompt); - - /// - /// Output with - /// to the global main logger, - /// and output the extra detailed exception trace to - /// latest.errtrace.log. - /// - /// The exception caught in the program. - /// The summary of where the exception is caught. - /// The sender param used by logging. - /// 查询或分配的 Trace ID. - public static Guid InfoTrace(this BaseLogger logger, - Exception? ex, string? sender = null, string? prompt = null) - => logger.GetChannel(sender).LogInfoTrace(ex, prompt); - - /// - /// Output with - /// to the global main logger, - /// and output the extra detailed exception trace to - /// latest.errtrace.log. - /// - /// The exception caught in the program. - /// The summary of where the exception is caught. - /// The sender param used by logging. - /// 查询或分配的 Trace ID. - public static Guid DbugTrace(this BaseLogger logger, - Exception? ex, string? sender = null, string? prompt = null) - => logger.GetChannel(sender).LogDbugTrace(ex, prompt); - - /// - /// Output with - /// to the global main logger, - /// and output the extra detailed exception trace to - /// latest.errtrace.log. - /// - /// The exception caught in the program. - /// The summary of where the exception is caught. - /// The sender param used by logging. - /// 查询或分配的 Trace ID. - public static Guid VerbTrace(this BaseLogger logger, - Exception? ex, string? sender = null, string? prompt = null) - => logger.GetChannel(sender).LogVerbTrace(ex, prompt); - } - - public static class LogTrace - { - /// - /// Output with - /// a given to the global main logger, - /// and output the extra detailed exception trace to - /// latest.errtrace.log. - /// - /// The exception caught in the program. - /// The summary of where the exception is caught. - /// The sender param used by logging. - /// 查询或分配的 Trace ID. - public static Guid ExceptionTrace( - Exception? ex, LogLevel logLevel, string? sender = null, string? prompt = null) - => Log.GlobalBasedLogger.ExceptionTrace(ex, logLevel, sender, prompt); - - /// - /// Output with - /// to the global main logger, - /// and output the extra detailed exception trace to - /// latest.errtrace.log. - /// - /// The exception caught in the program. - /// The summary of where the exception is caught. - /// The sender param used by logging. - /// 查询或分配的 Trace ID. - public static Guid ErroTrace( - Exception? ex, string? sender = null, string? prompt = null) - => Log.GlobalBasedLogger.ErroTrace(ex, sender, prompt); - - /// - /// Output with - /// to the global main logger, - /// and output the extra detailed exception trace to - /// latest.errtrace.log. - /// - /// The exception caught in the program. - /// The summary of where the exception is caught. - /// The sender param used by logging. - /// 查询或分配的 Trace ID. - public static Guid WarnTrace( - Exception? ex, string? sender = null, string? prompt = null) - => Log.GlobalBasedLogger.WarnTrace(ex, sender, prompt); - - /// - /// Output with - /// to the global main logger, - /// and output the extra detailed exception trace to - /// latest.errtrace.log. - /// - /// The exception caught in the program. - /// The summary of where the exception is caught. - /// The sender param used by logging. - /// 查询或分配的 Trace ID. - public static Guid InfoTrace( - Exception? ex, string? sender = null, string? prompt = null) - => Log.GlobalBasedLogger.InfoTrace(ex, sender, prompt); - - /// - /// Output with - /// to the global main logger, - /// and output the extra detailed exception trace to - /// latest.errtrace.log. - /// - /// The exception caught in the program. - /// The summary of where the exception is caught. - /// The sender param used by logging. - /// 查询或分配的 Trace ID. - public static Guid DbugTrace( - Exception? ex, string? sender = null, string? prompt = null) - => Log.GlobalBasedLogger.DbugTrace(ex, sender, prompt); - - /// - /// Output with - /// to the global main logger, - /// and output the extra detailed exception trace to - /// latest.errtrace.log. - /// - /// The exception caught in the program. - /// The summary of where the exception is caught. - /// The sender param used by logging. - /// 查询或分配的 Trace ID. - public static Guid VerbTrace( - Exception? ex, string? sender = null, string? prompt = null) - => Log.GlobalBasedLogger.VerbTrace(ex, sender, prompt); - } -} \ No newline at end of file diff --git a/csharp-Protoshift/csharp-Protoshift.csproj b/csharp-Protoshift/csharp-Protoshift.csproj index 12e227f99..6764402c3 100644 --- a/csharp-Protoshift/csharp-Protoshift.csproj +++ b/csharp-Protoshift/csharp-Protoshift.csproj @@ -28,7 +28,7 @@ - +