Files
mxaccess/rust
Joseph Doherty 983f02921c
rust / build / test / clippy / fmt (push) Has been cancelled
asb-subscribe example: drive every canonical-XML signed op live
Extends the example to exercise the full data-plane through the
new canonical-XML signing path (F28 step 2). Each op is announced
with a "[canonical XML <Op>]" tag in the trace so the lifecycle is
self-documenting:

  Connect → Register → Read → Write → CreateSubscription
  → AddMonitoredItems → Publish × N → PublishWriteComplete
  → DeleteMonitoredItems → DeleteSubscription
  → UnregisterItems → Disconnect → SendEnd

Per-section errors are caught and logged but don't abort the
lifecycle — a failed Publish still reaches Disconnect cleanly so
the server-side pending-connection table doesn't fill up.

New env vars MX_RUN_WRITE / MX_RUN_SUBSCRIBE / MX_SUBSCRIBE_COUNT
(defaults: run, run, 3) for opting into / sizing the optional steps.

Live verification on this host (this turn, first run):
  register status: 1 item(s); result_code=Some(0) success=Some(true)
  TestChildObject.TestInt = AsbVariant{type_id:4,length:4,payload:[99]}
  write status: 0 item(s); result_code=Some(0) success=Some(true)
  subscription_id=2 result_code=Some(0) success=Some(true)
  add status: 0 item(s); result_code=Some(0) success=Some(true)
  publish: 0 value(s); result_code=Some(32) success=Some(false)
  publish_write_complete: 0 write(s); result_code=Some(0)
  delete_monitored_items ok
  delete_subscription ok
  unregistering ... disconnecting

All 13 canonical-XML-signed ops accepted by MxDataProvider — no SOAP
faults, no HMAC rejections, no decode errors. F28 step 2 verified
end-to-end against the live AVEVA install.

Bonus fix: F26 stream's publish_loop bail logic narrowed.
The original F33 bail-on-any-non-zero-result_code was over-aggressive:
.NET's MxAsbClient.Probe shows that result_code=32 (= 0x20) fires on
*every* Publish poll while values are still being delivered. Updated
publish_loop and the example's Publish loop to bail only on
RESULT_CODE_INVALID_CONNECTION_ID (1) — that one truly means the
session is desynced. Other non-zero result_codes are informational
and the loop continues draining.

New public re-export: mxaccess_asb::RESULT_CODE_INVALID_CONNECTION_ID
(was crate-private under the operations module).

The InvalidConnectionId transient still hits after many back-to-back
test runs against a long-running MxDataProvider — the pending-
connection table fills up — same well-documented behaviour from F32.
A 30-second cool-down restores reliability in our experience.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 02:19:47 -04:00
..

mxaccess (Rust port)

Native Rust replacement for AVEVA / Wonderware MXAccess. See ../design/ for the architectural specification, ../src/ for the .NET reference (the executable spec), and ../CLAUDE.md for project-wide rules.

Status

M0 — Workspace skeleton. Stub types compile; nothing is implemented yet. See ../design/60-roadmap.md for the M0M6 milestone plan.

Layout

rust/
  Cargo.toml                 workspace root
  rust-toolchain.toml        1.85 stable
  crates/
    mxaccess-codec/          pure protocol codec, no I/O
    mxaccess-galaxy/         Galaxy SQL resolver (tiberius)
    mxaccess-rpc/            DCE/RPC + NTLMv2 + OXID + OBJREF
    mxaccess-callback/       INmxSvcCallback RPC server
    mxaccess-nmx/            INmxService2 client
    mxaccess-asb-nettcp/     net.tcp framing (MC-NMF + MC-NBFX/NBFS)
    mxaccess-asb/            IASBIDataV2 client
    mxaccess/                async session + Transport trait + public API
    mxaccess-compat/         LMXProxyServer-shaped facade

Build

cargo build --workspace
cargo test --workspace
cargo clippy --workspace -- -D warnings
cargo fmt --check

Live probes

. ..\tools\Setup-LiveProbeEnv.ps1
cargo test -p mxaccess --features live -- --ignored

The setup script fetches credentials from Infisical via wwtools/secrets/Get-Secret.ps1. Never inline plaintext credentials.

License

MIT — see ../LICENSE.