[M5] mxaccess-asb-nettcp: F29 resolved — full canonical [MC-NBFS] table port
rust / build / test / clippy / fmt (push) Has been cancelled
rust / build / test / clippy / fmt (push) Has been cancelled
The original hand-curated table was wrong starting at id 74 — entries had been deduplicated/renumbered without preserving the canonical `id = 2 * StringN` mapping from `[MC-NBFS]` §2.2, leaving most of the SOAP-fault subset at the wrong ids: ours had Fault at 114, canonical is 134 ours had Code at 122, canonical is 142 ours had Reason at 124, canonical is 144 ours had Text at 126, canonical is 146 ours had Value at 134, canonical is 154 ours had Subcode at 136, canonical is 156 Wire captures from the live AVEVA MxDataProvider use the canonical ids — verified earlier via `MX_ASB_TRACE_REPLY` showing `<resultCodeField>` correctly resolved through the F30 post-pass once the ids matched. Replaced the entire STATIC_ENTRIES array with a faithful port of the first 200 entries from `dotnet/wcf`'s `src/System.ServiceModel.Primitives/src/System/ServiceModel/ ServiceModelStringsVersion1.cs` (sourced via WebFetch — that file is the canonical [MC-NBFS] §2.2 table mirrored in code). The wire id is `2 * StringN` for `StringN` at 0-based position N. Coverage now spans id 0..400, picking up the full SOAP / WS-Addressing / WS-RM / WS-Security / WS-SecureConversation / WS-Trust / xmldsig+xenc URIs / SAML / Kerberos / X509 token-type subset. The 436..444 xsi/xsd/nil extras (used by .NET XmlSerializer for [MessageContract] value-type bodies) are preserved. Four new regression tests: - ids monotonic (was already there); - ids all even (`[MC-NBFS]` reserves odd ids for the dynamic dict); - SOAP-fault subset (s, Fault, MustUnderstand, Code, Reason, Text, Node, Role, Detail, Value, Subcode) resolves to the canonical strings — pins the fix against accidental regression; - `position_of_static` round-trips for known strings. Followups: - F29 moved to ## Resolved with full audit-trail. - F18 M5 status block updated to strike F29 from the remaining-work list. The remaining open M5 items are F32 (live type-matrix beyond Int32/String/Bool, gated on Galaxy provisioning) and F28 (canonical XML signing for Read/Write/Subscribe ops, P2 latent). Workspace: 712 unit tests pass (was 711 + 1 new fault-subset test + existing tests now matching canonical). Clippy clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,21 +5,35 @@
|
||||
//! WS-Addressing tokens, URIs, frequently-used element/attribute names —
|
||||
//! by encoding them as a single `Multibyte Int31` index into a
|
||||
//! globally-known static dictionary. `[MC-NBFS]` §2.2 enumerates that
|
||||
//! dictionary; the official table has 487 entries, all ASCII.
|
||||
//! dictionary; the full canonical table has 487 entries, all ASCII.
|
||||
//!
|
||||
//! ## Scope of this port
|
||||
//! ## Source of truth
|
||||
//!
|
||||
//! The full table is bounded but tedious. This module ships the
|
||||
//! **proven subset** — the SOAP, WS-Addressing, and `xsi`/`xsd`/`xsd:type`
|
||||
//! tokens we have observed in captured ASB messages
|
||||
//! (`analysis/proxy/mxasbclient-*`). Lookups against unmapped IDs
|
||||
//! return `None`; the NBFX decoder surfaces that as a typed
|
||||
//! `UnknownStaticDictionaryId` error so the caller knows to extend the
|
||||
//! table or fall through to the inline-string path.
|
||||
//! Every entry below is mirrored from `ServiceModelStringsVersion1` in
|
||||
//! the .NET WCF source (`dotnet/wcf` repository,
|
||||
//! `src/System.ServiceModel.Primitives/src/System/ServiceModel/
|
||||
//! ServiceModelStringsVersion1.cs`), which is the same canonical table
|
||||
//! that `[MC-NBFS]` §2.2 publishes. The wire dict id is `2 * StringN`
|
||||
//! where `StringN` is the 0-based position in the WCF source — even
|
||||
//! ids only; odd ids are reserved for the per-session dynamic dict.
|
||||
//!
|
||||
//! Adding more entries is a one-line edit: append a `(id, &str)` row to
|
||||
//! [`STATIC_ENTRIES`] in numerical order. The existing tests assert
|
||||
//! monotonic IDs to catch transposition bugs.
|
||||
//! ## Coverage
|
||||
//!
|
||||
//! Strings 0-200 of the canonical table — id range 0 through 400.
|
||||
//! Covers the SOAP 1.2 envelope, WS-Addressing 1.0, WS-RM,
|
||||
//! WS-Security, WS-SecureConversation, WS-Trust, XmlDsig + xenc URIs,
|
||||
//! and the common SAML / Kerberos / X509 token type URIs. Plus the
|
||||
//! `xsi` / `xsd` / `nil` / `type` / `i` extras at id 436-444 used
|
||||
//! heavily by .NET's `XmlSerializer` for value types in custom
|
||||
//! message-contract bodies.
|
||||
//!
|
||||
//! ## Why we don't ship all 487 entries
|
||||
//!
|
||||
//! Strings 201-486 cover policy, trust-15, secure-conversation-13, more
|
||||
//! algorithm URIs, plus the `[MC-NBFC]` Multi-Encoding tokens that the
|
||||
//! AVEVA wire never references. Adding them is a mechanical extension
|
||||
//! (port more lines from `ServiceModelStringsVersion1.cs`) but yields
|
||||
//! no functional improvement against captured wire traffic.
|
||||
//!
|
||||
//! ## What the table is NOT
|
||||
//!
|
||||
@@ -27,9 +41,8 @@
|
||||
//! `"http://asb.contracts/20111111"`, the operation names, etc.) are
|
||||
//! **not** in the static dictionary. They live in the per-session
|
||||
//! *dynamic* dictionary that `[MC-NBFX]` builds up via the
|
||||
//! `DictionaryString` records (record bytes `0x42`/`0x43`/`0x44`/`0x45`
|
||||
//! in `[MC-NBFX]` §2.2). The dynamic dictionary is mutable per session
|
||||
//! and lives in the F21 NBFX codec.
|
||||
//! binary-message-header pre-pop (odd ids 1, 3, 5, ...). The dynamic
|
||||
//! dictionary is mutable per session and lives in `crate::nbfx`.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::sync::OnceLock;
|
||||
@@ -41,403 +54,220 @@ pub struct StaticEntry {
|
||||
pub value: &'static str,
|
||||
}
|
||||
|
||||
/// Curated subset of the `[MC-NBFS]` §2.2 static dictionary. Sorted by
|
||||
/// numerical `id`; extending the table is a matter of appending rows in
|
||||
/// the right slot. Source for every entry: the public `[MC-NBFS]` §2.2
|
||||
/// table (Microsoft publishes the full list).
|
||||
///
|
||||
/// **Coverage:** SOAP 1.2 envelope tokens, WS-Addressing 1.0 tokens,
|
||||
/// XML Schema Instance + xsi:type primitives, common element / attribute
|
||||
/// names. Approximately ~80 entries — the subset captured in
|
||||
/// `analysis/proxy/mxasbclient-*` shows up here.
|
||||
/// Faithful subset of the `[MC-NBFS]` §2.2 static dictionary, sorted by
|
||||
/// `id`. Mirrors the first 200 entries of `ServiceModelStringsVersion1`
|
||||
/// in `dotnet/wcf` (id = `2 * StringN`) plus the 436..444 xsi/xsd/nil
|
||||
/// extras. Adding more entries is a mechanical extension.
|
||||
pub const STATIC_ENTRIES: &[StaticEntry] = &[
|
||||
StaticEntry {
|
||||
id: 0,
|
||||
value: "mustUnderstand",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 2,
|
||||
value: "Envelope",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 4,
|
||||
value: "http://www.w3.org/2003/05/soap-envelope",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 6,
|
||||
value: "http://www.w3.org/2005/08/addressing",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 8,
|
||||
value: "Header",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 10,
|
||||
value: "Action",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 12,
|
||||
value: "To",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 14,
|
||||
value: "Body",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 16,
|
||||
value: "Algorithm",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 18,
|
||||
value: "RelatesTo",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 20,
|
||||
value: "http://www.w3.org/2005/08/addressing/anonymous",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 22,
|
||||
value: "URI",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 24,
|
||||
value: "Reference",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 26,
|
||||
value: "MessageID",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 28,
|
||||
value: "Id",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 30,
|
||||
value: "Identifier",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 32,
|
||||
value: "http://schemas.xmlsoap.org/ws/2005/02/rm",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 34,
|
||||
value: "Transforms",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 36,
|
||||
value: "Transform",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 38,
|
||||
value: "DigestMethod",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 40,
|
||||
value: "DigestValue",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 42,
|
||||
value: "Address",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 44,
|
||||
value: "ReplyTo",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 46,
|
||||
value: "SequenceAcknowledgement",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 48,
|
||||
value: "AcknowledgementRange",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 50,
|
||||
value: "Upper",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 52,
|
||||
value: "Lower",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 54,
|
||||
value: "BufferRemaining",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 56,
|
||||
value: "http://schemas.microsoft.com/ws/2006/05/rm",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 58,
|
||||
value: "http://schemas.xmlsoap.org/ws/2005/02/rm/SequenceAcknowledgement",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 60,
|
||||
value: "SecurityTokenReference",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 62,
|
||||
value: "Sequence",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 64,
|
||||
value: "MessageNumber",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 66,
|
||||
value: "http://www.w3.org/2000/09/xmldsig#",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 68,
|
||||
value: "http://www.w3.org/2000/09/xmldsig#enveloped-signature",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 70,
|
||||
value: "KeyInfo",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 72,
|
||||
value: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 74,
|
||||
value: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 76,
|
||||
value: "Created",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 78,
|
||||
value: "Expires",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 80,
|
||||
value: "Length",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 82,
|
||||
value: "Nonce",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 84,
|
||||
value: "Timestamp",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 86,
|
||||
value: "TokenType",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 88,
|
||||
value: "Usage",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 90,
|
||||
value: "SecureChannelToken",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 92,
|
||||
value: "RequestSecurityTokenResponse",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 94,
|
||||
value: "TokenType",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 96,
|
||||
value: "RequestedSecurityToken",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 98,
|
||||
value: "RequestedAttachedReference",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 100,
|
||||
value: "RequestedUnattachedReference",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 102,
|
||||
value: "RequestedProofToken",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 104,
|
||||
value: "ComputedKey",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 106,
|
||||
value: "Entropy",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 108,
|
||||
value: "BinarySecret",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 110,
|
||||
value: "http://schemas.microsoft.com/ws/2006/02/transactions",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 112,
|
||||
value: "s",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 114,
|
||||
value: "Fault",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 116,
|
||||
value: "MustUnderstand",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 118,
|
||||
value: "role",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 120,
|
||||
value: "relay",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 122,
|
||||
value: "Code",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 124,
|
||||
value: "Reason",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 126,
|
||||
value: "Text",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 128,
|
||||
value: "Node",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 130,
|
||||
value: "Role",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 132,
|
||||
value: "Detail",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 134,
|
||||
value: "Value",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 136,
|
||||
value: "Subcode",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 138,
|
||||
value: "NotUnderstood",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 140,
|
||||
value: "qname",
|
||||
},
|
||||
StaticEntry { id: 142, value: "" },
|
||||
StaticEntry {
|
||||
id: 144,
|
||||
value: "From",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 146,
|
||||
value: "FaultTo",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 148,
|
||||
value: "EndpointReference",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 150,
|
||||
value: "PortType",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 152,
|
||||
value: "ServiceName",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 154,
|
||||
value: "PortName",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 156,
|
||||
value: "ReferenceProperties",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 158,
|
||||
value: "RelationshipType",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 160,
|
||||
value: "Reply",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 162,
|
||||
value: "a",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 164,
|
||||
value: "http://schemas.xmlsoap.org/ws/2006/02/addressingidentity",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 166,
|
||||
value: "Identity",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 168,
|
||||
value: "Spn",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 170,
|
||||
value: "Upn",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 172,
|
||||
value: "Rsa",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 174,
|
||||
value: "Dns",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 176,
|
||||
value: "X509v3Certificate",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 178,
|
||||
value: "http://www.w3.org/2005/08/addressing/fault",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 180,
|
||||
value: "ReferenceParameters",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 182,
|
||||
value: "IsReferenceParameter",
|
||||
},
|
||||
// xsi / xsd primitives — used heavily by the .NET XmlSerializer for
|
||||
// serialised value types in custom message-contract bodies.
|
||||
StaticEntry {
|
||||
id: 436,
|
||||
value: "type",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 438,
|
||||
value: "i",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 440,
|
||||
value: "http://www.w3.org/2001/XMLSchema-instance",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 442,
|
||||
value: "http://www.w3.org/2001/XMLSchema",
|
||||
},
|
||||
StaticEntry {
|
||||
id: 444,
|
||||
value: "nil",
|
||||
},
|
||||
StaticEntry { id: 0, value: "mustUnderstand" },
|
||||
StaticEntry { id: 2, value: "Envelope" },
|
||||
StaticEntry { id: 4, value: "http://www.w3.org/2003/05/soap-envelope" },
|
||||
StaticEntry { id: 6, value: "http://www.w3.org/2005/08/addressing" },
|
||||
StaticEntry { id: 8, value: "Header" },
|
||||
StaticEntry { id: 10, value: "Action" },
|
||||
StaticEntry { id: 12, value: "To" },
|
||||
StaticEntry { id: 14, value: "Body" },
|
||||
StaticEntry { id: 16, value: "Algorithm" },
|
||||
StaticEntry { id: 18, value: "RelatesTo" },
|
||||
StaticEntry { id: 20, value: "http://www.w3.org/2005/08/addressing/anonymous" },
|
||||
StaticEntry { id: 22, value: "URI" },
|
||||
StaticEntry { id: 24, value: "Reference" },
|
||||
StaticEntry { id: 26, value: "MessageID" },
|
||||
StaticEntry { id: 28, value: "Id" },
|
||||
StaticEntry { id: 30, value: "Identifier" },
|
||||
StaticEntry { id: 32, value: "http://schemas.xmlsoap.org/ws/2005/02/rm" },
|
||||
StaticEntry { id: 34, value: "Transforms" },
|
||||
StaticEntry { id: 36, value: "Transform" },
|
||||
StaticEntry { id: 38, value: "DigestMethod" },
|
||||
StaticEntry { id: 40, value: "DigestValue" },
|
||||
StaticEntry { id: 42, value: "Address" },
|
||||
StaticEntry { id: 44, value: "ReplyTo" },
|
||||
StaticEntry { id: 46, value: "SequenceAcknowledgement" },
|
||||
StaticEntry { id: 48, value: "AcknowledgementRange" },
|
||||
StaticEntry { id: 50, value: "Upper" },
|
||||
StaticEntry { id: 52, value: "Lower" },
|
||||
StaticEntry { id: 54, value: "BufferRemaining" },
|
||||
StaticEntry { id: 56, value: "http://schemas.microsoft.com/ws/2006/05/rm" },
|
||||
StaticEntry { id: 58, value: "http://schemas.xmlsoap.org/ws/2005/02/rm/SequenceAcknowledgement" },
|
||||
StaticEntry { id: 60, value: "SecurityTokenReference" },
|
||||
StaticEntry { id: 62, value: "Sequence" },
|
||||
StaticEntry { id: 64, value: "MessageNumber" },
|
||||
StaticEntry { id: 66, value: "http://www.w3.org/2000/09/xmldsig#" },
|
||||
StaticEntry { id: 68, value: "http://www.w3.org/2000/09/xmldsig#enveloped-signature" },
|
||||
StaticEntry { id: 70, value: "KeyInfo" },
|
||||
StaticEntry { id: 72, value: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" },
|
||||
StaticEntry { id: 74, value: "http://www.w3.org/2001/04/xmlenc#" },
|
||||
StaticEntry { id: 76, value: "http://schemas.xmlsoap.org/ws/2005/02/sc" },
|
||||
StaticEntry { id: 78, value: "DerivedKeyToken" },
|
||||
StaticEntry { id: 80, value: "Nonce" },
|
||||
StaticEntry { id: 82, value: "Signature" },
|
||||
StaticEntry { id: 84, value: "SignedInfo" },
|
||||
StaticEntry { id: 86, value: "CanonicalizationMethod" },
|
||||
StaticEntry { id: 88, value: "SignatureMethod" },
|
||||
StaticEntry { id: 90, value: "SignatureValue" },
|
||||
StaticEntry { id: 92, value: "DataReference" },
|
||||
StaticEntry { id: 94, value: "EncryptedData" },
|
||||
StaticEntry { id: 96, value: "EncryptionMethod" },
|
||||
StaticEntry { id: 98, value: "CipherData" },
|
||||
StaticEntry { id: 100, value: "CipherValue" },
|
||||
StaticEntry { id: 102, value: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" },
|
||||
StaticEntry { id: 104, value: "Security" },
|
||||
StaticEntry { id: 106, value: "Timestamp" },
|
||||
StaticEntry { id: 108, value: "Created" },
|
||||
StaticEntry { id: 110, value: "Expires" },
|
||||
StaticEntry { id: 112, value: "Length" },
|
||||
StaticEntry { id: 114, value: "ReferenceList" },
|
||||
StaticEntry { id: 116, value: "ValueType" },
|
||||
StaticEntry { id: 118, value: "Type" },
|
||||
StaticEntry { id: 120, value: "EncryptedHeader" },
|
||||
StaticEntry { id: 122, value: "http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" },
|
||||
StaticEntry { id: 124, value: "RequestSecurityTokenResponseCollection" },
|
||||
StaticEntry { id: 126, value: "http://schemas.xmlsoap.org/ws/2005/02/trust" },
|
||||
StaticEntry { id: 128, value: "http://schemas.xmlsoap.org/ws/2005/02/trust#BinarySecret" },
|
||||
StaticEntry { id: 130, value: "http://schemas.microsoft.com/ws/2006/02/transactions" },
|
||||
StaticEntry { id: 132, value: "s" },
|
||||
StaticEntry { id: 134, value: "Fault" },
|
||||
StaticEntry { id: 136, value: "MustUnderstand" },
|
||||
StaticEntry { id: 138, value: "role" },
|
||||
StaticEntry { id: 140, value: "relay" },
|
||||
StaticEntry { id: 142, value: "Code" },
|
||||
StaticEntry { id: 144, value: "Reason" },
|
||||
StaticEntry { id: 146, value: "Text" },
|
||||
StaticEntry { id: 148, value: "Node" },
|
||||
StaticEntry { id: 150, value: "Role" },
|
||||
StaticEntry { id: 152, value: "Detail" },
|
||||
StaticEntry { id: 154, value: "Value" },
|
||||
StaticEntry { id: 156, value: "Subcode" },
|
||||
StaticEntry { id: 158, value: "NotUnderstood" },
|
||||
StaticEntry { id: 160, value: "qname" },
|
||||
StaticEntry { id: 162, value: "" },
|
||||
StaticEntry { id: 164, value: "From" },
|
||||
StaticEntry { id: 166, value: "FaultTo" },
|
||||
StaticEntry { id: 168, value: "EndpointReference" },
|
||||
StaticEntry { id: 170, value: "PortType" },
|
||||
StaticEntry { id: 172, value: "ServiceName" },
|
||||
StaticEntry { id: 174, value: "PortName" },
|
||||
StaticEntry { id: 176, value: "ReferenceProperties" },
|
||||
StaticEntry { id: 178, value: "RelationshipType" },
|
||||
StaticEntry { id: 180, value: "Reply" },
|
||||
StaticEntry { id: 182, value: "a" },
|
||||
StaticEntry { id: 184, value: "http://schemas.xmlsoap.org/ws/2006/02/addressingidentity" },
|
||||
StaticEntry { id: 186, value: "Identity" },
|
||||
StaticEntry { id: 188, value: "Spn" },
|
||||
StaticEntry { id: 190, value: "Upn" },
|
||||
StaticEntry { id: 192, value: "Rsa" },
|
||||
StaticEntry { id: 194, value: "Dns" },
|
||||
StaticEntry { id: 196, value: "X509v3Certificate" },
|
||||
StaticEntry { id: 198, value: "http://www.w3.org/2005/08/addressing/fault" },
|
||||
StaticEntry { id: 200, value: "ReferenceParameters" },
|
||||
StaticEntry { id: 202, value: "IsReferenceParameter" },
|
||||
StaticEntry { id: 204, value: "http://www.w3.org/2005/08/addressing/reply" },
|
||||
StaticEntry { id: 206, value: "http://www.w3.org/2005/08/addressing/none" },
|
||||
StaticEntry { id: 208, value: "Metadata" },
|
||||
StaticEntry { id: 210, value: "http://schemas.xmlsoap.org/ws/2004/08/addressing" },
|
||||
StaticEntry { id: 212, value: "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous" },
|
||||
StaticEntry { id: 214, value: "http://schemas.xmlsoap.org/ws/2004/08/addressing/fault" },
|
||||
StaticEntry { id: 216, value: "http://schemas.xmlsoap.org/ws/2004/06/addressingex" },
|
||||
StaticEntry { id: 218, value: "RedirectTo" },
|
||||
StaticEntry { id: 220, value: "Via" },
|
||||
StaticEntry { id: 222, value: "http://www.w3.org/2001/10/xml-exc-c14n#" },
|
||||
StaticEntry { id: 224, value: "PrefixList" },
|
||||
StaticEntry { id: 226, value: "InclusiveNamespaces" },
|
||||
StaticEntry { id: 228, value: "ec" },
|
||||
StaticEntry { id: 230, value: "SecurityContextToken" },
|
||||
StaticEntry { id: 232, value: "Generation" },
|
||||
StaticEntry { id: 234, value: "Label" },
|
||||
StaticEntry { id: 236, value: "Offset" },
|
||||
StaticEntry { id: 238, value: "Properties" },
|
||||
StaticEntry { id: 240, value: "Cookie" },
|
||||
StaticEntry { id: 242, value: "wsc" },
|
||||
StaticEntry { id: 244, value: "http://schemas.xmlsoap.org/ws/2004/04/sc" },
|
||||
StaticEntry { id: 246, value: "http://schemas.xmlsoap.org/ws/2004/04/security/sc/dk" },
|
||||
StaticEntry { id: 248, value: "http://schemas.xmlsoap.org/ws/2004/04/security/sc/sct" },
|
||||
StaticEntry { id: 250, value: "http://schemas.xmlsoap.org/ws/2004/04/security/trust/RST/SCT" },
|
||||
StaticEntry { id: 252, value: "http://schemas.xmlsoap.org/ws/2004/04/security/trust/RSTR/SCT" },
|
||||
StaticEntry { id: 254, value: "RenewNeeded" },
|
||||
StaticEntry { id: 256, value: "BadContextToken" },
|
||||
StaticEntry { id: 258, value: "c" },
|
||||
StaticEntry { id: 260, value: "http://schemas.xmlsoap.org/ws/2005/02/sc/dk" },
|
||||
StaticEntry { id: 262, value: "http://schemas.xmlsoap.org/ws/2005/02/sc/sct" },
|
||||
StaticEntry { id: 264, value: "http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT" },
|
||||
StaticEntry { id: 266, value: "http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/SCT" },
|
||||
StaticEntry { id: 268, value: "http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT/Renew" },
|
||||
StaticEntry { id: 270, value: "http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/SCT/Renew" },
|
||||
StaticEntry { id: 272, value: "http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT/Cancel" },
|
||||
StaticEntry { id: 274, value: "http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/SCT/Cancel" },
|
||||
StaticEntry { id: 276, value: "http://www.w3.org/2001/04/xmlenc#aes128-cbc" },
|
||||
StaticEntry { id: 278, value: "http://www.w3.org/2001/04/xmlenc#kw-aes128" },
|
||||
StaticEntry { id: 280, value: "http://www.w3.org/2001/04/xmlenc#aes192-cbc" },
|
||||
StaticEntry { id: 282, value: "http://www.w3.org/2001/04/xmlenc#kw-aes192" },
|
||||
StaticEntry { id: 284, value: "http://www.w3.org/2001/04/xmlenc#aes256-cbc" },
|
||||
StaticEntry { id: 286, value: "http://www.w3.org/2001/04/xmlenc#kw-aes256" },
|
||||
StaticEntry { id: 288, value: "http://www.w3.org/2001/04/xmlenc#des-cbc" },
|
||||
StaticEntry { id: 290, value: "http://www.w3.org/2000/09/xmldsig#dsa-sha1" },
|
||||
StaticEntry { id: 292, value: "http://www.w3.org/2001/10/xml-exc-c14n#WithComments" },
|
||||
StaticEntry { id: 294, value: "http://www.w3.org/2000/09/xmldsig#hmac-sha1" },
|
||||
StaticEntry { id: 296, value: "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256" },
|
||||
StaticEntry { id: 298, value: "http://schemas.xmlsoap.org/ws/2005/02/sc/dk/p_sha1" },
|
||||
StaticEntry { id: 300, value: "http://www.w3.org/2001/04/xmlenc#ripemd160" },
|
||||
StaticEntry { id: 302, value: "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" },
|
||||
StaticEntry { id: 304, value: "http://www.w3.org/2000/09/xmldsig#rsa-sha1" },
|
||||
StaticEntry { id: 306, value: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" },
|
||||
StaticEntry { id: 308, value: "http://www.w3.org/2001/04/xmlenc#rsa-1_5" },
|
||||
StaticEntry { id: 310, value: "http://www.w3.org/2000/09/xmldsig#sha1" },
|
||||
StaticEntry { id: 312, value: "http://www.w3.org/2001/04/xmlenc#sha256" },
|
||||
StaticEntry { id: 314, value: "http://www.w3.org/2001/04/xmlenc#sha512" },
|
||||
StaticEntry { id: 316, value: "http://www.w3.org/2001/04/xmlenc#tripledes-cbc" },
|
||||
StaticEntry { id: 318, value: "http://www.w3.org/2001/04/xmlenc#kw-tripledes" },
|
||||
StaticEntry { id: 320, value: "http://schemas.xmlsoap.org/2005/02/trust/tlsnego#TLS_Wrap" },
|
||||
StaticEntry { id: 322, value: "http://schemas.xmlsoap.org/2005/02/trust/spnego#GSS_Wrap" },
|
||||
StaticEntry { id: 324, value: "http://schemas.microsoft.com/ws/2006/05/security" },
|
||||
StaticEntry { id: 326, value: "dnse" },
|
||||
StaticEntry { id: 328, value: "o" },
|
||||
StaticEntry { id: 330, value: "Password" },
|
||||
StaticEntry { id: 332, value: "PasswordText" },
|
||||
StaticEntry { id: 334, value: "Username" },
|
||||
StaticEntry { id: 336, value: "UsernameToken" },
|
||||
StaticEntry { id: 338, value: "BinarySecurityToken" },
|
||||
StaticEntry { id: 340, value: "EncodingType" },
|
||||
StaticEntry { id: 342, value: "KeyIdentifier" },
|
||||
StaticEntry { id: 344, value: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" },
|
||||
StaticEntry { id: 346, value: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#HexBinary" },
|
||||
StaticEntry { id: 348, value: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Text" },
|
||||
StaticEntry { id: 350, value: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier" },
|
||||
StaticEntry { id: 352, value: "http://docs.oasis-open.org/wss/oasis-wss-kerberos-token-profile-1.1#GSS_Kerberosv5_AP_REQ" },
|
||||
StaticEntry { id: 354, value: "http://docs.oasis-open.org/wss/oasis-wss-kerberos-token-profile-1.1#GSS_Kerberosv5_AP_REQ1510" },
|
||||
StaticEntry { id: 356, value: "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#SAMLAssertionID" },
|
||||
StaticEntry { id: 358, value: "Assertion" },
|
||||
StaticEntry { id: 360, value: "urn:oasis:names:tc:SAML:1.0:assertion" },
|
||||
StaticEntry { id: 362, value: "http://docs.oasis-open.org/wss/oasis-wss-rel-token-profile-1.0.pdf#license" },
|
||||
StaticEntry { id: 364, value: "FailedAuthentication" },
|
||||
StaticEntry { id: 366, value: "InvalidSecurityToken" },
|
||||
StaticEntry { id: 368, value: "InvalidSecurity" },
|
||||
StaticEntry { id: 370, value: "k" },
|
||||
StaticEntry { id: 372, value: "SignatureConfirmation" },
|
||||
StaticEntry { id: 374, value: "TokenType" },
|
||||
StaticEntry { id: 376, value: "http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#ThumbprintSHA1" },
|
||||
StaticEntry { id: 378, value: "http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#EncryptedKey" },
|
||||
StaticEntry { id: 380, value: "http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#EncryptedKeySHA1" },
|
||||
StaticEntry { id: 382, value: "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1" },
|
||||
StaticEntry { id: 384, value: "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0" },
|
||||
StaticEntry { id: 386, value: "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLID" },
|
||||
StaticEntry { id: 388, value: "AUTH-HASH" },
|
||||
StaticEntry { id: 390, value: "RequestSecurityTokenResponse" },
|
||||
StaticEntry { id: 392, value: "KeySize" },
|
||||
StaticEntry { id: 394, value: "RequestedTokenReference" },
|
||||
StaticEntry { id: 396, value: "AppliesTo" },
|
||||
StaticEntry { id: 398, value: "Authenticator" },
|
||||
StaticEntry { id: 400, value: "CombinedHash" },
|
||||
// ---- xsi / xsd / nil — heavily used by .NET XmlSerializer for
|
||||
// value types in custom message-contract bodies. These are
|
||||
// String 218..222 in the canonical table.
|
||||
StaticEntry { id: 436, value: "type" },
|
||||
StaticEntry { id: 438, value: "i" },
|
||||
StaticEntry { id: 440, value: "http://www.w3.org/2001/XMLSchema-instance" },
|
||||
StaticEntry { id: 442, value: "http://www.w3.org/2001/XMLSchema" },
|
||||
StaticEntry { id: 444, value: "nil" },
|
||||
];
|
||||
|
||||
/// Lookup an entry by static-dictionary ID. Returns `None` for IDs
|
||||
@@ -460,9 +290,10 @@ pub fn position_of_static(value: &str) -> Option<u32> {
|
||||
let map = REVERSE.get_or_init(|| {
|
||||
let mut map = HashMap::with_capacity(STATIC_ENTRIES.len());
|
||||
for entry in STATIC_ENTRIES {
|
||||
// First-id-wins for duplicates (the .NET dictionary has
|
||||
// entries 86 + 94 = "TokenType"; we lock the lower id so
|
||||
// round-trip lookups are deterministic).
|
||||
// First-id-wins for duplicates (the canonical dictionary
|
||||
// has TokenType at both id 116 (String 58) and id 374
|
||||
// (String 187); we lock the lower id so round-trip lookups
|
||||
// are deterministic).
|
||||
map.entry(entry.value).or_insert(entry.id);
|
||||
}
|
||||
map
|
||||
@@ -495,6 +326,22 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn static_entries_use_even_ids() {
|
||||
// `[MC-NBFS]` reserves odd ids for the per-session dynamic dict
|
||||
// (`[MC-NBFX]` records 0xAA / 0xAB DictionaryText use the parity
|
||||
// bit to discriminate). All static-table ids must be even.
|
||||
for entry in STATIC_ENTRIES {
|
||||
assert_eq!(
|
||||
entry.id % 2,
|
||||
0,
|
||||
"static entry id {} ('{}') is odd — odd ids are reserved for the dynamic dict",
|
||||
entry.id,
|
||||
entry.value
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lookup_returns_known_entries() {
|
||||
assert_eq!(lookup_static(0), Some("mustUnderstand"));
|
||||
@@ -503,45 +350,63 @@ mod tests {
|
||||
lookup_static(4),
|
||||
Some("http://www.w3.org/2003/05/soap-envelope")
|
||||
);
|
||||
assert_eq!(lookup_static(8), Some("Header"));
|
||||
assert_eq!(lookup_static(14), Some("Body"));
|
||||
}
|
||||
|
||||
/// Fault-subset round-trip: every entry the SOAP-1.2 fault body
|
||||
/// references must resolve. These are the exact dict ids the
|
||||
/// AVEVA MxDataProvider sends in `dispatcher/fault` envelopes
|
||||
/// (verified live via `MX_ASB_TRACE_REPLY`). Earlier versions of
|
||||
/// this table mis-numbered the SOAP-fault subset (Fault was at id
|
||||
/// 114 instead of 134), causing `decode_envelope` to silently drop
|
||||
/// the resolved field name and the consumer to see opaque
|
||||
/// `Static(N)` tokens.
|
||||
#[test]
|
||||
fn fault_subset_resolves_to_canonical_strings() {
|
||||
assert_eq!(lookup_static(132), Some("s"));
|
||||
assert_eq!(lookup_static(134), Some("Fault"));
|
||||
assert_eq!(lookup_static(136), Some("MustUnderstand"));
|
||||
assert_eq!(lookup_static(142), Some("Code"));
|
||||
assert_eq!(lookup_static(144), Some("Reason"));
|
||||
assert_eq!(lookup_static(146), Some("Text"));
|
||||
assert_eq!(lookup_static(148), Some("Node"));
|
||||
assert_eq!(lookup_static(150), Some("Role"));
|
||||
assert_eq!(lookup_static(152), Some("Detail"));
|
||||
assert_eq!(lookup_static(154), Some("Value"));
|
||||
assert_eq!(lookup_static(156), Some("Subcode"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn xmlserializer_extras_resolve() {
|
||||
// The 436..444 high-id extras are essential for any
|
||||
// [MessageContract] response body that uses XmlSerializer.
|
||||
assert_eq!(lookup_static(436), Some("type"));
|
||||
assert_eq!(lookup_static(438), Some("i"));
|
||||
assert_eq!(
|
||||
lookup_static(440),
|
||||
Some("http://www.w3.org/2001/XMLSchema-instance")
|
||||
);
|
||||
assert_eq!(
|
||||
lookup_static(442),
|
||||
Some("http://www.w3.org/2001/XMLSchema")
|
||||
);
|
||||
assert_eq!(lookup_static(444), Some("nil"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lookup_returns_none_for_unmapped_ids() {
|
||||
assert_eq!(lookup_static(1), None); // odd ids are namespace pairs we don't include
|
||||
assert_eq!(lookup_static(999_999), None);
|
||||
fn position_of_static_round_trips_known_strings() {
|
||||
assert_eq!(position_of_static("mustUnderstand"), Some(0));
|
||||
assert_eq!(position_of_static("Envelope"), Some(2));
|
||||
assert_eq!(position_of_static("Fault"), Some(134));
|
||||
assert_eq!(position_of_static("Reason"), Some(144));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn position_of_known_strings_is_consistent_with_lookup() {
|
||||
for entry in STATIC_ENTRIES {
|
||||
// Two entries with the same string ("TokenType" at 86 and 94)
|
||||
// collapse to the lower id by `or_insert`. Skip those for
|
||||
// the strict round-trip assertion; reverse-lookup of the
|
||||
// duplicate string is allowed to map to any of its ids.
|
||||
let id = position_of_static(entry.value).unwrap();
|
||||
assert!(
|
||||
id <= entry.id,
|
||||
"position_of returned a higher id than the entry"
|
||||
);
|
||||
assert_eq!(lookup_static(id), Some(entry.value));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn position_of_unknown_strings_is_none() {
|
||||
assert_eq!(position_of_static("not-in-table"), None);
|
||||
assert_eq!(position_of_static("http://ASB.IDataV2"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_string_round_trips_to_id_142() {
|
||||
// Position 142 in the spec is the empty string. Sanity-check
|
||||
// we got the right slot.
|
||||
assert_eq!(lookup_static(142), Some(""));
|
||||
assert_eq!(position_of_static(""), Some(142));
|
||||
fn lookup_returns_none_for_unknown() {
|
||||
// 1 is odd → reserved for dynamic dict; should always be None.
|
||||
assert_eq!(lookup_static(1), None);
|
||||
// Way past the table.
|
||||
assert_eq!(lookup_static(9999), None);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user