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>
918 lines
29 KiB
C#
918 lines
29 KiB
C#
#define TRACE
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Diagnostics;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Net.NetworkInformation;
|
|
using System.Net.Security;
|
|
using System.Net.Sockets;
|
|
using System.ServiceModel;
|
|
using System.ServiceModel.Channels;
|
|
using System.ServiceModel.Discovery;
|
|
using System.ServiceProcess;
|
|
using System.Threading;
|
|
using System.Xml.Linq;
|
|
using Microsoft.Win32;
|
|
|
|
namespace ArchestrAServices.Common;
|
|
|
|
public static class SvcUtilities
|
|
{
|
|
public const string AsbCoreServiceScope = "archestra://coreservices";
|
|
|
|
public const string AsbUserServiceScope = "archestra://asb/";
|
|
|
|
public const string AsbScopePrefix = "archestra://";
|
|
|
|
public const string ServiceNameScope = "instancename/";
|
|
|
|
public const string ServiceVersionScope = "serviceversion/";
|
|
|
|
public const string DataTypeScope = "datatype/";
|
|
|
|
public const string SolutionNameScope = "asbsolution/";
|
|
|
|
public const string DomainScope = "domainname/";
|
|
|
|
public const string NamespaceScope = "namespace/";
|
|
|
|
public static ConfigurationRepository asbCommonConfiguration = new ConfigurationRepository();
|
|
|
|
public static string MetaOuterElement = "ArchestrA.Discovery";
|
|
|
|
public static string MetaReplicationElement = "replicationScope";
|
|
|
|
public static string MetaReplicationAttributeName = "scope";
|
|
|
|
public static string MetaReplicationAttributeValue = "localASBSolution";
|
|
|
|
private static readonly int Auto_Port = 0;
|
|
|
|
private static readonly int portStartIndex = 10000;
|
|
|
|
private static readonly int portEndIndex = 15000;
|
|
|
|
public static string ParseCommandLine(string[] args, string switchName)
|
|
{
|
|
if (args == null)
|
|
{
|
|
return string.Empty;
|
|
}
|
|
if (string.IsNullOrEmpty(switchName))
|
|
{
|
|
return string.Empty;
|
|
}
|
|
string text = switchName.ToUpperInvariant();
|
|
if (!switchName.StartsWith("/", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
text = "/" + text;
|
|
}
|
|
foreach (string text2 in args)
|
|
{
|
|
if (text2.ToUpperInvariant().StartsWith(text, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
string text3 = text2.Substring(text.Length);
|
|
if (text3.StartsWith("=", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
text3 = text3.Substring(1);
|
|
}
|
|
return text3;
|
|
}
|
|
}
|
|
return string.Empty;
|
|
}
|
|
|
|
public static Binding GetBinding(string endpointAddress)
|
|
{
|
|
return GetBinding(endpointAddress, NetTcpBindingSecurityMode.None);
|
|
}
|
|
|
|
public static Binding GetBinding(string endpointAddress, NetTcpBindingSecurityMode securityMode)
|
|
{
|
|
Binding result = null;
|
|
string text = endpointAddress.ToLower();
|
|
if (text.StartsWith("http"))
|
|
{
|
|
result = GetWSHttpBinding();
|
|
}
|
|
else if (text.StartsWith("net.tcp"))
|
|
{
|
|
switch (securityMode)
|
|
{
|
|
case NetTcpBindingSecurityMode.None:
|
|
result = GetTcpBinding();
|
|
break;
|
|
case NetTcpBindingSecurityMode.CertificateEncryption:
|
|
result = GetSecureCertificateTcpBinding();
|
|
break;
|
|
case NetTcpBindingSecurityMode.CredentialAuthentication:
|
|
result = GetSecureCredentialTcpBinding();
|
|
break;
|
|
}
|
|
}
|
|
else if (text.StartsWith("net.pipe"))
|
|
{
|
|
result = GetNamedPipeBinding();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public static WSHttpBinding GetHttpBinding()
|
|
{
|
|
return GetWSHttpBinding();
|
|
}
|
|
|
|
public static WSHttpBinding GetWSHttpBinding()
|
|
{
|
|
int num = int.MaxValue;
|
|
WSHttpBinding wSHttpBinding = new WSHttpBinding();
|
|
try
|
|
{
|
|
string parameter = asbCommonConfiguration.GetParameter("HttpBinding.Security.Mode", "None");
|
|
wSHttpBinding.Security.Mode = (SecurityMode)Enum.Parse(typeof(SecurityMode), parameter);
|
|
parameter = asbCommonConfiguration.GetParameter("HttpBinding.AllowCookies", "false");
|
|
wSHttpBinding.AllowCookies = bool.Parse(parameter);
|
|
parameter = asbCommonConfiguration.GetParameter("HttpBinding.BypassProxyOnLocal", "true");
|
|
wSHttpBinding.BypassProxyOnLocal = bool.Parse(parameter);
|
|
parameter = asbCommonConfiguration.GetParameter("HttpBinding.HostNameComparisonMode", "StrongWildcard");
|
|
wSHttpBinding.HostNameComparisonMode = (HostNameComparisonMode)Enum.Parse(typeof(HostNameComparisonMode), parameter);
|
|
parameter = asbCommonConfiguration.GetParameter("HttpBinding.MessageEncoding", "Text");
|
|
wSHttpBinding.MessageEncoding = (WSMessageEncoding)Enum.Parse(typeof(WSMessageEncoding), parameter);
|
|
parameter = asbCommonConfiguration.GetParameter("HttpBinding.MaxReceivedMessageSize", int.MaxValue.ToString());
|
|
wSHttpBinding.MaxReceivedMessageSize = int.Parse(parameter);
|
|
parameter = asbCommonConfiguration.GetParameter("HttpBinding.MaxBufferPoolSize", long.MaxValue.ToString());
|
|
wSHttpBinding.MaxBufferPoolSize = long.Parse(parameter);
|
|
parameter = asbCommonConfiguration.GetParameter("HttpBinding.ReaderQuotas.MaxArrayLength", int.MaxValue.ToString());
|
|
wSHttpBinding.ReaderQuotas.MaxArrayLength = int.Parse(parameter);
|
|
parameter = asbCommonConfiguration.GetParameter("HttpBinding.ReaderQuotas.MaxBytesPerRead", int.MaxValue.ToString());
|
|
wSHttpBinding.ReaderQuotas.MaxBytesPerRead = num;
|
|
parameter = asbCommonConfiguration.GetParameter("HttpBinding.ReaderQuotas.MaxDepth", int.MaxValue.ToString());
|
|
wSHttpBinding.ReaderQuotas.MaxDepth = num;
|
|
parameter = asbCommonConfiguration.GetParameter("HttpBinding.ReaderQuotas.MaxNameTableCharCount", int.MaxValue.ToString());
|
|
wSHttpBinding.ReaderQuotas.MaxNameTableCharCount = num;
|
|
parameter = asbCommonConfiguration.GetParameter("HttpBinding.ReaderQuotas.MaxStringContentLength", int.MaxValue.ToString());
|
|
wSHttpBinding.ReaderQuotas.MaxStringContentLength = num;
|
|
parameter = asbCommonConfiguration.GetParameter("HttpBinding.OpenTimeout", new TimeSpan(0, 1, 0).ToString());
|
|
wSHttpBinding.OpenTimeout = TimeSpan.Parse(parameter);
|
|
parameter = asbCommonConfiguration.GetParameter("HttpBinding.ReceiveTimeout", new TimeSpan(0, 1, 0).ToString());
|
|
wSHttpBinding.ReceiveTimeout = TimeSpan.Parse(parameter);
|
|
parameter = asbCommonConfiguration.GetParameter("HttpBinding.SendTimeout", new TimeSpan(0, 1, 0).ToString());
|
|
wSHttpBinding.SendTimeout = TimeSpan.Parse(parameter);
|
|
parameter = asbCommonConfiguration.GetParameter("HttpBinding.CloseTimeout", new TimeSpan(0, 1, 0).ToString());
|
|
wSHttpBinding.CloseTimeout = TimeSpan.Parse(parameter);
|
|
parameter = asbCommonConfiguration.GetParameter("HttpBinding.ReliableSession.InactivityTimeout", new TimeSpan(0, 1, 0).ToString());
|
|
wSHttpBinding.ReliableSession.InactivityTimeout = TimeSpan.Parse(parameter);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SvcTrace.DiagException.TraceEvent(TraceEventType.Error, 2, $"GetHttpBinding exception: '{ex.Message}'");
|
|
}
|
|
return wSHttpBinding;
|
|
}
|
|
|
|
public static IEnumerable<ASBEndpointDescription> ParseEndpoints(XElement ServiceConfiguration)
|
|
{
|
|
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 2, "ParseEndpoints entry");
|
|
List<ASBEndpointDescription> list = new List<ASBEndpointDescription>();
|
|
string text = "ASBService";
|
|
XAttribute xAttribute = ServiceConfiguration.Attribute("ServiceName");
|
|
if (xAttribute != null)
|
|
{
|
|
text = xAttribute.Value;
|
|
}
|
|
string text2 = "ASBInstance";
|
|
XAttribute xAttribute2 = ServiceConfiguration.Attribute("InstanceName");
|
|
if (xAttribute2 != null)
|
|
{
|
|
text2 = xAttribute2.Value;
|
|
}
|
|
XElement xElement = ServiceConfiguration.Descendants("CommonData").FirstOrDefault();
|
|
IEnumerable<XElement> enumerable = null;
|
|
if (xElement != null)
|
|
{
|
|
enumerable = xElement.Descendants("Endpoint");
|
|
}
|
|
if (enumerable != null)
|
|
{
|
|
foreach (XElement item in enumerable)
|
|
{
|
|
string text3 = "<unknown>";
|
|
XAttribute xAttribute3 = item.Attribute("transport");
|
|
if (xAttribute3 != null)
|
|
{
|
|
text3 = xAttribute3.Value;
|
|
}
|
|
string text4 = "localhost";
|
|
XAttribute xAttribute4 = item.Attribute("address");
|
|
if (xAttribute4 != null)
|
|
{
|
|
text4 = xAttribute4.Value;
|
|
}
|
|
string text5 = string.Empty;
|
|
XAttribute xAttribute5 = item.Attribute("interfaceName");
|
|
if (xAttribute5 != null)
|
|
{
|
|
text5 = xAttribute5.Value;
|
|
}
|
|
string text6 = string.Empty;
|
|
XAttribute xAttribute6 = item.Attribute("port");
|
|
if (xAttribute6 != null)
|
|
{
|
|
text6 = xAttribute6.Value;
|
|
if (text6 == "0")
|
|
{
|
|
text6 = string.Empty;
|
|
}
|
|
}
|
|
string value = string.Empty;
|
|
XAttribute xAttribute7 = item.Attribute("default");
|
|
if (xAttribute7 != null)
|
|
{
|
|
value = xAttribute7.Value;
|
|
}
|
|
bool flag = true;
|
|
if (!string.IsNullOrEmpty(value))
|
|
{
|
|
flag = Convert.ToBoolean(value);
|
|
}
|
|
Binding TypedBinding = null;
|
|
string addressPrefix = GetAddressPrefix(text3, out TypedBinding);
|
|
if (!string.IsNullOrEmpty(text5) && !string.IsNullOrEmpty(addressPrefix) && TypedBinding != null)
|
|
{
|
|
string empty = string.Empty;
|
|
empty = ((!(string.IsNullOrEmpty(text6) || flag)) ? (addressPrefix + "://" + text4 + ":" + text6 + "/" + text + "/" + text2) : (addressPrefix + "://" + text4 + "/" + text + "/" + text2));
|
|
Uri endpointUri = GetEndpointUri(new Uri(empty), bCreatePort: false);
|
|
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 2, "ParseEndpoints adding description: Address = {0} Contract = {1} Binding = {2}", endpointUri, text5, TypedBinding.Name);
|
|
if (flag)
|
|
{
|
|
if (TypedBinding is NetTcpBinding)
|
|
{
|
|
((NetTcpBinding)TypedBinding).PortSharingEnabled = true;
|
|
}
|
|
}
|
|
else if (TypedBinding is NetTcpBinding)
|
|
{
|
|
((NetTcpBinding)TypedBinding).PortSharingEnabled = string.IsNullOrEmpty(text6);
|
|
}
|
|
list.Add(new ASBEndpointDescription(endpointUri, text5, TypedBinding));
|
|
}
|
|
else
|
|
{
|
|
if (string.IsNullOrEmpty(text5))
|
|
{
|
|
SvcTrace.DiagException.TraceEvent(TraceEventType.Error, 2, "ParseEndpoints: <Endpoint /> element in configuration without an interfaceName attribute, no endpoint generated");
|
|
}
|
|
if (string.IsNullOrEmpty(addressPrefix))
|
|
{
|
|
SvcTrace.DiagException.TraceEvent(TraceEventType.Error, 2, $"ParseEndpoints: <Endpoint /> element in configuration with transport attribute='{text3}' does not translate to a scheme, no endpoint generated");
|
|
}
|
|
if (TypedBinding == null)
|
|
{
|
|
SvcTrace.DiagException.TraceEvent(TraceEventType.Error, 2, $"ParseEndpoints: <Endpoint /> element in configuration with transport attribute='{text3}' does not translate to a binding, no endpoint generated");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
|
|
public static string GetAddressPrefix(string Transport, out Binding TypedBinding)
|
|
{
|
|
string result = string.Empty;
|
|
TypedBinding = null;
|
|
if (!string.IsNullOrEmpty(Transport))
|
|
{
|
|
switch (Transport.ToLower())
|
|
{
|
|
case "net.tcp":
|
|
result = "net.tcp";
|
|
TypedBinding = GetTcpBinding();
|
|
break;
|
|
case "basichttp":
|
|
result = "http";
|
|
TypedBinding = new BasicHttpBinding();
|
|
break;
|
|
case "webhttp":
|
|
result = "http";
|
|
TypedBinding = null;
|
|
break;
|
|
case "wsdualhttp":
|
|
result = "http";
|
|
TypedBinding = new WSDualHttpBinding();
|
|
break;
|
|
case "wshttp":
|
|
case "http":
|
|
result = "http";
|
|
TypedBinding = GetWSHttpBinding();
|
|
break;
|
|
default:
|
|
TypedBinding = null;
|
|
break;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public static EndpointAddress GetEndPointAddress(Uri endpointAddressUri)
|
|
{
|
|
return GetEndPointAddress(endpointAddressUri, bCreatePort: true);
|
|
}
|
|
|
|
public static EndpointAddress GetEndPointAddress(Uri endpointAddressUri, bool bCreatePort)
|
|
{
|
|
if (endpointAddressUri == null)
|
|
{
|
|
return null;
|
|
}
|
|
EndpointAddress result = new EndpointAddress(endpointAddressUri);
|
|
Uri endpointUri = GetEndpointUri(endpointAddressUri, bCreatePort);
|
|
if (endpointUri != null)
|
|
{
|
|
result = new EndpointAddress(endpointUri);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public static Uri GetEndpointUri(Uri endpointAddressUri, bool bCreatePort)
|
|
{
|
|
if (endpointAddressUri == null)
|
|
{
|
|
return null;
|
|
}
|
|
try
|
|
{
|
|
UriBuilder uriBuilder = new UriBuilder(endpointAddressUri);
|
|
if (uriBuilder.Scheme != "net.pipe")
|
|
{
|
|
if (endpointAddressUri.OriginalString.IndexOf("localhost", StringComparison.OrdinalIgnoreCase) != -1)
|
|
{
|
|
uriBuilder.Host = Environment.MachineName;
|
|
}
|
|
if (bCreatePort && (uriBuilder.Port == -1 || uriBuilder.Port == Auto_Port))
|
|
{
|
|
uriBuilder.Port = FindAvailablePortOnMachine();
|
|
}
|
|
}
|
|
return uriBuilder.Uri;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SvcTrace.DiagException.TraceEvent(TraceEventType.Warning, 2, $"GetEndpointUri exception: '{ex.Message}'");
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static Uri GetEndpointListenUri(Uri endpointAddress)
|
|
{
|
|
Uri result = null;
|
|
if (endpointAddress != null)
|
|
{
|
|
try
|
|
{
|
|
UriBuilder uriBuilder = new UriBuilder(endpointAddress);
|
|
if (uriBuilder != null)
|
|
{
|
|
IPAddress[] hostAddresses = Dns.GetHostAddresses(uriBuilder.Host);
|
|
foreach (IPAddress iPAddress in hostAddresses)
|
|
{
|
|
if (iPAddress.AddressFamily == AddressFamily.InterNetwork)
|
|
{
|
|
uriBuilder.Host = iPAddress.ToString();
|
|
}
|
|
}
|
|
result = uriBuilder.Uri;
|
|
}
|
|
else
|
|
{
|
|
result = endpointAddress;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SvcTrace.DiagException.TraceEvent(TraceEventType.Warning, 2, $"GetEndpointListenUri exception: '{ex.Message}'");
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public static int FindAvailablePortOnMachine()
|
|
{
|
|
int result = 0;
|
|
Random random = new Random(Environment.TickCount);
|
|
using (Mutex mutex = new Mutex(initiallyOwned: false, "ArchestraCommon"))
|
|
{
|
|
mutex.WaitOne();
|
|
List<int> list = (from p in IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners()
|
|
select p.Port).ToList();
|
|
for (int num = 0; num < 5000; num++)
|
|
{
|
|
int num2 = random.Next(portStartIndex, portEndIndex);
|
|
if (!list.Contains(num2))
|
|
{
|
|
result = num2;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public static EndpointDiscoveryMetadata GetDiscoveryEndpointMetada(EndpointDiscoveryMetadata metaData)
|
|
{
|
|
try
|
|
{
|
|
if (metaData != null)
|
|
{
|
|
UriBuilder uriBuilder = new UriBuilder(metaData.Address.Uri);
|
|
if (uriBuilder != null && !string.IsNullOrEmpty(uriBuilder.Host))
|
|
{
|
|
IPAddress[] hostAddresses = Dns.GetHostAddresses(uriBuilder.Host);
|
|
foreach (IPAddress iPAddress in hostAddresses)
|
|
{
|
|
if (iPAddress.AddressFamily == AddressFamily.InterNetwork)
|
|
{
|
|
uriBuilder.Host = iPAddress.ToString();
|
|
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 2, string.Format(CultureInfo.CurrentCulture, "IP address {0} for host name {1}", new object[2]
|
|
{
|
|
iPAddress.ToString(),
|
|
metaData.Address.Uri.ToString()
|
|
}));
|
|
if (!metaData.ListenUris.Contains(uriBuilder.Uri))
|
|
{
|
|
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 2, string.Format(CultureInfo.CurrentCulture, "IP address {0} is not exist in the ListenUris collection ", new object[1] { uriBuilder.Uri.ToString() }));
|
|
metaData.ListenUris.Insert(0, uriBuilder.Uri);
|
|
}
|
|
else
|
|
{
|
|
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 2, string.Format(CultureInfo.CurrentCulture, "IP address {0} is already exist in the ListenUris collection ", new object[1] { uriBuilder.Uri.ToString() }));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SvcTrace.DiagException.TraceEvent(TraceEventType.Information, 2, string.Format(CultureInfo.CurrentCulture, "GetDiscoveryEndpointMetada: Exception {0}", new object[1] { ex.Message }));
|
|
}
|
|
return metaData;
|
|
}
|
|
|
|
public static string ReadKeyValue(string subKey, string value)
|
|
{
|
|
string result = string.Empty;
|
|
try
|
|
{
|
|
string text = RegistryHandler.RegistryPath;
|
|
if (!string.IsNullOrEmpty(subKey))
|
|
{
|
|
text = text + "\\" + subKey;
|
|
}
|
|
RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(text, writable: false);
|
|
if (registryKey != null)
|
|
{
|
|
object value2 = registryKey.GetValue(value);
|
|
if (value2 != null)
|
|
{
|
|
result = value2.ToString();
|
|
}
|
|
registryKey.Close();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SvcTrace.DiagException.TraceEvent(TraceEventType.Error, 0, $"ReadKeyValue: Exception caught: {ex.Message}");
|
|
result = string.Empty;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public static void GetLocalDiscoveryInfoFromWatchdogConfigFile(string WatchdogConfigFilePath, out string LocalDiscovery)
|
|
{
|
|
LocalDiscovery = string.Empty;
|
|
if (!File.Exists(WatchdogConfigFilePath))
|
|
{
|
|
return;
|
|
}
|
|
try
|
|
{
|
|
XElement xElement = XElement.Load(WatchdogConfigFilePath);
|
|
if (!xElement.Elements("appSettings").Any())
|
|
{
|
|
return;
|
|
}
|
|
foreach (XElement item in xElement.Elements("appSettings").Descendants())
|
|
{
|
|
if (item.Attribute("key") != null && item.Attribute("key").Value == "LocalDiscoveryEndpoint" && item.Attribute("value") != null)
|
|
{
|
|
LocalDiscovery = item.Attribute("value").Value;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SvcTrace.DiagException.TraceEvent(TraceEventType.Error, 0, $"GetLocalDiscoveryInfoFromWatchdogConfigFile: Exception caught: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
public static void GetDiscoveryInfoFromWatchdogConfigFile(string WatchdogConfigFilePath, out string Discovery1, out string Discovery2)
|
|
{
|
|
Discovery1 = string.Empty;
|
|
Discovery2 = string.Empty;
|
|
if (!File.Exists(WatchdogConfigFilePath))
|
|
{
|
|
return;
|
|
}
|
|
try
|
|
{
|
|
XElement xElement = XElement.Load(WatchdogConfigFilePath);
|
|
if (!xElement.Elements("appSettings").Any())
|
|
{
|
|
return;
|
|
}
|
|
foreach (XElement item in xElement.Elements("appSettings").Descendants())
|
|
{
|
|
if (item.Attribute("key") != null && item.Attribute("key").Value == "PrimaryGlobalDiscoveryEndpoint" && item.Attribute("value") != null)
|
|
{
|
|
Discovery1 = item.Attribute("value").Value;
|
|
}
|
|
if (item.Attribute("key") != null && item.Attribute("key").Value == "SecondaryGlobalDiscoveryEndpoint" && item.Attribute("value") != null)
|
|
{
|
|
Discovery2 = item.Attribute("value").Value;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SvcTrace.DiagException.TraceEvent(TraceEventType.Error, 0, $"GetDiscoveryInfoFromWatchdogConfigFile: Exception caught: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
public static string GetDiscoveryEndpoint()
|
|
{
|
|
string empty = string.Empty;
|
|
empty = ReadKeyValue(RegistryHandler.ASBRegistration, RegistryHandler.LDSEndPoint);
|
|
if (string.IsNullOrEmpty(empty))
|
|
{
|
|
empty = "net.tcp://localhost/LDS/Probe";
|
|
}
|
|
return empty;
|
|
}
|
|
|
|
public static bool UpdateWatchDogFile(string WatchdogConfigFilePath, string endpoint1, string endpoint2)
|
|
{
|
|
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "UpdateWatchDogFile: returning true.");
|
|
return true;
|
|
}
|
|
|
|
public static string ReadWatchdogConfigFilePath()
|
|
{
|
|
string text = ReadKeyValue(string.Empty, "ASBInstallPath");
|
|
if (!string.IsNullOrEmpty(text))
|
|
{
|
|
text = Path.Combine(text, "aaServiceWatchdog.exe.config");
|
|
}
|
|
return text;
|
|
}
|
|
|
|
public static void PersistDiscoveryInfo(string discovery1, string discovery2)
|
|
{
|
|
string text = ReadWatchdogConfigFilePath();
|
|
if (!string.IsNullOrEmpty(text))
|
|
{
|
|
UpdateWatchDogFile(text, discovery1, discovery2);
|
|
}
|
|
}
|
|
|
|
public static void WriteKeyValue(string subKey, string key, string value)
|
|
{
|
|
try
|
|
{
|
|
string text = RegistryHandler.RegistryPath;
|
|
if (!string.IsNullOrEmpty(subKey))
|
|
{
|
|
text = text + "\\" + subKey;
|
|
}
|
|
Registry.LocalMachine.OpenSubKey(text, writable: true)?.SetValue(key, value);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SvcTrace.DiagException.TraceEvent(TraceEventType.Error, 0, $"WriteKeyValue: Exception caught: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
public static bool IsKeyExist(string subKey, string value)
|
|
{
|
|
try
|
|
{
|
|
string text = RegistryHandler.RegistryPath;
|
|
if (!string.IsNullOrEmpty(subKey))
|
|
{
|
|
text = text + "\\" + subKey;
|
|
}
|
|
RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(text, writable: false);
|
|
if (registryKey != null && registryKey.GetValue(value) != null)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SvcTrace.DiagException.TraceEvent(TraceEventType.Error, 0, $"IsKeyExist: Exception caught: {ex.Message}");
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static void CreateKeysIfNotExist(string subKey)
|
|
{
|
|
if (!IsKeyExist(subKey, "NodeRegistration"))
|
|
{
|
|
string text = RegistryHandler.RegistryPath;
|
|
if (!string.IsNullOrEmpty(subKey))
|
|
{
|
|
text = text + "\\" + subKey;
|
|
}
|
|
text += "\\NodeRegistration";
|
|
try
|
|
{
|
|
Registry.LocalMachine.CreateSubKey(text);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SvcTrace.DiagException.TraceEvent(TraceEventType.Error, 0, $"CreateKeysIfNotExist: Exception caught: {ex.Message}");
|
|
}
|
|
}
|
|
}
|
|
|
|
public static Collection<Uri> CreateRegisterScopes(string version, string serviceName, string dataType, string domain, string nameSpace, XElement configuration, List<string> extraScopes)
|
|
{
|
|
if (string.IsNullOrEmpty(version) || string.IsNullOrEmpty(serviceName) || string.IsNullOrEmpty(dataType) || string.IsNullOrEmpty(domain) || string.IsNullOrEmpty(nameSpace))
|
|
{
|
|
SvcTrace.DiagException.TraceEvent(TraceEventType.Warning, 0, "While creating Discovery scopes for a service, one of (version, serviceName, dataType, domain, or nameSpace) was missing, generating scopes for the rest");
|
|
}
|
|
Collection<Uri> collection = CreateFindScopes(version, serviceName, dataType, domain, nameSpace, extraScopes);
|
|
RegistryHandler.GetDefaultSolutionName(out var DefaultSolutionName);
|
|
if (!string.IsNullOrEmpty(DefaultSolutionName))
|
|
{
|
|
BuildScopeUri("asbsolution/", DefaultSolutionName, collection);
|
|
}
|
|
return collection;
|
|
}
|
|
|
|
public static Collection<Uri> CreateFindScopes(string version, string serviceName, string dataType, string domain, string nameSpace, List<string> extraScopes)
|
|
{
|
|
Collection<Uri> collection = new Collection<Uri>();
|
|
if (extraScopes != null)
|
|
{
|
|
foreach (string extraScope in extraScopes)
|
|
{
|
|
BuildScopeUri(string.Empty, extraScope, collection);
|
|
}
|
|
}
|
|
if (!string.IsNullOrEmpty(serviceName))
|
|
{
|
|
BuildScopeUri("instancename/", serviceName, collection);
|
|
}
|
|
if (!string.IsNullOrEmpty(version))
|
|
{
|
|
BuildScopeUri("serviceversion/", version, collection);
|
|
}
|
|
if (!string.IsNullOrEmpty(dataType))
|
|
{
|
|
BuildScopeUri("datatype/", dataType, collection);
|
|
}
|
|
if (!string.IsNullOrEmpty(domain))
|
|
{
|
|
BuildScopeUri("domainname/", domain, collection);
|
|
}
|
|
if (!string.IsNullOrEmpty(nameSpace))
|
|
{
|
|
BuildScopeUri("namespace/", nameSpace, collection);
|
|
}
|
|
return collection;
|
|
}
|
|
|
|
public static Collection<Uri> CreateRegisterScopes(string version, string serviceName, string dataType, XElement configuration, List<string> extraScopes)
|
|
{
|
|
if (string.IsNullOrEmpty(version) || string.IsNullOrEmpty(serviceName) || string.IsNullOrEmpty(dataType))
|
|
{
|
|
SvcTrace.DiagException.TraceEvent(TraceEventType.Warning, 0, "While creating Discovery scopes for a service, one of (version, serviceName, or dataType) was missing, generating scopes for the rest");
|
|
}
|
|
Collection<Uri> collection = CreateFindScopes(version, serviceName, dataType, extraScopes);
|
|
RegistryHandler.GetDefaultSolutionName(out var DefaultSolutionName);
|
|
if (!string.IsNullOrEmpty(DefaultSolutionName))
|
|
{
|
|
BuildScopeUri("asbsolution/", DefaultSolutionName, collection);
|
|
}
|
|
return collection;
|
|
}
|
|
|
|
public static Collection<Uri> CreateFindScopes(string version, string serviceName, string dataType, List<string> extraScopes)
|
|
{
|
|
Collection<Uri> collection = new Collection<Uri>();
|
|
if (extraScopes != null)
|
|
{
|
|
foreach (string extraScope in extraScopes)
|
|
{
|
|
BuildScopeUri(string.Empty, extraScope, collection);
|
|
}
|
|
}
|
|
if (!string.IsNullOrEmpty(serviceName))
|
|
{
|
|
BuildScopeUri("instancename/", serviceName, collection);
|
|
}
|
|
if (!string.IsNullOrEmpty(version))
|
|
{
|
|
BuildScopeUri("serviceversion/", version, collection);
|
|
}
|
|
if (!string.IsNullOrEmpty(dataType))
|
|
{
|
|
BuildScopeUri("datatype/", dataType, collection);
|
|
}
|
|
return collection;
|
|
}
|
|
|
|
public static bool IsGRInstalled(out string message)
|
|
{
|
|
bool result = false;
|
|
message = string.Empty;
|
|
try
|
|
{
|
|
if ((from svc in ServiceController.GetServices()
|
|
where svc.ServiceName == "aaGR"
|
|
select svc).FirstOrDefault() != null)
|
|
{
|
|
result = true;
|
|
message = "IsGRInstalled()::true; aaGR Service is Installed.";
|
|
}
|
|
else
|
|
{
|
|
message = "IsGRInstalled()::false; aaGR Service is not Installed.";
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
message = ex.ToString();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public static bool IsAnyPlatformIsDeployed(out string strFromMachineName, out string strGalaxyName, out string message)
|
|
{
|
|
bool result = false;
|
|
strFromMachineName = string.Empty;
|
|
strGalaxyName = string.Empty;
|
|
message = string.Empty;
|
|
string name = "SOFTWARE\\ArchestrA\\Framework\\ClusterInformation";
|
|
RegistryKey registryKey = null;
|
|
try
|
|
{
|
|
registryKey = Registry.LocalMachine.OpenSubKey(name, writable: false);
|
|
if (registryKey != null)
|
|
{
|
|
strGalaxyName = registryKey.GetValue("ClusterName").ToString();
|
|
strFromMachineName = registryKey.GetValue("GalaxyPlatformName").ToString();
|
|
result = true;
|
|
message = "IsAnyPlatformIsDeployed():: true; platform is deployed.";
|
|
}
|
|
else
|
|
{
|
|
message = "IsAnyPlatformIsDeployed():: false; platform is not deployed.";
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
message = ex.ToString();
|
|
}
|
|
finally
|
|
{
|
|
registryKey?.Close();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private static void BuildScopeUri(string scopeType, string scopeName, Collection<Uri> scopeCollection)
|
|
{
|
|
if (scopeCollection != null && !string.IsNullOrEmpty(scopeName))
|
|
{
|
|
string text = scopeName;
|
|
if (!text.StartsWith("archestra://", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
text = "archestra://asb/" + scopeType + scopeName;
|
|
}
|
|
scopeCollection.Add(new Uri(text.ToLower(CultureInfo.InvariantCulture)));
|
|
}
|
|
}
|
|
|
|
public static NetTcpBinding GetTcpBinding()
|
|
{
|
|
int num = int.MaxValue;
|
|
NetTcpBinding netTcpBinding = new NetTcpBinding();
|
|
try
|
|
{
|
|
netTcpBinding.Security.Mode = SecurityMode.None;
|
|
netTcpBinding.TransferMode = TransferMode.Buffered;
|
|
netTcpBinding.PortSharingEnabled = true;
|
|
netTcpBinding.MaxReceivedMessageSize = num;
|
|
netTcpBinding.MaxBufferSize = num;
|
|
netTcpBinding.MaxBufferPoolSize = long.MaxValue;
|
|
netTcpBinding.ReaderQuotas.MaxArrayLength = num;
|
|
netTcpBinding.ReaderQuotas.MaxBytesPerRead = num;
|
|
netTcpBinding.ReaderQuotas.MaxDepth = num;
|
|
netTcpBinding.ReaderQuotas.MaxNameTableCharCount = num;
|
|
netTcpBinding.ReaderQuotas.MaxStringContentLength = num;
|
|
netTcpBinding.OpenTimeout = new TimeSpan(0, 1, 0);
|
|
netTcpBinding.ReceiveTimeout = new TimeSpan(0, 1, 0);
|
|
netTcpBinding.SendTimeout = new TimeSpan(0, 1, 0);
|
|
netTcpBinding.CloseTimeout = new TimeSpan(0, 1, 0);
|
|
netTcpBinding.ReliableSession.InactivityTimeout = new TimeSpan(0, 1, 0);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SvcTrace.DiagException.TraceEvent(TraceEventType.Error, 2, $"GetTcpBinding exception: '{ex.Message}'");
|
|
}
|
|
return netTcpBinding;
|
|
}
|
|
|
|
public static NetTcpBinding GetAnnouncementBinding()
|
|
{
|
|
if (RegistryHandler.SecureCommunicationMode != SecureCommunicationModes.Never)
|
|
{
|
|
return GetSecureCredentialTcpBinding();
|
|
}
|
|
return GetTcpBinding();
|
|
}
|
|
|
|
public static NetTcpBinding GetAnnouncementBinding(Uri announcementAddress)
|
|
{
|
|
if (announcementAddress.AbsoluteUri.Contains("/LDS/") && RegistryHandler.SecureCommunicationMode != SecureCommunicationModes.Never)
|
|
{
|
|
return GetSecureCredentialTcpBinding();
|
|
}
|
|
return GetTcpBinding();
|
|
}
|
|
|
|
public static NetTcpBinding GetSecureCertificateTcpBinding()
|
|
{
|
|
NetTcpBinding tcpBinding = GetTcpBinding();
|
|
try
|
|
{
|
|
tcpBinding.Security.Mode = SecurityMode.Transport;
|
|
tcpBinding.Security.Transport.ProtectionLevel = ProtectionLevel.EncryptAndSign;
|
|
tcpBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SvcTrace.DiagException.TraceEvent(TraceEventType.Error, 2, $"GetTcpBinding exception: '{ex.Message}'");
|
|
}
|
|
return tcpBinding;
|
|
}
|
|
|
|
private static NetTcpBinding GetSecureCredentialTcpBinding()
|
|
{
|
|
NetTcpBinding tcpBinding = GetTcpBinding();
|
|
try
|
|
{
|
|
tcpBinding.Security.Mode = SecurityMode.Transport;
|
|
tcpBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SvcTrace.DiagException.TraceEvent(TraceEventType.Error, 2, $"GetTcpBinding exception: '{ex.Message}'");
|
|
}
|
|
return tcpBinding;
|
|
}
|
|
|
|
public static NetNamedPipeBinding GetNamedPipeBinding()
|
|
{
|
|
int num = int.MaxValue;
|
|
NetNamedPipeBinding netNamedPipeBinding = new NetNamedPipeBinding();
|
|
try
|
|
{
|
|
netNamedPipeBinding.Security.Mode = NetNamedPipeSecurityMode.None;
|
|
netNamedPipeBinding.TransferMode = TransferMode.Buffered;
|
|
netNamedPipeBinding.MaxReceivedMessageSize = num;
|
|
netNamedPipeBinding.MaxBufferSize = num;
|
|
netNamedPipeBinding.MaxBufferPoolSize = long.MaxValue;
|
|
netNamedPipeBinding.ReaderQuotas.MaxArrayLength = num;
|
|
netNamedPipeBinding.ReaderQuotas.MaxBytesPerRead = num;
|
|
netNamedPipeBinding.ReaderQuotas.MaxDepth = num;
|
|
netNamedPipeBinding.ReaderQuotas.MaxNameTableCharCount = num;
|
|
netNamedPipeBinding.ReaderQuotas.MaxStringContentLength = num;
|
|
netNamedPipeBinding.OpenTimeout = new TimeSpan(0, 1, 0);
|
|
netNamedPipeBinding.ReceiveTimeout = new TimeSpan(0, 1, 0);
|
|
netNamedPipeBinding.SendTimeout = new TimeSpan(0, 1, 0);
|
|
netNamedPipeBinding.CloseTimeout = new TimeSpan(0, 1, 0);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SvcTrace.DiagException.TraceEvent(TraceEventType.Error, 2, $"NetNamedPipeBinding exception: '{ex.Message}'");
|
|
}
|
|
return netNamedPipeBinding;
|
|
}
|
|
}
|