Files
histsdk/docs/reverse-engineering/wcf-event-read-spike-results.md
T
Joseph Doherty f1c57f7149 docs(c2): record WCF event-read spike live result (RED — transport not served on 2023 R2)
WCF net.tcp (RemoteTcpIntegrated) against the live 2023 R2 historian is reset
at the socket-write/framing layer before any auth — both the event spike and a
basic Probe/ReadRaw throw the identical CommunicationException/SocketException
("forcibly closed by the remote host"). The 2023 R2 box does not serve the
legacy WCF transport; C2's "route via WCF" unblock is moot on this server class.
Sanitized: counts + native return codes + buffer lengths only.

Claude-Session: https://claude.ai/code/session_012SDSQ3AcaXqPcBtDESBRii
2026-06-25 16:58:56 -04:00

64 lines
3.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# WCF event-read spike — live result (2026-06-25): WCF transport not served on 2023 R2
Settles the open question behind **C2** ("event reads over gRPC are gated; the only listed unblock is
*route event reads via WCF*"). The gRPC event-read path is a proven server-side dead-end
(`grpc-event-query-capture.md`: auth fully solved, every client-controllable layer byte-matched to the
stock client, yet the server scopes 0 rows to our connection). This spike tested the **WCF** leg.
## What was run
A Windows-only, env-gated diagnostic (`tests/AVEVA.Historian.Client.Tests/WcfEventReadSpikeTests.cs`,
gated by `HISTORIAN_WCF_EVENT_HOST`) drove `HistorianWcfEventOrchestrator.ReadEventsAsync` directly
over `RemoteTcpIntegrated` (WCF `net.tcp`, port 32568) against the **live 2023 R2 historian**, with a
90d window (the engine holds tens of thousands of events in that range), run from the native Windows
capture rig over VPN. Auth supplied as explicit domain credentials (consumed by the app-level
`ValidateClientCredential` SSPI rounds).
## Result — RED (transport not served), sanitized
Event spike:
| field | value |
|---|---|
| outcome | `THREW System.ServiceModel.CommunicationException` ("The socket connection was aborted") |
| inner | `System.Net.Sockets.SocketException` — "An existing connection was forcibly closed by the remote host" |
| events observed | 0 |
| LastUpdC3ReturnCode / LastRTag2ReturnCode / LastAddReturnCode(EnsT2) | 0 / 0 / 0 |
| LastEnsT2PayloadSha256 | empty |
| LastResultBufferLength | 0 |
All native return codes are `0` and the EnsT2 payload sha256 is empty: the chain failed at the **first
WCF call** (`GetInterfaceVersion`), *before* any auth token round or CM_EVENT registration ran.
Corroboration — a basic (non-event) `RemoteTcpIntegrated` `ProbeAsync` + `ReadRawAsync` (the committed
`RemoteTcpIntegrationTests`) throws the **identical** exception, with the stack landing in
`System.ServiceModel.Channels.SocketConnection.WriteAsync` — i.e. the failure is **transport-wide**, not
event-specific, and not auth-specific (it never reaches auth).
Phase 0 (reachability) had confirmed TCP 32568 is **open** (the connect succeeds). So the port accepts a
socket, but the moment the SDK writes its `net.tcp` binary-SOAP framing the server **resets the
connection** (RST at the socket-write layer).
## Conclusion
The **2023 R2 historian does not serve the legacy WCF NetTcp transport.** A raw RST at the first socket
write — before any security negotiation, SOAP fault, or auth exchange — is the signature of a listener
that does not speak `net.tcp` binary SOAP, not of an auth/SPN problem or event-row scoping. (The earlier
WCF event-chain native return codes 76/85 documented in `HistorianWcfEventOrchestrator` were only ever
observed against a **2020** historian; against 2023 R2 there is no WCF endpoint to reach at all.)
Therefore **C2's "route event reads via WCF" unblock is moot on 2023 R2** — there is no WCF endpoint to
route to. Event reads are unavailable on the 2023 R2 historian over **both** transports:
- **gRPC** — auth-solved but retrieval-server-gated (server scopes 0 rows to our connection;
`grpc-event-query-capture.md`).
- **WCF (`net.tcp`)** — transport not served on 2023 R2 (connection reset at framing).
The WCF event-read managed path would only ever apply to a legacy **2020** historian, which the gateway
does not target (the gateway runs `RemoteGrpc` against 2023 R2). The only remaining theoretical unblock
is server-side (AVEVA exposing event-row retrieval to a managed gRPC connection) — not client-fixable.
**C2 is closed won't-fix** for the gateway's target (2023 R2). `ReadEventsAsync` over gRPC keeps its
honest no-row throw; the gating messages are corrected so they no longer point operators at the WCF
transport as a live fallback on 2023 R2.