Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,541 changes: 1,541 additions & 0 deletions .doc/CSM-TCP-Router.excalidraw

Large diffs are not rendered by default.

Binary file added .doc/CSM-TCP-Router.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions .doc/Protocol.v0.(zh-cn).md
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ sequenceDiagram

> [!NOTE]
> `status` 和 `interrupt` 两种订阅广播类型均受支持:
>
> - `status`(`0x06`):普通广播,订阅模块的常规状态变化
> - `interrupt`(`0x07`):中断广播,订阅模块触发的中断事件
>
Expand Down
14 changes: 14 additions & 0 deletions .doc/csm-tcp-router-client-console.excalidraw
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"type": "excalidraw",
"version": 2,
"source": "https://excalidraw.com",
"elements": [
{"id":"u","type":"text","x":80,"y":60,"width":52,"height":24,"angle":0,"strokeColor":"#1e1e1e","backgroundColor":"transparent","fillStyle":"hachure","strokeWidth":1,"strokeStyle":"solid","roughness":0,"opacity":100,"groupIds":[],"frameId":null,"roundness":null,"seed":21,"version":1,"versionNonce":21,"isDeleted":false,"boundElements":[],"updated":1,"link":null,"locked":false,"text":"User","fontSize":20,"fontFamily":1,"textAlign":"left","verticalAlign":"top","containerId":null,"originalText":"User","lineHeight":1.2},
{"id":"c","type":"text","x":290,"y":60,"width":150,"height":24,"angle":0,"strokeColor":"#1e1e1e","backgroundColor":"transparent","fillStyle":"hachure","strokeWidth":1,"strokeStyle":"solid","roughness":0,"opacity":100,"groupIds":[],"frameId":null,"roundness":null,"seed":22,"version":1,"versionNonce":22,"isDeleted":false,"boundElements":[],"updated":1,"link":null,"locked":false,"text":"Client Console","fontSize":20,"fontFamily":1,"textAlign":"left","verticalAlign":"top","containerId":null,"originalText":"Client Console","lineHeight":1.2},
{"id":"r","type":"text","x":570,"y":60,"width":150,"height":24,"angle":0,"strokeColor":"#1e1e1e","backgroundColor":"transparent","fillStyle":"hachure","strokeWidth":1,"strokeStyle":"solid","roughness":0,"opacity":100,"groupIds":[],"frameId":null,"roundness":null,"seed":23,"version":1,"versionNonce":23,"isDeleted":false,"boundElements":[],"updated":1,"link":null,"locked":false,"text":"TCP Router","fontSize":20,"fontFamily":1,"textAlign":"left","verticalAlign":"top","containerId":null,"originalText":"TCP Router","lineHeight":1.2},
{"id":"s","type":"text","x":830,"y":60,"width":104,"height":24,"angle":0,"strokeColor":"#1e1e1e","backgroundColor":"transparent","fillStyle":"hachure","strokeWidth":1,"strokeStyle":"solid","roughness":0,"opacity":100,"groupIds":[],"frameId":null,"roundness":null,"seed":24,"version":1,"versionNonce":24,"isDeleted":false,"boundElements":[],"updated":1,"link":null,"locked":false,"text":"Server Log","fontSize":20,"fontFamily":1,"textAlign":"left","verticalAlign":"top","containerId":null,"originalText":"Server Log","lineHeight":1.2},
{"id":"note","type":"text","x":140,"y":180,"width":760,"height":72,"angle":0,"strokeColor":"#1e1e1e","backgroundColor":"transparent","fillStyle":"hachure","strokeWidth":1,"strokeStyle":"solid","roughness":0,"opacity":100,"groupIds":[],"frameId":null,"roundness":null,"seed":25,"version":1,"versionNonce":25,"isDeleted":false,"boundElements":[],"updated":1,"link":null,"locked":false,"text":"Connect -> welcome(info) -> send cmd -> resp/async-resp -> Bye -> goodbye(info)","fontSize":24,"fontFamily":1,"textAlign":"left","verticalAlign":"top","containerId":null,"originalText":"Connect -> welcome(info) -> send cmd -> resp/async-resp -> Bye -> goodbye(info)","lineHeight":1.2}
],
"appState": {"gridSize": null, "viewBackgroundColor": "#ffffff"},
"files": {}
}
Binary file added .doc/csm-tcp-router-client-console.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions .doc/csm-tcp-router-command-sets.excalidraw
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"type": "excalidraw",
"version": 2,
"source": "https://excalidraw.com",
"elements": [
{"id":"r0","type":"rectangle","x":420,"y":40,"width":240,"height":70,"angle":0,"strokeColor":"#1e1e1e","backgroundColor":"#fff7ed","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"groupIds":[],"frameId":null,"roundness":{"type":3},"seed":11,"version":1,"versionNonce":11,"isDeleted":false,"boundElements":[],"updated":1,"link":null,"locked":false},
{"id":"t0","type":"text","x":470,"y":64,"width":140,"height":24,"angle":0,"strokeColor":"#1e1e1e","backgroundColor":"transparent","fillStyle":"hachure","strokeWidth":1,"strokeStyle":"solid","roughness":0,"opacity":100,"groupIds":[],"frameId":null,"roundness":null,"seed":12,"version":1,"versionNonce":12,"isDeleted":false,"boundElements":[],"updated":1,"link":null,"locked":false,"text":"Command Sets","fontSize":20,"fontFamily":1,"textAlign":"center","verticalAlign":"middle","containerId":null,"originalText":"Command Sets","lineHeight":1.2},
{"id":"r1","type":"rectangle","x":80,"y":200,"width":280,"height":82,"angle":0,"strokeColor":"#1e1e1e","backgroundColor":"#eff6ff","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"groupIds":[],"frameId":null,"roundness":{"type":3},"seed":13,"version":1,"versionNonce":13,"isDeleted":false,"boundElements":[],"updated":1,"link":null,"locked":false},
{"id":"t1","type":"text","x":110,"y":230,"width":220,"height":24,"angle":0,"strokeColor":"#1e1e1e","backgroundColor":"transparent","fillStyle":"hachure","strokeWidth":1,"strokeStyle":"solid","roughness":0,"opacity":100,"groupIds":[],"frameId":null,"roundness":null,"seed":14,"version":1,"versionNonce":14,"isDeleted":false,"boundElements":[],"updated":1,"link":null,"locked":false,"text":"1) CSM Message APIs","fontSize":20,"fontFamily":1,"textAlign":"center","verticalAlign":"middle","containerId":null,"originalText":"1) CSM Message APIs","lineHeight":1.2},
{"id":"r2","type":"rectangle","x":430,"y":200,"width":280,"height":82,"angle":0,"strokeColor":"#1e1e1e","backgroundColor":"#f0fdfa","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"groupIds":[],"frameId":null,"roundness":{"type":3},"seed":15,"version":1,"versionNonce":15,"isDeleted":false,"boundElements":[],"updated":1,"link":null,"locked":false},
{"id":"t2","type":"text","x":444,"y":230,"width":252,"height":24,"angle":0,"strokeColor":"#1e1e1e","backgroundColor":"transparent","fillStyle":"hachure","strokeWidth":1,"strokeStyle":"solid","roughness":0,"opacity":100,"groupIds":[],"frameId":null,"roundness":null,"seed":16,"version":1,"versionNonce":16,"isDeleted":false,"boundElements":[],"updated":1,"link":null,"locked":false,"text":"2) Router Management APIs","fontSize":20,"fontFamily":1,"textAlign":"center","verticalAlign":"middle","containerId":null,"originalText":"2) Router Management APIs","lineHeight":1.2},
{"id":"r3","type":"rectangle","x":780,"y":200,"width":280,"height":82,"angle":0,"strokeColor":"#1e1e1e","backgroundColor":"#faf5ff","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"groupIds":[],"frameId":null,"roundness":{"type":3},"seed":17,"version":1,"versionNonce":17,"isDeleted":false,"boundElements":[],"updated":1,"link":null,"locked":false},
{"id":"t3","type":"text","x":820,"y":230,"width":200,"height":24,"angle":0,"strokeColor":"#1e1e1e","backgroundColor":"transparent","fillStyle":"hachure","strokeWidth":1,"strokeStyle":"solid","roughness":0,"opacity":100,"groupIds":[],"frameId":null,"roundness":null,"seed":18,"version":1,"versionNonce":18,"isDeleted":false,"boundElements":[],"updated":1,"link":null,"locked":false,"text":"3) Client Built-ins","fontSize":20,"fontFamily":1,"textAlign":"center","verticalAlign":"middle","containerId":null,"originalText":"3) Client Built-ins","lineHeight":1.2}
],
"appState": {"gridSize": null, "viewBackgroundColor": "#ffffff"},
"files": {}
}
Binary file added .doc/csm-tcp-router-command-sets.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions .doc/csm-tcp-router-framework.excalidraw
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"type": "excalidraw",
"version": 2,
"source": "https://excalidraw.com",
"elements": [
{"id":"c1","type":"rectangle","x":40,"y":160,"width":190,"height":72,"angle":0,"strokeColor":"#1e1e1e","backgroundColor":"#e8f4ff","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"groupIds":[],"frameId":null,"roundness":{"type":3},"seed":1,"version":1,"versionNonce":1,"isDeleted":false,"boundElements":[],"updated":1,"link":null,"locked":false},
{"id":"t1","type":"text","x":72,"y":186,"width":126,"height":24,"angle":0,"strokeColor":"#1e1e1e","backgroundColor":"transparent","fillStyle":"hachure","strokeWidth":1,"strokeStyle":"solid","roughness":0,"opacity":100,"groupIds":[],"frameId":null,"roundness":null,"seed":2,"version":1,"versionNonce":2,"isDeleted":false,"boundElements":[],"updated":1,"link":null,"locked":false,"text":"TCP Clients","fontSize":20,"fontFamily":1,"textAlign":"center","verticalAlign":"middle","containerId":null,"originalText":"TCP Clients","lineHeight":1.2},
{"id":"c2","type":"rectangle","x":290,"y":160,"width":230,"height":72,"angle":0,"strokeColor":"#1e1e1e","backgroundColor":"#ecfeff","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"groupIds":[],"frameId":null,"roundness":{"type":3},"seed":3,"version":1,"versionNonce":3,"isDeleted":false,"boundElements":[],"updated":1,"link":null,"locked":false},
{"id":"t2","type":"text","x":322,"y":186,"width":166,"height":24,"angle":0,"strokeColor":"#1e1e1e","backgroundColor":"transparent","fillStyle":"hachure","strokeWidth":1,"strokeStyle":"solid","roughness":0,"opacity":100,"groupIds":[],"frameId":null,"roundness":null,"seed":4,"version":1,"versionNonce":4,"isDeleted":false,"boundElements":[],"updated":1,"link":null,"locked":false,"text":"CSM-TCP-Router","fontSize":20,"fontFamily":1,"textAlign":"center","verticalAlign":"middle","containerId":null,"originalText":"CSM-TCP-Router","lineHeight":1.2},
{"id":"c3","type":"rectangle","x":580,"y":160,"width":220,"height":72,"angle":0,"strokeColor":"#1e1e1e","backgroundColor":"#f5f3ff","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"groupIds":[],"frameId":null,"roundness":{"type":3},"seed":5,"version":1,"versionNonce":5,"isDeleted":false,"boundElements":[],"updated":1,"link":null,"locked":false},
{"id":"t3","type":"text","x":620,"y":186,"width":140,"height":24,"angle":0,"strokeColor":"#1e1e1e","backgroundColor":"transparent","fillStyle":"hachure","strokeWidth":1,"strokeStyle":"solid","roughness":0,"opacity":100,"groupIds":[],"frameId":null,"roundness":null,"seed":6,"version":1,"versionNonce":6,"isDeleted":false,"boundElements":[],"updated":1,"link":null,"locked":false,"text":"CSM Bus","fontSize":20,"fontFamily":1,"textAlign":"center","verticalAlign":"middle","containerId":null,"originalText":"CSM Bus","lineHeight":1.2},
{"id":"c4","type":"rectangle","x":860,"y":160,"width":210,"height":72,"angle":0,"strokeColor":"#1e1e1e","backgroundColor":"#f0fdf4","fillStyle":"solid","strokeWidth":2,"strokeStyle":"solid","roughness":1,"opacity":100,"groupIds":[],"frameId":null,"roundness":{"type":3},"seed":7,"version":1,"versionNonce":7,"isDeleted":false,"boundElements":[],"updated":1,"link":null,"locked":false},
{"id":"t4","type":"text","x":884,"y":186,"width":162,"height":24,"angle":0,"strokeColor":"#1e1e1e","backgroundColor":"transparent","fillStyle":"hachure","strokeWidth":1,"strokeStyle":"solid","roughness":0,"opacity":100,"groupIds":[],"frameId":null,"roundness":null,"seed":8,"version":1,"versionNonce":8,"isDeleted":false,"boundElements":[],"updated":1,"link":null,"locked":false,"text":"CSM Modules","fontSize":20,"fontFamily":1,"textAlign":"center","verticalAlign":"middle","containerId":null,"originalText":"CSM Modules","lineHeight":1.2}
],
"appState": {"gridSize": null, "viewBackgroundColor": "#ffffff"},
"files": {}
}
File renamed without changes
File renamed without changes.
124 changes: 124 additions & 0 deletions .github/workflows/CSharp_SDK.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
name: CSharp SDK

on:
push:
paths:
- 'SDK/csharp/**'
- '.github/workflows/CSharp_SDK.yml'
tags:
- 'csharp-sdk-v*'
pull_request:
paths:
- 'SDK/csharp/**'
- '.github/workflows/CSharp_SDK.yml'
workflow_dispatch:

defaults:
run:
working-directory: SDK/csharp

jobs:
# -------------------------------------------------------------------------
# Build + test on multiple OSes
# -------------------------------------------------------------------------
test:
name: Build & Test (${{ matrix.os }})
runs-on: ${{ matrix.os }}
permissions:
contents: read
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]

steps:
- uses: actions/checkout@v4

- name: Set up .NET 8 SDK
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'

- name: Restore
run: dotnet restore CsmTcpRouter.sln

- name: Build
run: dotnet build CsmTcpRouter.sln -c Release --no-restore

- name: Test
run: dotnet test tests/CsmTcpRouter.Tests/CsmTcpRouter.Tests.csproj -c Release --no-build --logger "trx;LogFileName=test-results.trx" --collect:"XPlat Code Coverage"

- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-${{ matrix.os }}
path: SDK/csharp/tests/CsmTcpRouter.Tests/TestResults/
if-no-files-found: ignore

# -------------------------------------------------------------------------
# Pack the NuGet package
# -------------------------------------------------------------------------
pack:
name: Pack NuGet
runs-on: ubuntu-latest
needs: test
permissions:
contents: read

steps:
- uses: actions/checkout@v4

- name: Set up .NET 8 SDK
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'

- name: Pack
run: dotnet pack src/CsmTcpRouter/CsmTcpRouter.csproj -c Release -o nupkg

- name: Upload NuGet artifact
uses: actions/upload-artifact@v4
with:
name: csharp-sdk-nupkg
path: SDK/csharp/nupkg/

# -------------------------------------------------------------------------
# Publish to NuGet.org (on tag push only)
# -------------------------------------------------------------------------
publish:
name: Publish to NuGet.org
runs-on: ubuntu-latest
needs: pack
if: startsWith(github.ref, 'refs/tags/csharp-sdk-v')
environment:
name: nuget
url: https://www.nuget.org/packages/CsmTcpRouter.Client/

permissions:
contents: read

steps:
- name: Download NuGet artifact
uses: actions/download-artifact@v4
with:
name: csharp-sdk-nupkg
path: nupkg

- name: Set up .NET 8 SDK
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'

- name: Push to NuGet.org
# NUGET_API_KEY must be configured as a secret in the `nuget`
# environment. The workflow is gated by the `csharp-sdk-v*` tag
# filter above to prevent accidental publishes.
env:
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
run: |
dotnet nuget push "nupkg/*.nupkg" \
--api-key "$NUGET_API_KEY" \
--source https://api.nuget.org/v3/index.json \
--skip-duplicate
working-directory: ${{ github.workspace }}
67 changes: 67 additions & 0 deletions .github/workflows/C_SDK.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: C SDK

on:
push:
paths:
- 'SDK/c/**'
- '.github/workflows/C_SDK.yml'
tags:
- 'c-sdk-v*'
pull_request:
paths:
- 'SDK/c/**'
- '.github/workflows/C_SDK.yml'
workflow_dispatch:

defaults:
run:
working-directory: SDK/c

jobs:
# -------------------------------------------------------------------------
# Build & test on Linux, macOS, and Windows.
# -------------------------------------------------------------------------
build-test:
name: Build & test (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
permissions:
contents: read
steps:
- uses: actions/checkout@v4

- name: Configure (CMake)
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release

- name: Build
run: cmake --build build --config Release -j

- name: Run tests (ctest)
run: ctest --test-dir build --output-on-failure -C Release

# -------------------------------------------------------------------------
# Sanitizer build on Linux to catch undefined behaviour, leaks, and races.
# -------------------------------------------------------------------------
sanitizers:
name: Sanitizers (Linux)
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4

- name: Configure with ASan + UBSan
run: |
cmake -S . -B build-san \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_C_FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer -O1 -g" \
-DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address,undefined"

- name: Build (sanitizers)
run: cmake --build build-san -j

- name: Run tests (sanitizers)
run: ctest --test-dir build-san --output-on-failure
Loading
Loading