Skip to content

Continue adding TLS support #29

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ dotnet_style_qualification_for_method = false:suggestion
dotnet_style_qualification_for_event = false:suggestion

# Types: use keywords instead of BCL types, and permit var only when the type is clear
# TODO consider making csharp_style_var_for_built_in_types and csharp_style_var_elsewhere ERRORS
csharp_style_var_for_built_in_types = false:suggestion
csharp_style_var_when_type_is_apparent = false:none
csharp_style_var_elsewhere = false:suggestion
Expand Down
9 changes: 5 additions & 4 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@
<ItemGroup>
<!-- RabbitMQ.Amqp.Client -->
<PackageVersion Include="AMQPNetLite.Core" Version="2.4.11" />
<PackageVersion Include="EasyNetQ.Management.Client" Version="3.0.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="3.3.4" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="1.1.1" />
<PackageVersion Include="MinVer" Version="4.3.0" />
<PackageVersion Include="MinVer" Version="5.0.0" />
<!-- Tests -->
<PackageVersion Include="AltCover" Version="8.8.74" />
<PackageVersion Include="xunit" Version="2.8.1" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.1" />
<PackageVersion Include="AltCover" Version="8.8.165" />
<PackageVersion Include="xunit" Version="2.9.0" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
<PackageVersion Include="Xunit.SkippableFact" Version="1.4.13" />
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
<!-- docs/**/*.csproj -->
Expand Down
5 changes: 3 additions & 2 deletions RabbitMQ.AMQP.Client/IConnectionSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ public interface IConnectionSettings : IEquatable<IConnectionSettings>
string Host { get; }
int Port { get; }
string VirtualHost { get; }
string User { get; }
string Password { get; }
string? User { get; }
string? Password { get; }
string Scheme { get; }
string ConnectionName { get; }
string Path { get; }
bool UseSsl { get; }
SaslMechanism SaslMechanism { get; }
ITlsSettings? TlsSettings { get; }
}

Expand Down
4 changes: 2 additions & 2 deletions RabbitMQ.AMQP.Client/ILifeCycle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public interface ILifeCycle
{
Task CloseAsync();

public State State { get; }
State State { get; }

public event LifeCycleCallBack ChangeState;
event LifeCycleCallBack ChangeState;
}
2 changes: 1 addition & 1 deletion RabbitMQ.AMQP.Client/IRecoveryConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,6 @@ public interface IBackOffDelayPolicy
/// or when the user wants to disable the backoff delay policy.
/// </summary>
bool IsActive();

int CurrentAttempt { get; }
}
6 changes: 6 additions & 0 deletions RabbitMQ.AMQP.Client/Impl/AmqpConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.ObjectModel;
using Amqp;
using Amqp.Framing;
using Amqp.Sasl;
using Amqp.Types;

namespace RabbitMQ.AMQP.Client.Impl;
Expand Down Expand Up @@ -232,6 +233,11 @@ void onOpened(Amqp.IConnection connection, Open open1)
}
}

if (_connectionSettings.SaslMechanism == SaslMechanism.External)
{
cf.SASL.Profile = SaslProfile.External;
}

try
{
_nativeConnection = await cf.CreateAsync(_connectionSettings.Address, open: open, onOpened: onOpened)
Expand Down
4 changes: 2 additions & 2 deletions RabbitMQ.AMQP.Client/Impl/AmqpManagement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -388,8 +388,8 @@ public override string ToString()

return info;
}


