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();
}
}
}