Files
mxaccess/analysis/decompiled/aaServicesContractIAuthenticateASB/Asb.Base.V2/BaseV2Client.cs
T
Joseph Doherty fe2a6db786
rust / build / test / clippy / fmt (push) Has been cancelled
Initial project state: .NET reference, design, Rust port (M0+M1), evidence
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>
2026-05-05 06:21:00 -04:00

662 lines
23 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Net;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Discovery;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using ArchestrAServices.Common;
using ArchestrAServices.Proxy;
using Asb.Base.V2.ContractTypes;
namespace Asb.Base.V2;
public class BaseV2Client<T> : IBaseV2, IDisposable where T : class, IAuthenticateAsb
{
private readonly object connectionLock = new object();
private readonly string connectionUser = string.Empty;
private readonly string connectionApplication = string.Empty;
private readonly TimeSpan timeToWaitForConnection = DefaultTimeToWaitForConnection;
private IClientManagement clientManager;
private long connectionInProgress;
private ConnectContext<T> successfulConnectionResult;
private ManualResetEvent connectionEstablishedEvent;
private bool disposed;
public static TimeSpan DefaultTimeToWaitForConnection => TimeSpan.FromSeconds(20.0);
public SecureCommunicationModes SecureCommunicationMode { get; set; }
public DateTime ServiceLoadTime { get; set; }
public bool Connected
{
get
{
if (successfulConnectionResult?.ServiceChannel != null)
{
return successfulConnectionResult.ServiceChannel.State == CommunicationState.Opened;
}
return false;
}
}
public CommunicationState State
{
get
{
if (successfulConnectionResult != null && successfulConnectionResult.ServiceChannel != null)
{
return successfulConnectionResult.ServiceChannel.State;
}
return CommunicationState.Closed;
}
}
public ConnectionState DownstreamConnectionState { get; protected set; }
internal ConnectContext<T> Context => successfulConnectionResult;
protected T ChannelClient => successfulConnectionResult.ServiceClient;
public Guid ConnectionId
{
get
{
if (successfulConnectionResult != null)
{
return successfulConnectionResult.ConnectionId;
}
return Guid.Empty;
}
set
{
}
}
public BaseV2Client()
{
clientManager = new ClientManagement();
SecureCommunicationMode = RegistryHandler.SecureCommunicationMode;
}
public BaseV2Client(TimeSpan connectTimeout)
: this()
{
if (connectTimeout.TotalMilliseconds > 2147483647.0 || connectTimeout < TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException("connectTimeout");
}
timeToWaitForConnection = connectTimeout;
}
internal BaseV2Client(TimeSpan connectTimeout, IClientManagement manager)
: this(manager)
{
if (connectTimeout.TotalMilliseconds > 2147483647.0 || connectTimeout < TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException("connectTimeout");
}
timeToWaitForConnection = connectTimeout;
}
internal BaseV2Client(TimeSpan connectTimeout, IClientManagement manager, string application, string user)
: this(connectTimeout, manager)
{
connectionApplication = application;
connectionUser = user;
}
public BaseV2Client(TimeSpan connectTimeout, string application, string user)
: this(connectTimeout)
{
connectionApplication = application;
connectionUser = user;
}
internal BaseV2Client(IClientManagement manager)
{
clientManager = manager;
SecureCommunicationMode = RegistryHandler.SecureCommunicationMode;
}
public bool Connect(EndpointDiscoveryMetadata selectedMetadata, string solutionName, ClientAccess access, Action<string> errorCallback)
{
return Connect(selectedMetadata, solutionName, access, errorCallback, useSecureConnection: false);
}
public bool Connect(EndpointDiscoveryMetadata selectedMetadata, string solutionName, ClientAccess access, Action<string> errorCallback, bool useSecureConnection)
{
ServiceTrace.LogCsv("Connect (endpoint discovered) entry");
ServiceTrace.LogResume("Connect (endpoint discovered) entry");
if (Interlocked.CompareExchange(ref connectionInProgress, 1L, 0L) != 0L)
{
string text = string.Format(CultureInfo.InvariantCulture, "Connect: another connection is in progress, cannot attempt a connection using selected discovery metadata");
ServiceTrace.LogError(text);
errorCallback?.Invoke(text);
return false;
}
try
{
bool flag = EstablishConnection(selectedMetadata, solutionName, access, errorCallback, useSecureConnection);
ServiceTrace.LogSuspend("Connect (endpoint discovered) exit, {0}", flag ? "succeeded" : "failed");
ServiceTrace.LogCsv("Connect (endpoint discovered) exit [success]", flag);
return flag;
}
finally
{
Interlocked.Exchange(ref connectionInProgress, 0L);
}
}
public void Disconnect()
{
ServiceTrace.LogCsv("Disconnect entry");
ServiceTrace.LogResume("Disconnect entry");
if (successfulConnectionResult == null || !successfulConnectionResult.Success)
{
return;
}
SystemAuthenticationClientAuthentication.DisconnectSecureSession(successfulConnectionResult.ConnectionId, delegate(DisconnectRequest request)
{
if (successfulConnectionResult != null && successfulConnectionResult.Success)
{
if (successfulConnectionResult.ServiceClient != null && successfulConnectionResult.ServiceChannel != null && successfulConnectionResult.ServiceChannel.State != CommunicationState.Faulted)
{
ServiceTrace.LogCsv("Calling WCF channel Disconnect method");
successfulConnectionResult.ServiceClient.Disconnect(request);
ServiceTrace.LogCsv("Returned from WCF channel Disconnect method");
}
Reset();
}
});
DownstreamConnectionState = ConnectionState.Unknown;
ServiceTrace.LogSuspend("Disconnect exit");
ServiceTrace.LogCsv("Disconnect exit");
}
public void Abort()
{
Reset();
}
internal void InjectClientManager(IClientManagement manager)
{
clientManager = manager;
}
protected static ReadOnlyCollection<EndpointDiscoveryMetadata> DiscoverEndpoints(XmlQualifiedName contract, string scopeRule)
{
return DiscoverEndpoints(contract, scopeRule, null);
}
protected static ReadOnlyCollection<EndpointDiscoveryMetadata> DiscoverEndpoints(XmlQualifiedName contract, string scopeRule, bool? useSecureConnection)
{
List<EndpointDiscoveryMetadata> list = new ClientManagement().DiscoverEndpointsForContract(contract, scopeRule)?.ToList();
if (list == null)
{
ServiceTrace.LogWarning(string.Format(CultureInfo.InvariantCulture, "DiscoverEndpoints: null FindResponse finding contract {0} with access name {1}", new object[2] { contract.Name, scopeRule }));
return new ReadOnlyCollection<EndpointDiscoveryMetadata>(new EndpointDiscoveryMetadata[0]);
}
if (list.Count == 0)
{
ServiceTrace.LogInfo(string.Format(CultureInfo.InvariantCulture, "DiscoverEndpoints found no endpoints for contract {0} with access name {1}", new object[2] { contract.Name, scopeRule }));
return new ReadOnlyCollection<EndpointDiscoveryMetadata>(new EndpointDiscoveryMetadata[0]);
}
return new ReadOnlyCollection<EndpointDiscoveryMetadata>(list);
}
protected bool Connect(XmlQualifiedName contract, string scopeRule, ClientAccess access, Action<string> errorCallback)
{
return Connect(contract, scopeRule, access, errorCallback, useSecureConnection: false);
}
protected bool Connect(XmlQualifiedName contract, string scopeRule, ClientAccess access, Action<string> errorCallback, bool useSecureConnection)
{
ServiceTrace.LogCsv("Connect (discover endpoint) entry");
ServiceTrace.LogResume("Connect (discover endpoint) entry");
if (contract == null)
{
string text = string.Format(CultureInfo.InvariantCulture, "Connect: no contract provided, no connection is possible");
ServiceTrace.LogError(text);
errorCallback?.Invoke(text);
return false;
}
if (Interlocked.CompareExchange(ref connectionInProgress, 1L, 0L) != 0L)
{
string text2 = string.Format(CultureInfo.InvariantCulture, "Connect: another connection is in progress, cannot attempt a connection with a specified contract and access name");
ServiceTrace.LogError(text2);
errorCallback?.Invoke(text2);
return false;
}
try
{
List<EndpointDiscoveryMetadata> list = clientManager.DiscoverEndpointsForContract(contract, scopeRule)?.ToList();
if (list == null)
{
string text3 = string.Format(CultureInfo.InvariantCulture, "Connect: null FindResponse finding contract {0} with access name {1}", new object[2] { contract.Name, scopeRule });
ServiceTrace.LogError(text3);
errorCallback?.Invoke(text3);
return false;
}
if (list.Count == 0)
{
string text4 = string.Format(CultureInfo.InvariantCulture, "Connect found no endpoints for contract {0} with access name {1}", new object[2] { contract.Name, scopeRule });
ServiceTrace.LogError(text4);
errorCallback?.Invoke(text4);
return false;
}
EndpointDiscoveryMetadata selectedMetadata;
if (list.Count > 1)
{
Random random = new Random(DateTime.Now.Millisecond);
selectedMetadata = list[random.Next(list.Count)];
}
else
{
selectedMetadata = list[0];
}
bool flag = EstablishConnection(selectedMetadata, string.Empty, access, errorCallback, useSecureConnection);
ServiceTrace.LogSuspend("Connect (discover endpoint) exit, {0}", flag ? "succeeded" : "failed");
ServiceTrace.LogCsv("Connect (discover endpoint) exit [success]", flag);
return flag;
}
finally
{
Interlocked.Exchange(ref connectionInProgress, 0L);
}
}
protected UserTokenContract EncryptUserToken(UserToken originalToken)
{
if (originalToken == null)
{
return null;
}
UserTokenContract userTokenContract = new UserTokenContract
{
Encryption = originalToken.Encryption,
HostName = originalToken.HostName,
IdType = originalToken.IdType,
LocationId = originalToken.LocationId,
UserName = originalToken.UserName,
Validity = originalToken.Validity
};
SystemAuthenticationClientAuthentication clientAuthenticator = SysAuthenticatorClientCache.GetClientAuthenticator(successfulConnectionResult.ConnectionId);
if (clientAuthenticator == null || !clientAuthenticator.SecureSessionEstablished)
{
throw new InvalidOperationException("Cannot encrypt user token due to session in wrong state");
}
if (originalToken.Password != null)
{
byte[] bytes = Encoding.UTF8.GetBytes(originalToken.Password);
userTokenContract.Password = clientAuthenticator.Encypher(bytes, clientAuthenticator.EncryptionKey);
}
if (originalToken.SamlToken != null)
{
userTokenContract.SamlToken = clientAuthenticator.Encypher(originalToken.SamlToken, clientAuthenticator.EncryptionKey);
}
if (originalToken.JwtToken != null)
{
byte[] bytes2 = Encoding.UTF8.GetBytes(originalToken.JwtToken);
userTokenContract.JwtToken = clientAuthenticator.Encypher(bytes2, clientAuthenticator.EncryptionKey);
}
if (originalToken.X509Certificate != null)
{
userTokenContract.X509Certificate = clientAuthenticator.Encypher(originalToken.X509Certificate, clientAuthenticator.EncryptionKey);
}
return userTokenContract;
}
protected void Reset()
{
successfulConnectionResult?.Dispose();
successfulConnectionResult = null;
}
private bool EstablishConnection(EndpointDiscoveryMetadata selectedMetadata, string solutionName, ClientAccess access, Action<string> errorCallback, bool useSecureConnection)
{
ServiceTrace.LogCsv("CreateConnectContext entry");
ServiceTrace.LogResume("CreateConnectContext entry");
if (selectedMetadata == null)
{
errorCallback?.Invoke("No discovery endpoint metadata provided, cannot connect");
return false;
}
if (string.IsNullOrWhiteSpace(solutionName))
{
solutionName = new ASBSolutionManager().GetASBSolutionName(selectedMetadata, out var errorMessage);
if (!string.IsNullOrEmpty(errorMessage))
{
errorCallback?.Invoke(errorMessage);
return false;
}
}
lock (connectionLock)
{
successfulConnectionResult = null;
connectionEstablishedEvent = new ManualResetEvent(initialState: false);
}
using (CancellationTokenSource cancellationTokenSource = new CancellationTokenSource())
{
SpinConnectionTasks(selectedMetadata.ListenUris, solutionName, access, errorCallback, useSecureConnection, cancellationTokenSource.Token);
bool flag = connectionEstablishedEvent.WaitOne(timeToWaitForConnection);
ServiceTrace.LogVerbose("{0} task connected with the service", flag ? "A" : "No");
cancellationTokenSource.Cancel();
}
bool result;
lock (connectionLock)
{
connectionEstablishedEvent.Dispose();
connectionEstablishedEvent = null;
result = true;
if (successfulConnectionResult == null)
{
result = false;
errorCallback?.Invoke("No connection was established with a service endpoint");
}
}
ServiceTrace.LogSuspend("CreateConnectContext exit");
ServiceTrace.LogCsv("CreateConnectContext exit");
return result;
}
private void SpinConnectionTasks(Collection<Uri> listenUris, string solutionName, ClientAccess access, Action<string> errorCallback, bool useSecureConnection, CancellationToken cancellationToken)
{
ServiceTrace.LogVerbose("Spinning tasks for {0} listen Uris", listenUris.Count);
foreach (Uri endpointUri in listenUris)
{
string selectedEndpointUri = endpointUri.ToString();
Task.Factory.StartNew(delegate
{
NetTcpBindingSecurityMode securityMode = (useSecureConnection ? NetTcpBindingSecurityMode.CertificateEncryption : NetTcpBindingSecurityMode.None);
Binding binding = SvcUtilities.GetBinding(selectedEndpointUri, securityMode);
binding.OpenTimeout = new TimeSpan(0, 10, 0);
binding.ReceiveTimeout = new TimeSpan(0, 10, 0);
binding.SendTimeout = new TimeSpan(0, 10, 0);
binding.CloseTimeout = new TimeSpan(0, 10, 0);
EndpointAddress serviceEndpointAddress = new EndpointAddress(selectedEndpointUri);
if (useSecureConnection)
{
IPHostEntry hostEntry = Dns.GetHostEntry(endpointUri.Host);
serviceEndpointAddress = new EndpointAddress(endpointUri, EndpointIdentity.CreateDnsIdentity(hostEntry.HostName));
}
InternalConnect(serviceEndpointAddress, binding, solutionName, access, errorCallback, cancellationToken);
}, cancellationToken, TaskCreationOptions.None, TaskScheduler.Default);
}
}
private void InternalConnect(EndpointAddress serviceEndpointAddress, Binding binding, string solutionName, ClientAccess access, Action<string> errorCallback, CancellationToken cancellationToken)
{
if (serviceEndpointAddress == null)
{
throw new ArgumentNullException("serviceEndpointAddress");
}
if (binding == null)
{
throw new ArgumentNullException("binding");
}
if (string.IsNullOrEmpty(solutionName))
{
throw new ArgumentNullException("solutionName");
}
try
{
EstablishChannelConnection(serviceEndpointAddress, binding, solutionName, access, errorCallback, cancellationToken);
}
catch (CommunicationException ex)
{
ServiceTrace.LogWarning("BaseV2Client caught CommunicationException opening channel: " + ex.Message);
errorCallback?.Invoke("BaseV2Client caught CommunicationException opening channel: " + ex.Message);
if (ex.InnerException != null)
{
ServiceTrace.LogWarning(" " + ex.InnerException.Message);
errorCallback?.Invoke(" " + ex.InnerException.Message);
}
}
catch (TimeoutException ex2)
{
ServiceTrace.LogWarning("BaseV2Client caught TimeoutException opening channel: " + ex2.Message);
errorCallback?.Invoke("BaseV2Client caught TimeoutException opening channel: " + ex2.Message);
if (ex2.InnerException != null)
{
ServiceTrace.LogWarning(" " + ex2.InnerException.Message);
errorCallback?.Invoke(" " + ex2.InnerException.Message);
}
}
catch (Exception ex3)
{
ServiceTrace.LogWarning("BaseV2Client caught exception opening channel: " + ex3.Message);
errorCallback?.Invoke("BaseV2Client caught exception opening channel: " + ex3.Message);
}
}
private void EstablishChannelConnection(EndpointAddress serviceEndpointAddress, Binding binding, string solutionName, ClientAccess access, Action<string> errorCallback, CancellationToken cancellationToken)
{
ConnectContext<T> connectContext = clientManager.CreateConnectContext<T>(serviceEndpointAddress, binding, connectionApplication, connectionUser, cancellationToken);
if ((connectContext != null && connectContext.ServiceChannelFactory?.State == CommunicationState.Closed) || (connectContext != null && connectContext.ServiceChannel?.State == CommunicationState.Closed))
{
return;
}
if (clientManager.EstablishSecureSession(connectContext, solutionName, access))
{
ServiceTrace.LogVerbose("Secure connection with endpoint {0} is established using solution {1}", serviceEndpointAddress.Uri.AbsoluteUri, solutionName);
bool flag = false;
lock (connectionLock)
{
if (successfulConnectionResult == null)
{
flag = true;
successfulConnectionResult = connectContext;
ServiceTrace.LogVerbose("Secure connection with endpoint {0} using solution {1} is first, signal success", serviceEndpointAddress.Uri.AbsoluteUri, solutionName);
connectionEstablishedEvent?.Set();
}
}
if (!flag)
{
ServiceTrace.LogVerbose("Secure connection with endpoint {0} using solution {1} is NOT first, disconnect", serviceEndpointAddress.Uri.AbsoluteUri, solutionName);
clientManager.DisconnectSecureSession(connectContext);
connectContext.Dispose();
}
}
else
{
if (connectContext != null && !string.IsNullOrEmpty(connectContext.ErrorMessage))
{
errorCallback?.Invoke(connectContext.ErrorMessage);
}
ServiceTrace.LogVerbose("Connection with endpoint {0} using solution {1} rejected", serviceEndpointAddress.Uri.AbsoluteUri, solutionName);
if (connectionEstablishedEvent != null)
{
connectionEstablishedEvent.Set();
}
}
}
public void OnConnect(ulong timeout, ConsumerMetadata metadata)
{
ServiceTrace.LogCsv("OnConnect entry");
ServiceTrace.LogResume("OnConnect entry");
throw new NotImplementedException();
}
public ArchestrAResult KeepAlive()
{
ServiceTrace.LogCsv("KeepAlive entry");
ServiceTrace.LogResume("KeepAlive entry");
ArchestrAResult archestrAResult = PrepareToSend(new KeepAliveRequest(), delegate(ConnectedRequest request, T channelClient)
{
ServiceTrace.LogVerbose("Calling WCF channel KeepAlive method");
KeepAliveResponse keepAliveResponse = channelClient.KeepAlive((KeepAliveRequest)request);
ServiceTrace.LogVerbose("Returned from WCF channel KeepAlive method");
if (keepAliveResponse == null)
{
return ArchestrAResult.MakeResult(ArchestrAError.BadNoCommunication, 0).AddErrorMessage("No response from the service");
}
UpdateDownstreamConnectionState(keepAliveResponse);
return keepAliveResponse.Result;
});
ServiceTrace.LogSuspend("KeepAlive exit with {0}", archestrAResult.Success ? "success" : "failure");
ServiceTrace.LogCsv("KeepAlive exit [success]", archestrAResult.Success);
return archestrAResult;
}
public ArchestrAResult GetStatusItems(out string[] items)
{
ServiceTrace.LogCsv("GetStatusItems entry");
ServiceTrace.LogResume("GetStatusItems entry");
string[] receivedItems = null;
ArchestrAResult archestrAResult = PrepareToSend(new GetStatusItemsRequest(), delegate(ConnectedRequest request, T channelClient)
{
ServiceTrace.LogCsv("Calling WCF channel GetStatusItems method");
GetStatusItemsResponse statusItems = channelClient.GetStatusItems((GetStatusItemsRequest)request);
ServiceTrace.LogCsv("Returned from WCF channel GetStatusItems method");
if (statusItems == null)
{
return ArchestrAResult.MakeResult(ArchestrAError.BadNoCommunication, 0).AddErrorMessage("No response from the service");
}
UpdateDownstreamConnectionState(statusItems);
receivedItems = statusItems.Items;
return statusItems.Result;
});
ServiceTrace.LogSuspend("GetStatusItems exit with {0}", archestrAResult.Success ? "success" : "failure");
ServiceTrace.LogCsv("GetStatusItems exit [success]", archestrAResult.Success);
items = receivedItems;
return archestrAResult;
}
public ArchestrAResult GetStatus(string[] itemsToReturn, out NamedValue[] items)
{
ServiceTrace.LogCsv("GetStatus entry");
ServiceTrace.LogResume("GetStatus entry");
NamedValue[] receivedItems = null;
ArchestrAResult archestrAResult = PrepareToSend(new GetStatusRequest
{
ItemsToReturn = itemsToReturn
}, delegate(ConnectedRequest request, T channelClient)
{
ServiceTrace.LogCsv("Calling WCF channel GetStatus method");
GetStatusResponse status = channelClient.GetStatus((GetStatusRequest)request);
ServiceTrace.LogCsv("Returned from WCF channel GetStatus method");
if (status == null)
{
return ArchestrAResult.MakeResult(ArchestrAError.BadNoCommunication, 0).AddErrorMessage("No response from the service");
}
UpdateDownstreamConnectionState(status);
receivedItems = status.Items;
return status.Result;
});
ServiceTrace.LogSuspend("GetStatus exit with {0}", archestrAResult.Success ? "success" : "failure");
ServiceTrace.LogCsv("GetStatus exit [success]", archestrAResult.Success);
items = receivedItems;
return archestrAResult;
}
public void OnDisconnect()
{
ServiceTrace.LogCsv("OnDisconnect entry");
ServiceTrace.LogResume("OnDisconnect entry");
throw new NotImplementedException();
}
protected ArchestrAResult PrepareToSend(ConnectedRequest request, Func<ConnectedRequest, T, ArchestrAResult> processFunc)
{
if (request == null)
{
return ArchestrAResult.MakeResult(ArchestrAError.BadNoCommunication, 0).AddErrorMessage("No request message provided for signature");
}
if (processFunc == null)
{
return ArchestrAResult.MakeResult(ArchestrAError.BadNoCommunication, 0).AddErrorMessage("No processing function provided");
}
ArchestrAResult archestrAResult = SignRequest(request);
if (!archestrAResult.Success)
{
return archestrAResult;
}
T channelClient = ChannelClient;
if (channelClient == null)
{
return ArchestrAResult.MakeResult(ArchestrAError.BadNoCommunication, 0).AddErrorMessage("No connected client for the current connection Id");
}
return processFunc(request, channelClient);
}
protected ArchestrAResult SignRequest(ConnectedRequest request)
{
ArchestrAResult result = ArchestrAResult.MakeResult(ArchestrAError.InvalidConnectionId, 0);
if (successfulConnectionResult != null && successfulConnectionResult.ServiceClient != null && State != CommunicationState.Faulted)
{
SystemAuthenticationClientAuthentication clientAuthenticator = SysAuthenticatorClientCache.GetClientAuthenticator(successfulConnectionResult.ConnectionId);
if (clientAuthenticator != null)
{
clientAuthenticator.Sign(request, forceHmac: false);
return ArchestrAResult.MakeGoodResult();
}
result.AddErrorMessage("Unable to find a signer using the current connection Id");
}
else
{
result.AddErrorMessage("Unable to use the client proxy for the current connection Id");
}
return result;
}
protected void UpdateDownstreamConnectionState(ConnectedResponse response)
{
if (response != null)
{
if (response.DownstreamConnectionState <= 6)
{
DownstreamConnectionState = (ConnectionState)response.DownstreamConnectionState;
return;
}
ServiceTrace.LogWarning(string.Format(CultureInfo.InvariantCulture, "ASB Base V2 client failed to parse downstream connection state value of {0}", new object[1] { response.DownstreamConnectionState }));
DownstreamConnectionState = ConnectionState.Unknown;
}
}
~BaseV2Client()
{
Dispose(disposing: false);
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (disposed)
{
return;
}
if (disposing)
{
if (successfulConnectionResult != null)
{
successfulConnectionResult.Dispose();
}
successfulConnectionResult = null;
}
disposed = true;
Reset();
}
}