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>
376 lines
14 KiB
C#
376 lines
14 KiB
C#
using ArchestrAServices.ASBContract;
|
|
using ArchestrAServices.ASBIDataContract;
|
|
using ArchestrAServices.ASBIDataContract.V2;
|
|
using ArchestrAServices.ASBIDataV2Contract;
|
|
|
|
namespace ArchestrAServices.ASBIDataV2Adapter;
|
|
|
|
public static class IDataV1toV2Extensions
|
|
{
|
|
public static ArchestrAServices.ASBIDataV2Contract.ItemIdentity ToV2ItemIdentity(this ArchestrAServices.ASBContract.ItemIdentity v1Identity)
|
|
{
|
|
ArchestrAServices.ASBIDataV2Contract.ItemIdentity result = new ArchestrAServices.ASBIDataV2Contract.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.ASBIDataV2Contract.ItemIdentity[] ToV2ItemIdentityArray(this ArchestrAServices.ASBContract.ItemIdentity[] v1ItemIdentity)
|
|
{
|
|
ArchestrAServices.ASBIDataV2Contract.ItemIdentity[] array = new ArchestrAServices.ASBIDataV2Contract.ItemIdentity[v1ItemIdentity.Length];
|
|
for (int i = 0; i < v1ItemIdentity.Length; i++)
|
|
{
|
|
array[i] = v1ItemIdentity[i].ToV2ItemIdentity();
|
|
}
|
|
return array;
|
|
}
|
|
|
|
public static ItemStatusV2 ToMirroredV2ItemStatus(this ArchestrAServices.ASBContract.ItemStatus v1Status)
|
|
{
|
|
ItemStatusV2 result = new ItemStatusV2
|
|
{
|
|
ErrorCodeSpecified = v1Status.ErrorCodeSpecified
|
|
};
|
|
if (v1Status.ErrorCodeSpecified)
|
|
{
|
|
result.ErrorCode = v1Status.ErrorCode;
|
|
}
|
|
result.Item = v1Status.Item;
|
|
result.Status = default(ArchestrAServices.ASBContract.ASBStatus);
|
|
return result;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBIDataV2Contract.ItemStatus ToV2ItemStatus(this ArchestrAServices.ASBContract.ItemStatus v1Status)
|
|
{
|
|
ArchestrAServices.ASBIDataV2Contract.ItemStatus result = new ArchestrAServices.ASBIDataV2Contract.ItemStatus
|
|
{
|
|
ErrorCodeSpecified = v1Status.ErrorCodeSpecified
|
|
};
|
|
if (v1Status.ErrorCodeSpecified)
|
|
{
|
|
result.ErrorCode = v1Status.ErrorCode;
|
|
}
|
|
result.Item = v1Status.Item.ToV2ItemIdentity();
|
|
result.Status = default(ArchestrAServices.ASBIDataV2Contract.ASBStatus);
|
|
return result;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBIDataV2Contract.ItemStatus[] ToV2ItemStatusArray(this ArchestrAServices.ASBContract.ItemStatus[] v1Status)
|
|
{
|
|
ArchestrAServices.ASBIDataV2Contract.ItemStatus[] array = new ArchestrAServices.ASBIDataV2Contract.ItemStatus[v1Status.Length];
|
|
for (int i = 0; i < v1Status.Length; i++)
|
|
{
|
|
array[i] = v1Status[i].ToV2ItemStatus();
|
|
}
|
|
return array;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBIDataV2Contract.ItemStatus ToV2ItemStatus(this ItemStatusV2 v1Status)
|
|
{
|
|
ArchestrAServices.ASBIDataV2Contract.ItemStatus result = new ArchestrAServices.ASBIDataV2Contract.ItemStatus
|
|
{
|
|
ErrorCodeSpecified = v1Status.ErrorCodeSpecified
|
|
};
|
|
if (v1Status.ErrorCodeSpecified)
|
|
{
|
|
result.ErrorCode = v1Status.ErrorCode;
|
|
}
|
|
result.Item = v1Status.Item.ToV2ItemIdentity();
|
|
result.Status = v1Status.Status.ToV2ASBStatus();
|
|
return result;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBIDataV2Contract.ItemStatus[] ToV2ItemStatusArray(this ItemStatusV2[] v1Status)
|
|
{
|
|
ArchestrAServices.ASBIDataV2Contract.ItemStatus[] array = new ArchestrAServices.ASBIDataV2Contract.ItemStatus[v1Status.Length];
|
|
for (int i = 0; i < v1Status.Length; i++)
|
|
{
|
|
array[i] = v1Status[i].ToV2ItemStatus();
|
|
}
|
|
return array;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBContract.ItemStatus ToV1ItemStatus(this ItemStatusV2 v1Status)
|
|
{
|
|
ArchestrAServices.ASBContract.ItemStatus result = new ArchestrAServices.ASBContract.ItemStatus
|
|
{
|
|
ErrorCodeSpecified = v1Status.ErrorCodeSpecified
|
|
};
|
|
if (v1Status.ErrorCodeSpecified)
|
|
{
|
|
result.ErrorCode = v1Status.ErrorCode;
|
|
}
|
|
result.Item = v1Status.Item;
|
|
return result;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBContract.ItemStatus[] ToV1ItemStatusArray(this ItemStatusV2[] v1Status)
|
|
{
|
|
ArchestrAServices.ASBContract.ItemStatus[] array = new ArchestrAServices.ASBContract.ItemStatus[v1Status.Length];
|
|
for (int i = 0; i < v1Status.Length; i++)
|
|
{
|
|
array[i] = v1Status[i].ToV1ItemStatus();
|
|
}
|
|
return array;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBIDataV2Contract.ItemRegistration ToV2ItemRegistration(this ArchestrAServices.ASBContract.ItemRegistration v1Registration)
|
|
{
|
|
ArchestrAServices.ASBIDataV2Contract.ItemRegistration result = new ArchestrAServices.ASBIDataV2Contract.ItemRegistration
|
|
{
|
|
IdSpecified = v1Registration.IdSpecified,
|
|
Id = v1Registration.Id,
|
|
WriteCapabilitySpecified = v1Registration.WriteCapabilitySpecified
|
|
};
|
|
if (v1Registration.WriteCapabilitySpecified)
|
|
{
|
|
result.WriteCapability = v1Registration.WriteCapability;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBIDataV2Contract.ItemRegistration[] ToV2ItemRegistrationArray(this ArchestrAServices.ASBContract.ItemRegistration[] v1Registration)
|
|
{
|
|
ArchestrAServices.ASBIDataV2Contract.ItemRegistration[] array = new ArchestrAServices.ASBIDataV2Contract.ItemRegistration[v1Registration.Length];
|
|
for (int i = 0; i < v1Registration.Length; i++)
|
|
{
|
|
array[i] = v1Registration[i].ToV2ItemRegistration();
|
|
}
|
|
return array;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBIDataContract.V2.Variant ToV2Variant(this ArchestrAServices.ASBIDataContract.Variant v1Variant)
|
|
{
|
|
return new ArchestrAServices.ASBIDataContract.V2.Variant
|
|
{
|
|
Type = v1Variant.Type,
|
|
Length = v1Variant.Length,
|
|
Payload = v1Variant.Payload
|
|
};
|
|
}
|
|
|
|
public static ArchestrAServices.ASBIDataV2Contract.MonitoredItem ToV2MonitoredItem(this ArchestrAServices.ASBContract.MonitoredItem v1MonitoredItem)
|
|
{
|
|
ArchestrAServices.ASBIDataV2Contract.MonitoredItem result = new ArchestrAServices.ASBIDataV2Contract.MonitoredItem
|
|
{
|
|
ActiveSpecified = v1MonitoredItem.ActiveSpecified
|
|
};
|
|
if (v1MonitoredItem.ActiveSpecified)
|
|
{
|
|
result.Active = v1MonitoredItem.Active;
|
|
}
|
|
result.Item = v1MonitoredItem.Item.ToV2ItemIdentity();
|
|
result.SampleInterval = v1MonitoredItem.SampleInterval;
|
|
result.TimeDeadbandSpecified = v1MonitoredItem.TimeDeadbandSpecified;
|
|
if (v1MonitoredItem.TimeDeadbandSpecified)
|
|
{
|
|
result.TimeDeadband = v1MonitoredItem.TimeDeadband;
|
|
}
|
|
result.UserData = v1MonitoredItem.UserData.ToV2Variant();
|
|
result.ValueDeadband = v1MonitoredItem.ValueDeadband.ToV2Variant();
|
|
return result;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBIDataV2Contract.MonitoredItem[] ToV2MonitoredItemArray(this ArchestrAServices.ASBContract.MonitoredItem[] v1MonitoredItem)
|
|
{
|
|
ArchestrAServices.ASBIDataV2Contract.MonitoredItem[] array = new ArchestrAServices.ASBIDataV2Contract.MonitoredItem[v1MonitoredItem.Length];
|
|
for (int i = 0; i < v1MonitoredItem.Length; i++)
|
|
{
|
|
array[i] = v1MonitoredItem[i].ToV2MonitoredItem();
|
|
}
|
|
return array;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBIDataV2Contract.ASBStatus ToV2ASBStatus(this ArchestrAServices.ASBContract.ASBStatus v1ASBStatus)
|
|
{
|
|
return new ArchestrAServices.ASBIDataV2Contract.ASBStatus
|
|
{
|
|
Count = v1ASBStatus.Count,
|
|
Payload = v1ASBStatus.Payload
|
|
};
|
|
}
|
|
|
|
public static ArchestrAServices.ASBIDataV2Contract.RuntimeValue ToV2RuntimeValue(this ArchestrAServices.ASBContract.RuntimeValue v1RuntimeValue)
|
|
{
|
|
ArchestrAServices.ASBIDataV2Contract.RuntimeValue result = new ArchestrAServices.ASBIDataV2Contract.RuntimeValue
|
|
{
|
|
Status = v1RuntimeValue.Status.ToV2ASBStatus(),
|
|
TimestampSpecified = v1RuntimeValue.TimestampSpecified
|
|
};
|
|
if (v1RuntimeValue.TimestampSpecified)
|
|
{
|
|
result.Timestamp = v1RuntimeValue.Timestamp;
|
|
}
|
|
result.Value = v1RuntimeValue.Value.ToV2Variant();
|
|
return result;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBIDataV2Contract.RuntimeValue[] ToV2RuntimeValueArray(this ArchestrAServices.ASBContract.RuntimeValue[] v1RuntimeValue)
|
|
{
|
|
ArchestrAServices.ASBIDataV2Contract.RuntimeValue[] array = new ArchestrAServices.ASBIDataV2Contract.RuntimeValue[v1RuntimeValue.Length];
|
|
for (int i = 0; i < v1RuntimeValue.Length; i++)
|
|
{
|
|
array[i] = v1RuntimeValue[i].ToV2RuntimeValue();
|
|
}
|
|
return array;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBIDataV2Contract.MonitoredItemValue ToV2MonitoredItemValue(this ArchestrAServices.ASBContract.MonitoredItemValue v1MonitoredItemValue)
|
|
{
|
|
return new ArchestrAServices.ASBIDataV2Contract.MonitoredItemValue
|
|
{
|
|
Item = v1MonitoredItemValue.Item.ToV2ItemIdentity(),
|
|
UserData = v1MonitoredItemValue.UserData.ToV2Variant(),
|
|
Value = v1MonitoredItemValue.Value.ToV2RuntimeValue()
|
|
};
|
|
}
|
|
|
|
public static ArchestrAServices.ASBIDataV2Contract.MonitoredItemValue[] ToV2MonitoredItemValueArray(this ArchestrAServices.ASBContract.MonitoredItemValue[] v1MonitoredItemValue)
|
|
{
|
|
ArchestrAServices.ASBIDataV2Contract.MonitoredItemValue[] array = new ArchestrAServices.ASBIDataV2Contract.MonitoredItemValue[v1MonitoredItemValue.Length];
|
|
for (int i = 0; i < v1MonitoredItemValue.Length; i++)
|
|
{
|
|
array[i] = v1MonitoredItemValue[i].ToV2MonitoredItemValue();
|
|
}
|
|
return array;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBIDataV2Contract.WriteValue ToV2WriteValue(this ArchestrAServices.ASBContract.WriteValue v1WriteValue)
|
|
{
|
|
ArchestrAServices.ASBIDataV2Contract.WriteValue result = new ArchestrAServices.ASBIDataV2Contract.WriteValue
|
|
{
|
|
ArrayElementIndex = 0,
|
|
Comment = v1WriteValue.Comment,
|
|
HasQTSpecified = v1WriteValue.HasQTSpecified
|
|
};
|
|
if (v1WriteValue.HasQTSpecified)
|
|
{
|
|
result.HasQT = v1WriteValue.HasQT;
|
|
}
|
|
result.Status = v1WriteValue.Status.ToV2ASBStatus();
|
|
result.TimestampSpecified = v1WriteValue.TimestampSpecified;
|
|
if (v1WriteValue.TimestampSpecified)
|
|
{
|
|
result.Timestamp = v1WriteValue.Timestamp;
|
|
}
|
|
result.Value = v1WriteValue.Value.ToV2Variant();
|
|
result.ArrayElementIndexSpecified = false;
|
|
return result;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBIDataV2Contract.WriteValue[] ToV2WriteValueArray(this ArchestrAServices.ASBContract.WriteValue[] v1WriteValue)
|
|
{
|
|
ArchestrAServices.ASBIDataV2Contract.WriteValue[] array = new ArchestrAServices.ASBIDataV2Contract.WriteValue[v1WriteValue.Length];
|
|
for (int i = 0; i < v1WriteValue.Length; i++)
|
|
{
|
|
array[i] = v1WriteValue[i].ToV2WriteValue();
|
|
}
|
|
return array;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBIDataV2Contract.ItemWriteComplete ToV2ItemWriteComplete(this ArchestrAServices.ASBContract.ItemWriteComplete v1ItemWriteComplete)
|
|
{
|
|
return new ArchestrAServices.ASBIDataV2Contract.ItemWriteComplete
|
|
{
|
|
Status = v1ItemWriteComplete.Status.ToV2ItemStatusArray(),
|
|
WriteHandle = v1ItemWriteComplete.WriteHandle
|
|
};
|
|
}
|
|
|
|
public static ArchestrAServices.ASBIDataV2Contract.ItemWriteComplete[] ToV2ItemWriteCompleteArray(this ArchestrAServices.ASBContract.ItemWriteComplete[] v1ItemWriteComplete)
|
|
{
|
|
ArchestrAServices.ASBIDataV2Contract.ItemWriteComplete[] array = new ArchestrAServices.ASBIDataV2Contract.ItemWriteComplete[v1ItemWriteComplete.Length];
|
|
for (int i = 0; i < v1ItemWriteComplete.Length; i++)
|
|
{
|
|
array[i] = v1ItemWriteComplete[i].ToV2ItemWriteComplete();
|
|
}
|
|
return array;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBIDataV2Contract.ItemWriteComplete ToV2ItemWriteComplete(this ItemWriteCompleteV2 v1ItemWriteComplete)
|
|
{
|
|
ArchestrAServices.ASBIDataV2Contract.ItemWriteComplete result = new ArchestrAServices.ASBIDataV2Contract.ItemWriteComplete
|
|
{
|
|
Status = v1ItemWriteComplete.Status.ToV2ItemStatusArray(),
|
|
WriteHandleSpecified = v1ItemWriteComplete.WriteHandleSpecified
|
|
};
|
|
if (v1ItemWriteComplete.WriteHandleSpecified)
|
|
{
|
|
result.WriteHandle = v1ItemWriteComplete.WriteHandle;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBIDataV2Contract.ItemWriteComplete[] ToV2ItemWriteCompleteArray(this ItemWriteCompleteV2[] v1ItemWriteComplete)
|
|
{
|
|
ArchestrAServices.ASBIDataV2Contract.ItemWriteComplete[] array = new ArchestrAServices.ASBIDataV2Contract.ItemWriteComplete[v1ItemWriteComplete.Length];
|
|
for (int i = 0; i < v1ItemWriteComplete.Length; i++)
|
|
{
|
|
array[i] = v1ItemWriteComplete[i].ToV2ItemWriteComplete();
|
|
}
|
|
return array;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBContract.ItemWriteComplete ToV1ItemWriteComplete(this ItemWriteCompleteV2 v1ItemWriteComplete)
|
|
{
|
|
ArchestrAServices.ASBContract.ItemWriteComplete result = new ArchestrAServices.ASBContract.ItemWriteComplete
|
|
{
|
|
Status = v1ItemWriteComplete.Status.ToV1ItemStatusArray(),
|
|
WriteHandleSpecified = v1ItemWriteComplete.WriteHandleSpecified
|
|
};
|
|
if (v1ItemWriteComplete.WriteHandleSpecified)
|
|
{
|
|
result.WriteHandle = v1ItemWriteComplete.WriteHandle;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBContract.ItemWriteComplete[] ToV1ItemWriteCompleteArray(this ItemWriteCompleteV2[] v1ItemWriteComplete)
|
|
{
|
|
ArchestrAServices.ASBContract.ItemWriteComplete[] array = new ArchestrAServices.ASBContract.ItemWriteComplete[v1ItemWriteComplete.Length];
|
|
for (int i = 0; i < v1ItemWriteComplete.Length; i++)
|
|
{
|
|
array[i] = v1ItemWriteComplete[i].ToV1ItemWriteComplete();
|
|
}
|
|
return array;
|
|
}
|
|
|
|
public static ArchestrAServices.ASBIDataV2Contract.UserToken ToV2UserToken(this ArchestrAServices.ASBContract.UserToken v1UserToken)
|
|
{
|
|
ArchestrAServices.ASBIDataV2Contract.UserToken result = new ArchestrAServices.ASBIDataV2Contract.UserToken
|
|
{
|
|
EncryptionSpecified = v1UserToken.EncryptionSpecified
|
|
};
|
|
if (v1UserToken.EncryptionSpecified)
|
|
{
|
|
result.Encryption = v1UserToken.Encryption;
|
|
}
|
|
result.HostName = v1UserToken.HostName;
|
|
result.IdTypeSpecified = v1UserToken.IdTypeSpecified;
|
|
if (v1UserToken.IdTypeSpecified)
|
|
{
|
|
result.IdType = v1UserToken.IdType;
|
|
}
|
|
result.LocationID = v1UserToken.LocationID;
|
|
result.Password = v1UserToken.Password;
|
|
result.SamlToken = v1UserToken.SamlToken;
|
|
result.UserName = v1UserToken.UserName;
|
|
result.ValiditySpecified = v1UserToken.ValiditySpecified;
|
|
if (v1UserToken.ValiditySpecified)
|
|
{
|
|
result.Validity = v1UserToken.Validity;
|
|
}
|
|
result.X509Certificate = v1UserToken.X509Certificate;
|
|
return result;
|
|
}
|
|
}
|