in src/library/EndpointManagement/EndpointManagementClient.cs [241:322]
private async Task<ResponseType> InvokeEndpointManagerAsync<RequestType, ResponseType>(RequestType request, CancellationToken cancellationToken, bool ensureEndpointManagerRunning = true)
where RequestType : EndpointManagerRequest
where ResponseType : EndpointManagerResult
{
if (ensureEndpointManagerRunning)
{
// We do not want invoke this method if we are calling from the 'Ping' method, as that will result in an infinite loop
await EnsureEndpointManagerRunningAsync(cancellationToken);
}
var errorMessage = $"Could not connect to {EndpointManager.ProcessName}";
ResponseType deserializedResult = null;
try
{
using (var socket = _socketFactory.Invoke())
using (cancellationToken.Register(() => socket.Close()))
{
_log.Info($"Connecting to {EndpointManager.ProcessName}");
await socket.ConnectAsync(new UnixDomainSocketEndPoint(_socketFilePath));
// Wait for the EndpointManager handshake.
var result = await socket.ReadUntilEndMarkerAsync();
if (!result.Equals(EndpointManager.SocketHandshake))
{
throw new UnexpectedStateException($"Received unexpected message over socket: '{result}'", _log);
}
// Send api invocation request
var serializedRequest = JsonHelpers.SerializeObject(request);
_log.Info($"Sending request: '{serializedRequest}'");
await socket.SendWithEndMarkerAsync(serializedRequest);
// Wait for response
result = await socket.ReadUntilEndMarkerAsync();
_log.Info($"Received response: '{result}'");
deserializedResult = JsonHelpers.DeserializeObject<ResponseType>(result);
}
}
catch (Exception ex) when (ex is SocketException socketException && (socketException.SocketErrorCode == SocketError.ConnectionRefused
|| socketException.SocketErrorCode == SocketError.AddressNotAvailable
|| socketException.SocketErrorCode == SocketError.NetworkDown))
{
// We expect to hit this case if the endpoint manager is not yet running.
_log.Info($"{EndpointManager.ProcessName} is not running: '{ex.Message}' and socket error code: '{socketException.SocketErrorCode}'");
}
catch (Exception ex) when (ex is IUserVisibleExceptionReporter)
{
throw;
}
catch (Exception ex) when (ex.InnerException is DependencyResolutionException autofacEx
&& autofacEx.InnerException is SocketException socketEx
&& socketEx.SocketErrorCode == SocketError.AddressFamilyNotSupported)
{
throw new UserVisibleException(_operationContext, Resources.UnixDomainSocketsNotSupported, Product.Name);
}
catch (UnexpectedStateException)
{
throw;
}
catch (Exception ex)
{
_log.Exception(ex);
throw new InvalidOperationException(errorMessage, ex);
}
if (deserializedResult != null && !deserializedResult.IsSuccess)
{
// Operation failed, but we got back a well-formed response. We check for user-visible error types
if (Enum.TryParse(deserializedResult.ErrorType, out EndpointManager.Errors errorType) && errorType == EndpointManager.Errors.UserVisible)
{
throw new UserVisibleException(_log.OperationContext, deserializedResult.ErrorMessage);
}
else
{
throw new InvalidOperationException(deserializedResult.ErrorMessage);
}
}
return deserializedResult;
}