internal void ChangeStatus(State newState, Error? error)
{
OnNewStatus(newState, error);
Expand Down
44 changes: 30 additions & 14 deletions RabbitMQ.AMQP.Client/Impl/ConnectionSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ public class ConnectionSettingBuilder
// TODO: maybe add the event "LifeCycle" to the builder
private string _host = "localhost";
private int _port = -1; // Note: -1 means use the defalt for the scheme
private string _user = "guest";
private string _password = "guest";
private string? _user = "guest";
private string? _password = "guest";
private string _scheme = "AMQP";
private string _connection = "AMQP.NET";
private string _connectionName = "AMQP.NET";
private string _virtualHost = "/";
private SaslMechanism _saslMechanism = Client.SaslMechanism.Plain;
private IRecoveryConfiguration _recoveryConfiguration = Impl.RecoveryConfiguration.Create();


private ConnectionSettingBuilder()
{
}
Expand All @@ -27,7 +27,6 @@ public static ConnectionSettingBuilder Create()
return new ConnectionSettingBuilder();
}


public ConnectionSettingBuilder Host(string host)
{
_host = host;
Expand All @@ -52,16 +51,15 @@ public ConnectionSettingBuilder Password(string password)
return this;
}


public ConnectionSettingBuilder Scheme(string scheme)
{
_scheme = scheme;
return this;
}

public ConnectionSettingBuilder ConnectionName(string connection)
public ConnectionSettingBuilder ConnectionName(string connectionName)
{
_connection = connection;
_connectionName = connectionName;
return this;
}

Expand All @@ -71,6 +69,18 @@ public ConnectionSettingBuilder VirtualHost(string virtualHost)
return this;
}

public ConnectionSettingBuilder SaslMechanism(SaslMechanism saslMechanism)
{
_saslMechanism = saslMechanism;
if (_saslMechanism == Client.SaslMechanism.External)
{
_user = null;
_password = null;
}

return this;
}

public ConnectionSettingBuilder RecoveryConfiguration(IRecoveryConfiguration recoveryConfiguration)
{
_recoveryConfiguration = recoveryConfiguration;
Expand All @@ -81,7 +91,10 @@ public ConnectionSettings Build()
{
var c = new ConnectionSettings(_host, _port, _user,
_password, _virtualHost,
_scheme, _connection) { RecoveryConfiguration = (RecoveryConfiguration)_recoveryConfiguration };
_scheme, _connectionName, _saslMechanism)
{
RecoveryConfiguration = (RecoveryConfiguration)_recoveryConfiguration
};

return c;
}
Expand All @@ -96,6 +109,7 @@ public class ConnectionSettings : IConnectionSettings
private readonly string _connectionName = "";
private readonly string _virtualHost = "/";
private readonly ITlsSettings? _tlsSettings;
private readonly SaslMechanism _saslMechanism = SaslMechanism.Plain;

public ConnectionSettings(string address, ITlsSettings? tlsSettings = null)
{
Expand All @@ -109,15 +123,16 @@ public ConnectionSettings(string address, ITlsSettings? tlsSettings = null)
}

