From bb4a74f8c4005041e996ab86fed8f4c777682080 Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Wed, 11 May 2022 15:02:17 +0200 Subject: [PATCH] Added more API Service Methods --- Borepin/Borepin/Service/BFFH/BFFHService.cs | 27 +--- .../Exceptions/APIIncompatibleException.cs | 22 --- .../Exceptions/AllreadyConnectedException.cs | 22 --- .../AuthenticatingFailedException.cs | 22 --- .../Exceptions/ConnectingFailedException.cs | 22 --- FabAccessAPI/API.cs | 140 ++++++++++++++++-- FabAccessAPI/Auth.cs | 32 ++-- FabAccessAPI/Connection.cs | 4 +- FabAccessAPI/IAPI.cs | 7 +- FabAccessAPI/Mechanism.cs | 21 ++- FabAccessAPI_Test/API_Test.cs | 33 +++-- 11 files changed, 202 insertions(+), 150 deletions(-) delete mode 100644 Borepin/Borepin/Service/BFFH/Exceptions/APIIncompatibleException.cs delete mode 100644 Borepin/Borepin/Service/BFFH/Exceptions/AllreadyConnectedException.cs delete mode 100644 Borepin/Borepin/Service/BFFH/Exceptions/AuthenticatingFailedException.cs delete mode 100644 Borepin/Borepin/Service/BFFH/Exceptions/ConnectingFailedException.cs diff --git a/Borepin/Borepin/Service/BFFH/BFFHService.cs b/Borepin/Borepin/Service/BFFH/BFFHService.cs index d69d1b5..a0fcf48 100644 --- a/Borepin/Borepin/Service/BFFH/BFFHService.cs +++ b/Borepin/Borepin/Service/BFFH/BFFHService.cs @@ -130,11 +130,6 @@ namespace Borepin.Service.BFFH /// public async Task Connect(Connection connection) { - if (IsConnected) - { - throw new AllreadyConnectedException(); - } - string password; try { @@ -162,7 +157,6 @@ namespace Borepin.Service.BFFH if (! await _AuthenticatePlainAsync(connection.Username, password).ConfigureAwait(false)) { await Disconnect().ConfigureAwait(false); - throw new AuthenticatingFailedException(); } _CurrentConnection = new Connection_Plain(connection) @@ -182,10 +176,6 @@ namespace Borepin.Service.BFFH /// public async Task Connect(Connection connection, string password) { - if (IsConnected) - { - throw new AllreadyConnectedException(); - } try { @@ -201,7 +191,7 @@ namespace Borepin.Service.BFFH if (!await _AuthenticatePlainAsync(connection.Username, password).ConfigureAwait(false)) { await Disconnect().ConfigureAwait(false); - throw new AuthenticatingFailedException(); + } _CurrentConnection = new Connection_Plain(connection) @@ -239,15 +229,6 @@ namespace Borepin.Service.BFFH _APIConnection = new FabAccessAPI.Connection(rpcClient); } - catch (RpcException exception) when (string.Equals(exception.Message, "TcpRpcClient is unable to connect", StringComparison.Ordinal)) - { - throw new ReconnectingFailedException("Connecting failed", new ConnectingFailedException("Connecting failed", exception)); - } - - if (! await _AuthenticatePlainAsync(_CurrentConnection.Username, _CurrentConnection.Password).ConfigureAwait(false)) - { - throw new ReconnectingFailedException("Authentication failed", new AuthenticatingFailedException()); - } } /// @@ -316,11 +297,7 @@ namespace Borepin.Service.BFFH await _APIConnection.Auth("PLAIN", new Dictionary(StringComparer.Ordinal) { { "Username", username }, { "Password", password } }).ConfigureAwait(false); return await Task.FromResult(true).ConfigureAwait(false); } - catch(InvalidCredentialsException) - { - return await Task.FromResult(true).ConfigureAwait(false); - } - catch (AuthenticatingFailedException) + catch(UnsupportedMechanismException) { return await Task.FromResult(true).ConfigureAwait(false); } diff --git a/Borepin/Borepin/Service/BFFH/Exceptions/APIIncompatibleException.cs b/Borepin/Borepin/Service/BFFH/Exceptions/APIIncompatibleException.cs deleted file mode 100644 index e676e0e..0000000 --- a/Borepin/Borepin/Service/BFFH/Exceptions/APIIncompatibleException.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace Borepin.Service.BFFH.Exceptions -{ - public class APIIncompatibleException : Exception - { - public APIIncompatibleException() - { - - } - - public APIIncompatibleException(string message) : base(message) - { - - } - - public APIIncompatibleException(string message, Exception inner) : base(message, inner) - { - - } - } -} diff --git a/Borepin/Borepin/Service/BFFH/Exceptions/AllreadyConnectedException.cs b/Borepin/Borepin/Service/BFFH/Exceptions/AllreadyConnectedException.cs deleted file mode 100644 index aa96c7b..0000000 --- a/Borepin/Borepin/Service/BFFH/Exceptions/AllreadyConnectedException.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace Borepin.Service.BFFH.Exceptions -{ - public class AllreadyConnectedException : Exception - { - public AllreadyConnectedException() - { - - } - - public AllreadyConnectedException(string message) : base(message) - { - - } - - public AllreadyConnectedException(string message, Exception inner) : base(message, inner) - { - - } - } -} diff --git a/Borepin/Borepin/Service/BFFH/Exceptions/AuthenticatingFailedException.cs b/Borepin/Borepin/Service/BFFH/Exceptions/AuthenticatingFailedException.cs deleted file mode 100644 index e753cdc..0000000 --- a/Borepin/Borepin/Service/BFFH/Exceptions/AuthenticatingFailedException.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace Borepin.Service.BFFH.Exceptions -{ - public class AuthenticatingFailedException : Exception - { - public AuthenticatingFailedException() - { - - } - - public AuthenticatingFailedException(string message) : base(message) - { - - } - - public AuthenticatingFailedException(string message, Exception inner) : base(message, inner) - { - - } - } -} diff --git a/Borepin/Borepin/Service/BFFH/Exceptions/ConnectingFailedException.cs b/Borepin/Borepin/Service/BFFH/Exceptions/ConnectingFailedException.cs deleted file mode 100644 index 082f442..0000000 --- a/Borepin/Borepin/Service/BFFH/Exceptions/ConnectingFailedException.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace Borepin.Service.BFFH.Exceptions -{ - public class ConnectingFailedException : Exception - { - public ConnectingFailedException() - { - - } - - public ConnectingFailedException(string message) : base(message) - { - - } - - public ConnectingFailedException(string message, Exception inner) : base(message, inner) - { - - } - } -} diff --git a/FabAccessAPI/API.cs b/FabAccessAPI/API.cs index c1bc7a0..91042c5 100644 --- a/FabAccessAPI/API.cs +++ b/FabAccessAPI/API.cs @@ -1,11 +1,19 @@ -using FabAccessAPI.Schema; +using Capnp.Rpc; +using FabAccessAPI.Exceptions; +using FabAccessAPI.Schema; using System; +using System.Collections.Generic; +using System.Net.Security; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; +using System.Threading.Tasks; namespace FabAccessAPI { public class API : IAPI { #region Private Members + private Connection _APIConnection; #endregion #region Constructors @@ -28,7 +36,7 @@ namespace FabAccessAPI { get { - throw new NotImplementedException(); + return _APIConnection != null && _APIConnection.RpcClient.State == ConnectionState.Active; } } @@ -42,24 +50,138 @@ namespace FabAccessAPI #endregion #region Methods - public void Connect(ConnectionData connectionData) + /// + /// Connect to server with ConnectionData + /// + /// + /// + public async Task Connect(ConnectionData connectionData) + { + if (IsConnected) + { + await Disconnect(); + } + + TcpRpcClient rpcClient = await _ConnectAsync(connectionData).ConfigureAwait(false); + + _APIConnection = new Connection(rpcClient); + + try + { + await _Authenticate(connectionData).ConfigureAwait(false); + } + catch(System.Exception) + { + await Disconnect().ConfigureAwait(false); + throw; + } + } + + public Task Disconnect() + { + if (IsConnected) + { + _APIConnection.RpcClient?.Dispose(); + } + + _APIConnection = null; + ConnectionData = null; + ConnectionInfo = null; + + return Task.CompletedTask; + } + + public Task Reconnect() { throw new NotImplementedException(); } - public void Disconnect() + public async Task TestConnection(ConnectionData connectionData) { - throw new NotImplementedException(); + try + { + TcpRpcClient rpcClient = await _ConnectAsync(connectionData).ConfigureAwait(false); + Connection testConnection = new Connection(rpcClient); + + rpcClient.Dispose(); + + ConnectionInfo connectionInfo = new ConnectionInfo() + { + APIVersion = testConnection. + } + + return true; + } + catch + { + return null; + } + } + #endregion + + #region Private Methods + private static bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) + { + // TODO Cert Check + return true; } - public void Reconnect() + /// + /// Connect to server async with ConnectionData + /// + /// TLS Error + /// Based on RPC Exception + /// + private async Task _ConnectAsync(ConnectionData connectionData) { - throw new NotImplementedException(); + TcpRpcClient rpcClient = new TcpRpcClient(); + rpcClient.InjectMidlayer((tcpstream) => + { + var sslStream = new SslStream(tcpstream, false, new RemoteCertificateValidationCallback(RemoteCertificateValidationCallback)); + try + { + sslStream.AuthenticateAsClient("bffhd"); + return sslStream; + } + catch (AuthenticationException) + { + sslStream.Close(); + throw; + } + }); + + try + { + rpcClient.Connect(connectionData.Host.Host, connectionData.Host.Port); + await rpcClient.WhenConnected.ConfigureAwait(false); + + return rpcClient; + } + catch (RpcException exception) when (string.Equals(exception.Message, "TcpRpcClient is unable to connect", StringComparison.Ordinal)) + { + throw new ConnectingFailedException("Connecting failed", exception); + } } - public ConnectionInfo TestConnection(ConnectionData connectionData) + /// + /// Authenticate connection with ConnectionData + /// + /// + /// + /// + private async Task _Authenticate(ConnectionData connectionData) { - throw new NotImplementedException(); + Dictionary joinedProperties = new Dictionary(); + foreach(KeyValuePair keyValuePair in connectionData.Properties) + { + joinedProperties.Add(keyValuePair.Key, keyValuePair.Value); + } + foreach (KeyValuePair keyValuePair in connectionData.SecretProperties) + { + joinedProperties.Add(keyValuePair.Key, keyValuePair.Value); + } + + await _APIConnection.Auth(MechanismString.ToString(connectionData.Mechanism), joinedProperties).ConfigureAwait(false); } #endregion } diff --git a/FabAccessAPI/Auth.cs b/FabAccessAPI/Auth.cs index 457a091..231952a 100644 --- a/FabAccessAPI/Auth.cs +++ b/FabAccessAPI/Auth.cs @@ -24,6 +24,12 @@ namespace FabAccessAPI #endregion #region Methods + /// + /// Authenticate Connection to get Session + /// + /// + /// + /// public async Task Authenticate(string mech, Dictionary properties) { SaslMechanism? saslMechanism = SaslFactory.Create(mech); @@ -44,17 +50,7 @@ namespace FabAccessAPI { if(response.Failed != null) { - switch (response.Failed.Code) - { - case Response.Error.badMechanism: - throw new BadMechanismException(); - case Response.Error.invalidCredentials: - throw new InvalidCredentialsException(); - case Response.Error.aborted: - case Response.Error.failed: - default: - throw new AuthenticationFailedException(response.Failed.AdditionalData.ToArray()); - } + break; } if(response.Challenge != null) { @@ -71,6 +67,20 @@ namespace FabAccessAPI { return response.Successful.Session; } + else if (response.Failed != null) + { + switch (response.Failed.Code) + { + case Response.Error.badMechanism: + throw new BadMechanismException(); + case Response.Error.invalidCredentials: + throw new InvalidCredentialsException(); + case Response.Error.aborted: + case Response.Error.failed: + default: + throw new AuthenticationFailedException(response.Failed.AdditionalData.ToArray()); + } + } else { throw new AuthenticationFailedException(); diff --git a/FabAccessAPI/Connection.cs b/FabAccessAPI/Connection.cs index 00d9246..34ade82 100644 --- a/FabAccessAPI/Connection.cs +++ b/FabAccessAPI/Connection.cs @@ -41,7 +41,9 @@ namespace FabAccessAPI /// /// The desired authentication mechanism /// Key-Value data specific to the mechanism - /// + /// + /// + /// public async Task Auth(string mech, Dictionary kvs, CancellationToken cancellationToken_ = default) { IReadOnlyList? mechs = await _BootstrapCap.Mechanisms(); diff --git a/FabAccessAPI/IAPI.cs b/FabAccessAPI/IAPI.cs index 884f8bc..0d6d203 100644 --- a/FabAccessAPI/IAPI.cs +++ b/FabAccessAPI/IAPI.cs @@ -1,5 +1,6 @@ using FabAccessAPI.Schema; using System; +using System.Threading.Tasks; namespace FabAccessAPI { @@ -35,17 +36,17 @@ namespace FabAccessAPI /// Connect to BFFH Server /// /// - void Connect(ConnectionData connectionData); + Task Connect(ConnectionData connectionData); /// /// Disconnect from BFFH Server /// - void Disconnect(); + Task Disconnect(); /// /// Reconnect after connection loss with the last ConnectionData /// - void Reconnect(); + Task Reconnect(); /// /// Connect to Server and get ConnectionInfo. diff --git a/FabAccessAPI/Mechanism.cs b/FabAccessAPI/Mechanism.cs index 0d196b3..96a4e53 100644 --- a/FabAccessAPI/Mechanism.cs +++ b/FabAccessAPI/Mechanism.cs @@ -1,7 +1,24 @@ -namespace FabAccessAPI +using System; + +namespace FabAccessAPI { public enum Mechanism { - PLAIN + PLAIN, } + + public static class MechanismString + { + public static string ToString(Mechanism mechanism) + { + switch(mechanism) + { + case Mechanism.PLAIN: + return "PLAIN"; + default: + throw new ArgumentException("Mechanism not known."); + } + } + } + } diff --git a/FabAccessAPI_Test/API_Test.cs b/FabAccessAPI_Test/API_Test.cs index dd3f52a..e631ed8 100644 --- a/FabAccessAPI_Test/API_Test.cs +++ b/FabAccessAPI_Test/API_Test.cs @@ -4,13 +4,14 @@ using FabAccessAPI.Exceptions; using NUnit.Framework; using System; using System.Collections.Generic; +using System.Threading.Tasks; namespace FabAccessAPI_Test { public class API_Test { [TestCase("Admin1")] - public void ConnectDisconnect(string username) + public async Task ConnectDisconnect(string username) { API api = new API(); @@ -29,12 +30,12 @@ namespace FabAccessAPI_Test } }; - api.Connect(connectionData); - api.Disconnect(); + await api.Connect(connectionData); + await api.Disconnect(); } [Test] - public void Connect_HostUnreachable() + public async Task Connect_HostUnreachable() { API api = new API(); @@ -53,14 +54,19 @@ namespace FabAccessAPI_Test } }; - Assert.Throws(() => + try { - api.Connect(connectionData); - }); + await api.Connect(connectionData); + } + catch (ConnectingFailedException) + { + Assert.Pass(); + } + Assert.Fail(); } [Test] - public void Connect_InvalidCredentials() + public async Task Connect_InvalidCredentials() { API api = new API(); @@ -79,10 +85,15 @@ namespace FabAccessAPI_Test } }; - Assert.Throws(() => + try { - api.Connect(connectionData); - }); + await api.Connect(connectionData); + } + catch(InvalidCredentialsException) + { + Assert.Pass(); + } + Assert.Fail(); } } }