fe2a6db786
rust / build / test / clippy / fmt (push) Has been cancelled
Layout:
- src/ .NET 10 x64 reference: MxNativeCodec, MxNativeClient,
MxAsbClient, probes, tests, harnesses. Executable spec.
- design/ Architectural plan for the Rust port (M0–M6), error
model, protocol invariants, risks (R1–R16), adversarial
review log (review.md).
- rust/ Rust workspace. M0 skeleton + M1 codec parity.
mxaccess-codec: 215 unit tests + 2 cross-implementation
parity tests (byte-identical against .NET reference).
Other crates are M0 stubs awaiting M2+.
- captures/ Frida + netsh + pcap evidence per CLAUDE.md
("captures are evidence, not throwaway logs").
- analysis/ Decompiled C# (frida/proxy/decompiled-*),
Ghidra exports for native DLLs (`exports/` only —
working state at `projects/` and AVEVA's input
binaries at `input/` are gitignored).
- docs/ Reverse-engineering reference docs.
- tools/ Setup-LiveProbeEnv.ps1 (Infisical credential fetcher),
Compute-Crc.ps1 (.NET parity helper).
- .github/workflows/ Rust CI: fmt + build + test + clippy on Windows.
- LICENSE MIT (Joseph Doherty, 2026).
Verified:
- cargo test --workspace → 217 passed (215 unit + 2 .NET parity), 0 failed
- cargo clippy --workspace -- -D warnings → clean
- cargo fmt --all -- --check → clean
- cargo publish --dry-run -p mxaccess-codec → packages cleanly
Excluded from history (see .gitignore):
- **/bin, **/obj, **/target — build artifacts
- analysis/ghidra/projects/ — Ghidra working state (regenerable)
- analysis/ghidra/input/ — AVEVA proprietary DLLs (vendor IP)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
286 lines
10 KiB
C#
286 lines
10 KiB
C#
using ArchestrAServices.ASBContract;
|
|
using ArchestrAServices.ASBIDataContract;
|
|
using ArchestrAServices.ASBIDataContract.V2;
|
|
using ArchestrAServices.ASBIDataV2Contract;
|
|
|
|
namespace ArchestrAServices.ASBIDataV2Adapter;
|
|
|
|
public static class IDataV2toV1Extensions
|
|
{
|
|
public static ArchestrAServices.ASBIDataContract.Variant ToV1Variant(this ArchestrAServices.ASBIDataContract.V2.Variant v2Variant)
|
|
{
|
|
return new ArchestrAServices.ASBIDataContract.Variant
|
|
{
|
|
Type = v2Variant.Type,
|
|
Length = v2Variant.Length,
|
|
Payload = v2Variant.Payload
|
|
};
|
|
}
|
|
|
|
public static ArchestrAServices.ASBContract.MonitoredItem ToV1MonitoredItem(this ArchestrAServices.ASBIDataV2Contract.MonitoredItem v2MonitoredItem)
|
|
{
|
|
ArchestrAServices.ASBContract.MonitoredItem result = new ArchestrAServices.ASBContract.MonitoredItem
|
|
{
|
|
ActiveSpecified = v2MonitoredItem.ActiveSpecified
|
|
};
|
|
if (v2MonitoredItem.ActiveSpecified)
|
|
{
|
|
result.Active = v2MonitoredItem.Active;
|
|
}
|
|
result.Item = v2MonitoredItem.Item.ToV1ItemIdentity();
|
|
result.SampleInterval = v2MonitoredItem.SampleInterval;
|
|
result.TimeDeadbandSpecified = v2MonitoredItem.TimeDeadbandSpecified;
|
|
if (v2MonitoredItem.TimeDeadbandSpecified)
|
|
{
|
|
result.TimeDeadband = v2MonitoredItem.TimeDeadband;
|
|
}
|
|
result.UserData = v2MonitoredItem.UserData.ToV1Variant();
|
|
result.ValueDeadband = v2MonitoredItem.ValueDeadband.ToV1Variant();
|
|
return result;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBContract.MonitoredItem[] ToV1MonitoredItemArray(this ArchestrAServices.ASBIDataV2Contract.MonitoredItem[] v2MonitoredItem)
|
|
{
|
|
ArchestrAServices.ASBContract.MonitoredItem[] array = new ArchestrAServices.ASBContract.MonitoredItem[v2MonitoredItem.Length];
|
|
for (int i = 0; i < v2MonitoredItem.Length; i++)
|
|
{
|
|
array[i] = v2MonitoredItem[i].ToV1MonitoredItem();
|
|
}
|
|
return array;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBContract.ASBStatus ToV1ASBStatus(this ArchestrAServices.ASBIDataV2Contract.ASBStatus v2ASBStatus)
|
|
{
|
|
return new ArchestrAServices.ASBContract.ASBStatus
|
|
{
|
|
Count = v2ASBStatus.Count,
|
|
Payload = v2ASBStatus.Payload
|
|
};
|
|
}
|
|
|
|
public static ArchestrAServices.ASBContract.WriteValue ToV1WriteValue(this WriteValueV2 v2MirroredWriteValue)
|
|
{
|
|
ArchestrAServices.ASBContract.WriteValue result = new ArchestrAServices.ASBContract.WriteValue
|
|
{
|
|
Comment = v2MirroredWriteValue.Comment,
|
|
HasQTSpecified = v2MirroredWriteValue.HasQTSpecified
|
|
};
|
|
if (v2MirroredWriteValue.HasQTSpecified)
|
|
{
|
|
result.HasQT = v2MirroredWriteValue.HasQT;
|
|
}
|
|
result.Status = v2MirroredWriteValue.Status;
|
|
result.TimestampSpecified = v2MirroredWriteValue.TimestampSpecified;
|
|
if (v2MirroredWriteValue.TimestampSpecified)
|
|
{
|
|
result.Timestamp = v2MirroredWriteValue.Timestamp;
|
|
}
|
|
result.Value = v2MirroredWriteValue.Value;
|
|
return result;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBContract.WriteValue ToV1WriteValue(this ArchestrAServices.ASBIDataV2Contract.WriteValue v2WriteValue)
|
|
{
|
|
ArchestrAServices.ASBContract.WriteValue result = new ArchestrAServices.ASBContract.WriteValue
|
|
{
|
|
Comment = v2WriteValue.Comment,
|
|
HasQTSpecified = v2WriteValue.HasQTSpecified
|
|
};
|
|
if (v2WriteValue.HasQTSpecified)
|
|
{
|
|
result.HasQT = v2WriteValue.HasQT;
|
|
}
|
|
result.Status = v2WriteValue.Status.ToV1ASBStatus();
|
|
result.TimestampSpecified = v2WriteValue.TimestampSpecified;
|
|
if (v2WriteValue.TimestampSpecified)
|
|
{
|
|
result.Timestamp = v2WriteValue.Timestamp;
|
|
}
|
|
result.Value = v2WriteValue.Value.ToV1Variant();
|
|
return result;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBContract.WriteValue[] ToV1WriteValueArray(this ArchestrAServices.ASBIDataV2Contract.WriteValue[] v2WriteValue)
|
|
{
|
|
ArchestrAServices.ASBContract.WriteValue[] array = new ArchestrAServices.ASBContract.WriteValue[v2WriteValue.Length];
|
|
for (int i = 0; i < v2WriteValue.Length; i++)
|
|
{
|
|
array[i] = v2WriteValue[i].ToV1WriteValue();
|
|
}
|
|
return array;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBContract.UserToken ToV1UserToken(this ArchestrAServices.ASBIDataV2Contract.UserToken v2UserToken)
|
|
{
|
|
ArchestrAServices.ASBContract.UserToken result = new ArchestrAServices.ASBContract.UserToken
|
|
{
|
|
EncryptionSpecified = v2UserToken.EncryptionSpecified
|
|
};
|
|
if (v2UserToken.EncryptionSpecified)
|
|
{
|
|
result.Encryption = v2UserToken.Encryption;
|
|
}
|
|
result.HostName = v2UserToken.HostName;
|
|
result.IdTypeSpecified = v2UserToken.IdTypeSpecified;
|
|
if (v2UserToken.IdTypeSpecified)
|
|
{
|
|
result.IdType = v2UserToken.IdType;
|
|
}
|
|
result.LocationID = v2UserToken.LocationID;
|
|
result.Password = v2UserToken.Password;
|
|
result.SamlToken = v2UserToken.SamlToken;
|
|
result.UserName = v2UserToken.UserName;
|
|
result.ValiditySpecified = v2UserToken.ValiditySpecified;
|
|
if (v2UserToken.ValiditySpecified)
|
|
{
|
|
result.Validity = v2UserToken.Validity;
|
|
}
|
|
result.X509Certificate = v2UserToken.X509Certificate;
|
|
return result;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBContract.ItemIdentity ToV1ItemIdentity(this ArchestrAServices.ASBIDataV2Contract.ItemIdentity v1Identity)
|
|
{
|
|
ArchestrAServices.ASBContract.ItemIdentity result = new ArchestrAServices.ASBContract.ItemIdentity
|
|
{
|
|
Name = v1Identity.Name,
|
|
ContextName = v1Identity.ContextName,
|
|
IdSpecified = v1Identity.IdSpecified
|
|
};
|
|
if (v1Identity.IdSpecified)
|
|
{
|
|
result.Id = v1Identity.Id;
|
|
}
|
|
result.ReferenceType = v1Identity.ReferenceType;
|
|
result.Type = v1Identity.Type;
|
|
return result;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBContract.ItemIdentity[] ToV1ItemIdentityArray(this ArchestrAServices.ASBIDataV2Contract.ItemIdentity[] v2ItemIdentity)
|
|
{
|
|
ArchestrAServices.ASBContract.ItemIdentity[] array = new ArchestrAServices.ASBContract.ItemIdentity[v2ItemIdentity.Length];
|
|
for (int i = 0; i < v2ItemIdentity.Length; i++)
|
|
{
|
|
array[i] = v2ItemIdentity[i].ToV1ItemIdentity();
|
|
}
|
|
return array;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBContract.ItemStatus ToV1ItemStatus(this ArchestrAServices.ASBIDataV2Contract.ItemStatus v2Status)
|
|
{
|
|
ArchestrAServices.ASBContract.ItemStatus result = new ArchestrAServices.ASBContract.ItemStatus
|
|
{
|
|
ErrorCodeSpecified = v2Status.ErrorCodeSpecified
|
|
};
|
|
if (v2Status.ErrorCodeSpecified)
|
|
{
|
|
result.ErrorCode = v2Status.ErrorCode;
|
|
}
|
|
result.Item = v2Status.Item.ToV1ItemIdentity();
|
|
return result;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBContract.ItemStatus[] ToV1ItemStatusArray(this ArchestrAServices.ASBIDataV2Contract.ItemStatus[] v2Status)
|
|
{
|
|
ArchestrAServices.ASBContract.ItemStatus[] array = new ArchestrAServices.ASBContract.ItemStatus[v2Status.Length];
|
|
for (int i = 0; i < v2Status.Length; i++)
|
|
{
|
|
array[i] = v2Status[i].ToV1ItemStatus();
|
|
}
|
|
return array;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBContract.ItemRegistration ToV1ItemRegistration(this ArchestrAServices.ASBIDataV2Contract.ItemRegistration v2Registration)
|
|
{
|
|
ArchestrAServices.ASBContract.ItemRegistration result = new ArchestrAServices.ASBContract.ItemRegistration
|
|
{
|
|
IdSpecified = v2Registration.IdSpecified
|
|
};
|
|
if (v2Registration.IdSpecified)
|
|
{
|
|
result.Id = v2Registration.Id;
|
|
}
|
|
result.WriteCapability = v2Registration.WriteCapability;
|
|
return result;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBContract.ItemRegistration[] ToV1ItemRegistrationArray(this ArchestrAServices.ASBIDataV2Contract.ItemRegistration[] v2Registration)
|
|
{
|
|
ArchestrAServices.ASBContract.ItemRegistration[] array = new ArchestrAServices.ASBContract.ItemRegistration[v2Registration.Length];
|
|
for (int i = 0; i < v2Registration.Length; i++)
|
|
{
|
|
array[i] = v2Registration[i].ToV1ItemRegistration();
|
|
}
|
|
return array;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBContract.RuntimeValue ToV1RuntimeValue(this ArchestrAServices.ASBIDataV2Contract.RuntimeValue v2RuntimeValue)
|
|
{
|
|
ArchestrAServices.ASBContract.RuntimeValue result = new ArchestrAServices.ASBContract.RuntimeValue
|
|
{
|
|
Status = v2RuntimeValue.Status.ToV1ASBStatus(),
|
|
TimestampSpecified = v2RuntimeValue.TimestampSpecified
|
|
};
|
|
if (v2RuntimeValue.TimestampSpecified)
|
|
{
|
|
result.Timestamp = v2RuntimeValue.Timestamp;
|
|
}
|
|
result.Value = v2RuntimeValue.Value.ToV1Variant();
|
|
return result;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBContract.RuntimeValue[] ToV1RuntimeValueArray(this ArchestrAServices.ASBIDataV2Contract.RuntimeValue[] v2RuntimeValue)
|
|
{
|
|
ArchestrAServices.ASBContract.RuntimeValue[] array = new ArchestrAServices.ASBContract.RuntimeValue[v2RuntimeValue.Length];
|
|
for (int i = 0; i < v2RuntimeValue.Length; i++)
|
|
{
|
|
array[i] = v2RuntimeValue[i].ToV1RuntimeValue();
|
|
}
|
|
return array;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBContract.MonitoredItemValue ToV1MonitoredItemValue(this ArchestrAServices.ASBIDataV2Contract.MonitoredItemValue v2MonitoredItemValue)
|
|
{
|
|
return new ArchestrAServices.ASBContract.MonitoredItemValue
|
|
{
|
|
Item = v2MonitoredItemValue.Item.ToV1ItemIdentity(),
|
|
UserData = v2MonitoredItemValue.UserData.ToV1Variant(),
|
|
Value = v2MonitoredItemValue.Value.ToV1RuntimeValue()
|
|
};
|
|
}
|
|
|
|
public static ArchestrAServices.ASBContract.MonitoredItemValue[] ToV1MonitoredItemValueArray(this ArchestrAServices.ASBIDataV2Contract.MonitoredItemValue[] v2MonitoredItemValue)
|
|
{
|
|
ArchestrAServices.ASBContract.MonitoredItemValue[] array = new ArchestrAServices.ASBContract.MonitoredItemValue[v2MonitoredItemValue.Length];
|
|
for (int i = 0; i < v2MonitoredItemValue.Length; i++)
|
|
{
|
|
array[i] = v2MonitoredItemValue[i].ToV1MonitoredItemValue();
|
|
}
|
|
return array;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBContract.ItemWriteComplete ToV1ItemWriteComplete(this ArchestrAServices.ASBIDataV2Contract.ItemWriteComplete v2ItemWriteComplete)
|
|
{
|
|
ArchestrAServices.ASBContract.ItemWriteComplete result = new ArchestrAServices.ASBContract.ItemWriteComplete
|
|
{
|
|
Status = v2ItemWriteComplete.Status.ToV1ItemStatusArray(),
|
|
WriteHandleSpecified = v2ItemWriteComplete.WriteHandleSpecified
|
|
};
|
|
if (v2ItemWriteComplete.WriteHandleSpecified)
|
|
{
|
|
result.WriteHandle = v2ItemWriteComplete.WriteHandle;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBContract.ItemWriteComplete[] ToV1ItemWriteCompleteArray(this ArchestrAServices.ASBIDataV2Contract.ItemWriteComplete[] v2ItemWriteComplete)
|
|
{
|
|
ArchestrAServices.ASBContract.ItemWriteComplete[] array = new ArchestrAServices.ASBContract.ItemWriteComplete[v2ItemWriteComplete.Length];
|
|
for (int i = 0; i < v2ItemWriteComplete.Length; i++)
|
|
{
|
|
array[i] = v2ItemWriteComplete[i].ToV1ItemWriteComplete();
|
|
}
|
|
return array;
|
|
}
|
|
}
|