f1c57f7149
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
64 lines
3.8 KiB
Markdown
64 lines
3.8 KiB
Markdown
# 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.
|