Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
a2b680a
Prepare current-main embedded profile for static MMS server
masarray Aug 11, 2026
747b675
Prepare current-main build for static MMS server
masarray Aug 11, 2026
a5a5083
Adopt no-throw UTC decode primitive for MMS server
masarray Aug 11, 2026
c0ff55d
Adopt no-throw UTC implementation for MMS server
masarray Aug 11, 2026
bc10c4b
Port clean static MMS server onto current main
masarray Aug 11, 2026
dcfa61e
Port cumulative BRCB R1-R3 server runtime
masarray Aug 11, 2026
2073fc6
Wire BRCB R1-R3 into embedded aggregate profile
masarray Aug 11, 2026
991a584
Wire BRCB R1-R3 into public MMS server core
masarray Aug 11, 2026
f0fb8a6
Fix static server object initializers after contextual writes
masarray Aug 11, 2026
a5eb9aa
Port static IED host adapter to current server runtime
masarray Aug 11, 2026
7597a90
Fix local DataSet span initialization portability
masarray Aug 11, 2026
0912927
Make socket runtime RAII portable under warnings-as-errors
masarray Aug 11, 2026
3606f62
Bind BRCB delivery to owner and defer commit
masarray Aug 11, 2026
7b927ef
Enforce owner-bound two-phase BRCB delivery
masarray Aug 11, 2026
233dc79
Prove owner-bound two-phase BRCB delivery
masarray Aug 11, 2026
8f2a013
Close MMS runtime on every terminal server session path
masarray Aug 11, 2026
22812f7
Prove terminal server session closes established association
masarray Aug 11, 2026
76563ab
Recover BRCB checkpoint from surviving A/B bank
masarray Aug 11, 2026
22eef13
Add one-bank BRCB checkpoint recovery regression
masarray Aug 11, 2026
907f516
Extend BRCB hard profile safety regressions
masarray Aug 11, 2026
b39a688
Isolate static MMS server from legacy core
masarray Aug 11, 2026
48efffd
Ignore POSIX SIGPIPE in static server host process
masarray Aug 11, 2026
f47017c
Wire host SIGPIPE guard into static server
masarray Aug 11, 2026
79d6fb0
Reauthorize owner on BRCB delivery commit
masarray Aug 11, 2026
dbc5ced
Fix BRCB two-phase commit authorization signature
masarray Aug 11, 2026
c753f66
Update BRCB delivery smoke for owner-bound commit API
masarray Aug 11, 2026
f67bba8
Merge current main into server consolidation
masarray Aug 11, 2026
7635fb7
Restore current-main live signal test in merged CMake
masarray Aug 11, 2026
35fe7ab
Track negotiated peer response limits
masarray Aug 11, 2026
68b0189
Enforce negotiated COTP and MMS response limits
masarray Aug 11, 2026
988eae0
Fail closed on negotiated peer limit overflow
masarray Aug 11, 2026
bd9a581
Expose BRCB peer-limit result
masarray Aug 11, 2026
a228dde
Enforce negotiated limits on BRCB delivery
masarray Aug 11, 2026
5f8ead9
Add negotiated response limit regression
masarray Aug 11, 2026
f4328d4
Run negotiated response limit smoke in embedded profile
masarray Aug 11, 2026
29e4996
Run negotiated limit regression through public server core
masarray Aug 11, 2026
7c17778
Prove negotiated limits under BRCB hard profile
masarray Aug 11, 2026
40bcc3f
Fix static server smoke command and capability scope
masarray Aug 11, 2026
42073d5
Fix negotiated limit smoke span view
masarray Aug 11, 2026
ec47fed
Advertise only implemented MMS services
masarray Aug 11, 2026
b6fe0b4
Remove duplicated ACSE external decode branch
masarray Aug 11, 2026
25831b4
Add confirmed-request Reject PDU encoder
masarray Aug 11, 2026
e060588
Encode bounded MMS confirmed-request Reject PDU
masarray Aug 11, 2026
7726e58
Return MMS RejectPDU for unsupported confirmed requests
masarray Aug 11, 2026
6e7ac5b
Make static server socket waits interruptible
masarray Aug 11, 2026
fe4c8cb
Assert narrow MMS service advertisement
masarray Aug 11, 2026
0c7512a
Update MMS PDU smoke for narrow services and RejectPDU
masarray Aug 11, 2026
eeebca8
Expect RejectPDU for unsupported confirmed request
masarray Aug 11, 2026
f000772
Port ARIEC61850 server discovery and wire parity (#61)
masarray Aug 11, 2026
05b64e6
Honor negotiated MMS server limits (#67)
masarray Aug 11, 2026
3adc52c
Return ConfirmedError for missing MMS objects
masarray Aug 11, 2026
acaca94
Regress strict missing-object ConfirmedError
masarray Aug 11, 2026
0ffce10
Keep strict ConfirmedError inside bounded runtime
masarray Aug 11, 2026
8a189fa
Merge current main PTP runtime into server consolidation
masarray Aug 11, 2026
3839587
Merge latest main ARStack Studio updates into server consolidation
masarray Aug 11, 2026
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
90 changes: 90 additions & 0 deletions .github/workflows/brcb-hard-profile-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: BRCB Hard Profile CI

on:
push:
branches:
- main
pull_request:

permissions:
contents: read

jobs:
brcb-hard-profile:
name: BRCB Hard / ${{ matrix.compiler }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
compiler: [gcc, clang]

steps:
- uses: actions/checkout@v4

- name: Select compiler
shell: bash
run: |
if [ "${{ matrix.compiler }}" = "clang" ]; then
echo "CC=clang" >> "$GITHUB_ENV"
echo "CXX=clang++" >> "$GITHUB_ENV"
else
echo "CC=gcc" >> "$GITHUB_ENV"
echo "CXX=g++" >> "$GITHUB_ENV"
fi

- name: Configure BRCB hard profile
run: cmake -S embedded/brcb_hard_profile -B build-brcb-hard

- name: Build BRCB hard profile
run: cmake --build build-brcb-hard --parallel

- name: Run BRCB smokes
run: >-
ctest --test-dir build-brcb-hard
--output-on-failure
--output-junit brcb-ctest.xml

- name: Prove exception runtime is absent
shell: bash
run: |
set -euo pipefail
for binary in \
build-brcb-hard/ariec61850_hard_mms_brcb_smoke \
build-brcb-hard/ariec61850_hard_mms_brcb_control_smoke \
build-brcb-hard/ariec61850_hard_mms_brcb_objects_smoke \
build-brcb-hard/ariec61850_hard_mms_brcb_lifecycle_smoke \
build-brcb-hard/ariec61850_hard_mms_brcb_connection_smoke \
build-brcb-hard/ariec61850_hard_mms_brcb_recovery_v2_smoke \
build-brcb-hard/ariec61850_hard_mms_brcb_persistence_smoke; do
if nm -C "$binary" | grep -E '__cxa_throw|__cxa_begin_catch|__cxa_end_catch|__gxx_personality_v0'; then
echo "exception runtime symbol found in $binary" >&2
exit 1
fi
done
echo 'NO_EXCEPTION_RUNTIME=PASS'

- name: Report footprint
shell: bash
run: |
set -euo pipefail
{
echo "compiler=${{ matrix.compiler }}"
size \
build-brcb-hard/ariec61850_hard_mms_brcb_smoke \
build-brcb-hard/ariec61850_hard_mms_brcb_control_smoke \
build-brcb-hard/ariec61850_hard_mms_brcb_objects_smoke \
build-brcb-hard/ariec61850_hard_mms_brcb_lifecycle_smoke \
build-brcb-hard/ariec61850_hard_mms_brcb_connection_smoke \
build-brcb-hard/ariec61850_hard_mms_brcb_recovery_v2_smoke \
build-brcb-hard/ariec61850_hard_mms_brcb_persistence_smoke
} | tee build-brcb-hard/brcb-footprint.txt

- name: Upload BRCB evidence
uses: actions/upload-artifact@v4
with:
name: brcb-hard-${{ matrix.compiler }}-${{ github.event.pull_request.head.sha || github.sha }}
if-no-files-found: error
retention-days: 14
path: |
build-brcb-hard/brcb-ctest.xml
build-brcb-hard/brcb-footprint.txt
61 changes: 61 additions & 0 deletions .github/workflows/mms-r12-server-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: MMS R1-R2 Server CI

on:
pull_request:
paths:
- 'include/ariec61850/acse/**'
- 'include/ariec61850/mms/**'
- 'src/acse/**'
- 'src/mms/**'
- 'tools/mms_direct_control_server.cpp'
- 'tools/mms_urcb_server.cpp'
- 'tools/mms_direct_control_server/**'
- 'tests/test_mms_static_direct_control.cpp'
- 'tests/test_mms_server_urcb_report.cpp'
- 'scripts/build_mms_direct_control_server.ps1'
- '.github/workflows/mms-r12-server-ci.yml'
workflow_dispatch:

permissions:
contents: read

jobs:
linux:
name: Linux ${{ matrix.compiler }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
compiler: [gcc, clang]
steps:
- uses: actions/checkout@v4
- name: Select compiler
shell: bash
run: |
if [[ "${{ matrix.compiler }}" == "clang" ]]; then
echo "CC=clang" >> "$GITHUB_ENV"
echo "CXX=clang++" >> "$GITHUB_ENV"
else
echo "CC=gcc" >> "$GITHUB_ENV"
echo "CXX=g++" >> "$GITHUB_ENV"
fi
- name: Configure
run: cmake -S tools/mms_direct_control_server -B build-mms-r12 -DCMAKE_BUILD_TYPE=Release
- name: Build
run: cmake --build build-mms-r12 --parallel
- name: Test
run: ctest --test-dir build-mms-r12 --output-on-failure
- name: Help contracts
shell: bash
run: |
./build-mms-r12/ariec61850_mms_direct_control_server --help
./build-mms-r12/ariec61850_mms_urcb_server --help

windows:
name: Windows MSVC
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Configure, build, test and locate executables
shell: powershell
run: .\scripts\build_mms_direct_control_server.ps1 -BuildDir build-mms-r12
104 changes: 103 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,46 @@ add_library(ariec61850_core

add_library(ARIEC61850::core ALIAS ariec61850_core)

add_library(ariec61850_mms_server_core
src/asn1/ber_span_reader.cpp
src/osi/tpkt_span.cpp
src/osi/cotp_span.cpp
src/osi/session_span.cpp
src/osi/presentation_span.cpp
src/acse/association_span.cpp
src/mms/pdu_span.cpp
src/mms/services_span.cpp
src/mms/write_span.cpp
src/mms/data_set_span.cpp
src/mms/information_report_span.cpp
src/mms/buffered_selective_information_report_span.cpp
src/mms/static_object_table.cpp
src/mms/static_write.cpp
src/mms/static_data_set_table.cpp
src/mms/static_dispatcher.cpp
src/mms/connection_runtime.cpp
src/mms/static_server_session.cpp
src/mms/static_brcb_runtime.cpp
src/mms/static_brcb_control.cpp
src/mms/static_brcb_objects.cpp
src/mms/static_brcb_connection.cpp
src/mms/static_brcb_checkpoint_store.cpp
src/mms/static_brcb_state_codec.cpp)

add_library(ARIEC61850::mms_server_core ALIAS ariec61850_mms_server_core)

target_compile_features(ariec61850_core PUBLIC cxx_std_20)
target_include_directories(ariec61850_core
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)

target_compile_features(ariec61850_mms_server_core PUBLIC cxx_std_20)
target_include_directories(ariec61850_mms_server_core
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)

if(WIN32)
target_link_libraries(ariec61850_core PRIVATE ws2_32)
endif()
Expand Down Expand Up @@ -107,6 +141,8 @@ endfunction()

ariec61850_apply_warnings(ariec61850_core)
ariec61850_apply_sanitizers(ariec61850_core)
ariec61850_apply_warnings(ariec61850_mms_server_core)
ariec61850_apply_sanitizers(ariec61850_mms_server_core)

if(ARIEC61850_BUILD_TOOLS)
add_executable(ariec61850_pcap_interop_check tools/pcap_interop_check.cpp)
Expand Down Expand Up @@ -156,6 +192,20 @@ if(ARIEC61850_BUILD_TOOLS)
target_compile_features(ariec61850_file_transfer PRIVATE cxx_std_20)
ariec61850_apply_warnings(ariec61850_file_transfer)
ariec61850_apply_sanitizers(ariec61850_file_transfer)

add_executable(
ariec61850_static_ied_server
tools/static_ied_server.cpp
tools/static_ied_server_sigpipe.cpp)
target_link_libraries(
ariec61850_static_ied_server
PRIVATE ARIEC61850::mms_server_core)
if(WIN32)
target_link_libraries(ariec61850_static_ied_server PRIVATE ws2_32)
endif()
target_compile_features(ariec61850_static_ied_server PRIVATE cxx_std_20)
ariec61850_apply_warnings(ariec61850_static_ied_server)
ariec61850_apply_sanitizers(ariec61850_static_ied_server)
endif()

if(ARIEC61850_BUILD_TESTS)
Expand Down Expand Up @@ -337,6 +387,55 @@ if(ARIEC61850_BUILD_TESTS)
ariec61850_apply_sanitizers(ariec61850_fuzz_smoke_tests)
add_test(NAME ariec61850_fuzz_smoke_tests COMMAND ariec61850_fuzz_smoke_tests)

add_executable(
ariec61850_mms_server_session_tests
tests/test_mms_static_server_session.cpp)
target_link_libraries(
ariec61850_mms_server_session_tests
PRIVATE ARIEC61850::mms_server_core)
target_compile_features(
ariec61850_mms_server_session_tests PRIVATE cxx_std_20)
ariec61850_apply_warnings(ariec61850_mms_server_session_tests)
ariec61850_apply_sanitizers(ariec61850_mms_server_session_tests)
add_test(
NAME ariec61850_mms_server_session_tests
COMMAND ariec61850_mms_server_session_tests)

add_executable(
ariec61850_mms_connection_runtime_tests
embedded/mms_connection_runtime_hard_profile_smoke.cpp)
target_link_libraries(
ariec61850_mms_connection_runtime_tests
PRIVATE ARIEC61850::mms_server_core)
target_compile_features(
ariec61850_mms_connection_runtime_tests PRIVATE cxx_std_20)
ariec61850_apply_warnings(ariec61850_mms_connection_runtime_tests)
ariec61850_apply_sanitizers(ariec61850_mms_connection_runtime_tests)
add_test(
NAME ariec61850_mms_connection_runtime_tests
COMMAND ariec61850_mms_connection_runtime_tests)

foreach(brcb_smoke IN ITEMS
mms_brcb
mms_brcb_control
mms_brcb_connection
mms_brcb_objects
mms_brcb_lifecycle
mms_brcb_persistence
mms_brcb_recovery_v2
mms_brcb_checkpoint_fallback
mms_negotiated_limits)
set(brcb_target "ariec61850_${brcb_smoke}_server_core_tests")
add_executable(
${brcb_target}
${CMAKE_CURRENT_SOURCE_DIR}/embedded/${brcb_smoke}_hard_profile_smoke.cpp)
target_link_libraries(${brcb_target} PRIVATE ARIEC61850::mms_server_core)
target_compile_features(${brcb_target} PRIVATE cxx_std_20)
ariec61850_apply_warnings(${brcb_target})
ariec61850_apply_sanitizers(${brcb_target})
add_test(NAME ${brcb_target} COMMAND ${brcb_target})
endforeach()

if(ARIEC61850_BUILD_TOOLS)
add_test(
NAME ariec61850_pcap_interop_smoke
Expand All @@ -357,6 +456,9 @@ if(ARIEC61850_BUILD_TESTS)
add_test(
NAME ariec61850_file_transfer_help
COMMAND ariec61850_file_transfer --help)
add_test(
NAME ariec61850_static_ied_server_help
COMMAND ariec61850_static_ied_server --help)
endif()
endif()

Expand Down Expand Up @@ -388,4 +490,4 @@ if(ARIEC61850_BUILD_FUZZERS)
ariec61850_add_fuzzer(ariec61850_fuzz_mms_services fuzz/fuzz_mms_services.cpp)
ariec61850_add_fuzzer(ariec61850_fuzz_mms_file_service fuzz/fuzz_mms_file_service.cpp)
ariec61850_add_fuzzer(ariec61850_fuzz_reporting fuzz/fuzz_reporting.cpp)
endif()
endif()
80 changes: 80 additions & 0 deletions docs/STATIC_IED_SERVER.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Static IEC 61850 server foundation

`ariec61850_static_ied_server` is the first runnable desktop adapter for the
bounded MMS server core. It deliberately keeps platform networking outside the
protocol engine, matching the same boundary required by ESP-IDF/lwIP.

```text
TCP listen/accept (WinSock or BSD sockets)
-> connected TcpByteStream callbacks
-> MmsStaticServerSession fixed-buffer pump
-> MmsStaticConnectionRuntime
-> MmsStaticApplicationDispatcher
-> static object/DataSet tables
```

The included desktop reference model is read-only:

```text
ESP32S3IOLD0
|- LLN0 Mod.stVal
|- LPHD1 PhyHealth.stVal
`- GGIO1 Ind1.stVal ... Ind8.stVal
```

## Desktop smoke run

Build with `ARIEC61850_BUILD_TOOLS=ON`, then run an unprivileged development
endpoint such as port 8102:

```powershell
.\ariec61850_static_ied_server.exe --port 8102 --digital-input-mask 0x35 --max-connections 1
```

The executable default is TCP port **102**, the standard IEC 61850 MMS port.
Use `--port 8102` when local permissions or another process prevent binding
port 102. `--digital-input-mask` defaults to `0x35`; `--max-connections 0`
means unlimited sequential accepts.

Implemented server services in this slice:

- COTP connection accept with negotiated TPDU-size bounds;
- ACSE association accept and MMS Initiate response with the peer MMS PDU limit
retained and enforced on outbound confirmed responses;
- `GetNameList`;
- `GetVariableAccessAttributes`;
- `GetNamedVariableListAttributes` when a static DataSet table is supplied;
- `Read`;
- bounded `Write` only for object entries that explicitly provide a write
callback (the included desktop model provides none).

The public `ARIEC61850::mms_server_core` also contains the bounded BRCB R1-R3
runtime, ownership/lifecycle objects, retained replay/recovery, and negotiated
outbound-limit enforcement for InformationReport delivery. The current
`ariec61850_static_ied_server` reference model does **not** yet instantiate or
schedule those BRCB objects, so a desktop IEDScout browse/read pass must not be
reported as live BRCB interoperability.

## ESP32/lwIP integration boundary

The protocol core does not include an ESP-IDF header or own a listening socket.
An ESP-IDF application accepts a TCP/102 connection through lwIP, supplies
`TcpSendFn`/`TcpReceiveFn` callbacks, gives each connection its own
`MmsStaticConnectionRuntime`, `MmsStaticServerSession`, and fixed buffers, then
calls `poll_once()` from its task or event loop. Buffer capacities and the
maximum concurrent association count remain product-profile decisions.

## Current limits

- The desktop adapter serves connections sequentially. The core is per-session
and supports platform-owned multi-client orchestration, but the adapter does
not yet schedule multiple clients concurrently.
- Physical IEDScout browse/read acceptance is not yet recorded.
- The reference values are startup constants; a board adapter still needs to
bind the eight GGIO values to debounced input snapshots.
- The desktop reference adapter does not yet expose BRCB reporting or control
objects even though the server core contains those bounded primitives.
- Authentication, TLS, file services, runtime SCL model loading, and outbound
COTP segmentation are not implemented in this reference adapter. Responses
that cannot fit the negotiated peer TPDU/MMS limits fail closed instead of
emitting an oversized frame.
Loading
Loading