public ConnectionSettings(string host, int port,
string user, string password,
string? user, string? password,
string virtualHost, string scheme, string connectionName,
ITlsSettings? tlsSettings = null)
SaslMechanism saslMechanism, ITlsSettings? tlsSettings = null)
{
_address = new Address(host: host, port: port,
user: user, password: password,
path: "/", scheme: scheme);
_connectionName = connectionName;
_virtualHost = virtualHost;
_saslMechanism = saslMechanism;
_tlsSettings = tlsSettings;

if (_address.UseSsl && _tlsSettings == null)
Expand All @@ -129,12 +144,13 @@ public ConnectionSettings(string host, int port,
public string Host => _address.Host;
public int Port => _address.Port;
public string VirtualHost => _virtualHost;
public string User => _address.User;
public string Password => _address.Password;
public string? User => _address.User;
public string? Password => _address.Password;
public string Scheme => _address.Scheme;
public string ConnectionName => _connectionName;
public string Path => _address.Path;
public bool UseSsl => _address.UseSsl;
public SaslMechanism SaslMechanism => _saslMechanism;

public ITlsSettings? TlsSettings => _tlsSettings;

Expand Down Expand Up @@ -279,7 +295,7 @@ public static BackOffDelayPolicy Create()
{
return new BackOffDelayPolicy();
}

public static BackOffDelayPolicy Create(int maxAttempt)
{
return new BackOffDelayPolicy(maxAttempt);
Expand Down
1 change: 0 additions & 1 deletion RabbitMQ.AMQP.Client/RabbitMQ.AMQP.Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
<None Include="$(MSBuildThisFileDirectory)..\LICENSE" Pack="true" Visible="false" PackagePath="" />
<None Include="$(MSBuildThisFileDirectory)..\LICENSE-APACHE2" Pack="true" Visible="false" PackagePath="" />
<None Include="$(MSBuildThisFileDirectory)..\LICENSE-MPL-RabbitMQ" Pack="true" Visible="false" PackagePath="" />
<Folder Include="Metrics/" />
<InternalsVisibleTo Include="Tests" />
<InternalsVisibleTo Include="DynamicProxyGenAssembly2" />
</ItemGroup>
Expand Down
57 changes: 57 additions & 0 deletions RabbitMQ.AMQP.Client/SaslMechanism.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
namespace RabbitMQ.AMQP.Client
{
public class SaslMechanism : IEquatable<SaslMechanism>
{
public static readonly SaslMechanism Plain = new("PLAIN");
public static readonly SaslMechanism External = new("EXTERNAL");

private readonly string _saslMechanism;

private SaslMechanism(string saslMechanism)
{
_saslMechanism = saslMechanism;
}

public string Mechanism => _saslMechanism;

public override bool Equals(object? obj)
{
if (obj is null)
{
return false;
}

if (obj is not SaslMechanism)
{
return false;
}

if (Object.ReferenceEquals(this, obj))
{
return true;
}

return GetHashCode() == obj.GetHashCode();
}

public bool Equals(SaslMechanism? other)
{
if (other is null)
{
return false;
}

if (Object.ReferenceEquals(this, other))
{
return true;
}

return GetHashCode() == other.GetHashCode();
}

public override int GetHashCode()
{
return _saslMechanism.GetHashCode();
}
}
}
13 changes: 8 additions & 5 deletions Tests/ConnectionRecoveryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@ public async Task NormalCloseTheStatusShouldBeCorrectAndErrorNull(bool activeRec
ConnectionSettingBuilder.Create().ConnectionName(connectionName).RecoveryConfiguration(
RecoveryConfiguration.Create().Activated(activeRecovery).Topology(false)).Build());

var completion = new TaskCompletionSource();
TaskCompletionSource completion = new TaskCompletionSource();
var listFromStatus = new List<State>();
var listToStatus = new List<State>();
var listError = new List<Error>();
var listError = new List<Error?>();
connection.ChangeState += (sender, from, to, error) =>
{
listFromStatus.Add(from);
Expand Down Expand Up @@ -103,14 +103,14 @@ public async Task NormalCloseTheStatusShouldBeCorrectAndErrorNull(bool activeRec
public async Task UnexpectedCloseTheStatusShouldBeCorrectAndErrorNotNull()
{
const string connectionName = "unexpected-close-connection-name";
var connection = await AmqpConnection.CreateAsync(
IConnection connection = await AmqpConnection.CreateAsync(
ConnectionSettingBuilder.Create().ConnectionName(connectionName).RecoveryConfiguration(
RecoveryConfiguration.Create().Activated(true).Topology(false)
.BackOffDelayPolicy(new FakeFastBackOffDelay())).Build());
var resetEvent = new ManualResetEvent(false);
var listFromStatus = new List<State>();
var listToStatus = new List<State>();
var listError = new List<Error>();
var listError = new List<Error?>();
connection.ChangeState += (sender, previousState, currentState, error) =>
{
listFromStatus.Add(previousState);
Expand Down Expand Up @@ -170,7 +170,10 @@ public async Task OverrideTheBackOffWithBackOffDisabled()
{
listFromStatus.Add(previousState);
listToStatus.Add(currentState);
listError.Add(error);
if (error is not null)
{
listError.Add(error);
}
if (listError.Count >= 4)
{
resetEvent.Set();
Expand Down
Loading