Skip to content

Commit

Permalink
v15.2.0 - Change ConfigurationOptions into ConnectionString with IL2 …
Browse files Browse the repository at this point in the history
…Network Parsing
  • Loading branch information
monoman committed Oct 22, 2024
1 parent f0b53d4 commit 11dc90b
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,66 +34,97 @@

namespace InterlockLedger.Rest.Client;

public class ConfigurationOptions(string host, ushort port, string? clientCertificateFilePath = null, string? clientCertificatePassword = null) : IParsable<ConfigurationOptions>
[JsonConverter(typeof(Converter))]
public class ConnectionString : IParsable<ConnectionString>
{
public string Host { get; set; } = host;
public ushort Port { get; set; } = port;
public string? ClientCertificateFilePath { get; set; } = clientCertificateFilePath;
public string? ClientCertificatePassword { get; set; } = clientCertificatePassword;
public sealed class Converter : JsonConverter<ConnectionString>
{
public override ConnectionString? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => Parse(reader.GetString().Required());
public override void Write(Utf8JsonWriter writer, ConnectionString value, JsonSerializerOptions options) => writer.WriteStringValue(value.ToString());
}

public KnownNetworks Network { get; set; }
public string Host { get; set; }
public ushort Port { get; set; }
public string? ClientCertificateFilePath { get; set; }
public string? ClientCertificatePassword { get; set; }

public ConnectionString(string host, ushort? port = null, string? clientCertificateFilePath = null, string? clientCertificatePassword = null, string? network = null) {
Network = new(network);
Host = host.Required().ToLowerInvariant();
Port = port.GetValueOrDefault(Network.DefaultPort);
ClientCertificateFilePath = clientCertificateFilePath;
ClientCertificatePassword = clientCertificatePassword;
}

public override string ToString() {
var sb =
new StringBuilder("ilkl-")
.Append(Network)
.Append("://")
.Append(Host)
.Append(':')
.Append(Port);
if (!ClientCertificateFilePath.IsBlank()) {
sb.Append(',').Append(ClientCertificateFilePath);
if (!ClientCertificatePassword.IsBlank()) {
sb.Append(',').Append(ClientCertificatePassword);
}
}
return sb.ToString();
}

/// <summary>
/// Parses a connection string to InterlockLedger REST Client ConfigurationOptions
/// Parses a connection string to InterlockLedger REST Client ConnectionString
/// </summary>
/// <param name="connectionString">Connection string in the form "ilkl-minerva://minerva-data.il2.io[:32067],/absolute/path/to/clientcertificate.pfx,clientCertificatePassword"</param>
/// <returns>Parsed ConfigurationOptions</returns>
/// <returns>Parsed ConnectionString</returns>
/// <exception cref="ArgumentException"></exception>
public static ConfigurationOptions Parse(string connectionString) => Parse(connectionString, null);
public static ConnectionString Parse(string connectionString) => Parse(connectionString, null);

/// <summary>
/// Parses a connection string to InterlockLedger REST Client ConfigurationOptions
/// Parses a connection string to InterlockLedger REST Client ConnectionString
/// </summary>
/// <param name="connectionString">Connection string in the form "ilkl-minerva://minerva-data.il2.io[:32067],/absolute/path/to/clientcertificate.pfx,clientCertificatePassword"</param>
/// <param name="provider">[Ignored] Format provider</param>
/// <returns>Parsed ConfigurationOptions</returns>
/// <returns>Parsed ConnectionString</returns>
/// <exception cref="ArgumentException"></exception>
public static ConfigurationOptions Parse(string connectionString, IFormatProvider? provider) =>
public static ConnectionString Parse(string connectionString, IFormatProvider? provider) =>
TryParse(connectionString, provider, out var result)
? result
: throw new ArgumentException("Malformed connection string", nameof(connectionString));

/// <summary>
/// Try to parse a connection string to InterlockLedger REST Client ConfigurationOptions
/// Try to parse a connection string to InterlockLedger REST Client ConnectionString
/// </summary>
/// <param name="connectionString">Connection string in the form "ilkl-minerva://minerva-data.il2.io[:32067],/absolute/path/to/clientcertificate.pfx,clientCertificatePassword"</param>
/// <param name="provider"></param>
/// <param name="result"></param>
/// <returns>True if correctly parsed</returns>
public static bool TryParse([NotNullWhen(true)] string? connectionString, IFormatProvider? provider, [MaybeNullWhen(false)] out ConfigurationOptions result) {
public static bool TryParse([NotNullWhen(true)] string? connectionString, IFormatProvider? provider, [MaybeNullWhen(false)] out ConnectionString result) {
if (!string.IsNullOrWhiteSpace(connectionString)) {
var match = ConfigurationOptionsParsingHelper.ConnectionStringRegex().Match(connectionString);
var groups = match.Groups;
if (match.Success && groups.Count >= 8 && ParsePort(groups[4], groups[1].Value, out ushort port)) {
result = new ConfigurationOptions(groups[2].Value, port, GetValueOrDefault(groups[6]), GetValueOrDefault(groups[7]));
result = new ConnectionString(groups[2].Value, port, GetValueOrDefault(groups[6]), GetValueOrDefault(groups[7]), groups[1].Value);
return true;
}
}
result = null;
return false;
}

private static string? GetValueOrDefault(Group group) => group.Success ? group.Value : null;

private static bool ParsePort(Group group, string network, out ushort port) {
if (group.Success)
return ushort.TryParse(group.Value, null, out port);
port = ConfigurationOptionsParsingHelper.GetDefaultPortFor(network);
port = new KnownNetworks(network).DefaultPort;
return true;
}

}

internal static partial class ConfigurationOptionsParsingHelper
{
[GeneratedRegex(@"^ilkl-(\w+)://([^:,]+)(:(\d+))?(,([^,]+),([^,]+))?$")]
public static partial Regex ConnectionStringRegex();
public static ushort GetDefaultPortFor(string network) => 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFrameworks>net8.0</TargetFrameworks>
<LangVersion>preview</LangVersion>
<Version>15.1.1</Version>
<Version>15.2.0</Version>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Copyright>Copyright (c) 2018-2024 InterlockLedger Network</Copyright>
<Description>
Expand All @@ -14,7 +14,7 @@
<RepositoryType>git</RepositoryType>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageTags>REST Client InterlockLedger</PackageTags>
<PackageReleaseNotes>Add MUTABLE ConfigurationOptions with parsing from connectionString</PackageReleaseNotes>
<PackageReleaseNotes>Change ConfigurationOptions into ConnectionString with IL2 Network Parsing</PackageReleaseNotes>
<PackageIcon>il2.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageLicenseExpression>BSD-3-Clause</PackageLicenseExpression>
Expand Down
55 changes: 55 additions & 0 deletions InterlockLedger.Rest.Client/KnownNetworks.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// ******************************************************************************************************************************
//
// Copyright (c) 2018-2022 InterlockLedger Network
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met
//
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES, LOSS OF USE, DATA, OR PROFITS, OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ******************************************************************************************************************************

namespace InterlockLedger.Rest.Client;

[JsonConverter(typeof(Converter))]
public sealed class KnownNetworks
{
public sealed class Converter : JsonConverter<KnownNetworks>
{
public override KnownNetworks? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => new(reader.GetString());
public override void Write(Utf8JsonWriter writer, KnownNetworks value, JsonSerializerOptions options) => writer.WriteStringValue(value.TextualRepresentation);
}
public KnownNetworks() : this(NetworkPredefinedPorts.MainNet) { }
public KnownNetworks(string? value) : this(Enum.TryParse(value, ignoreCase: true, out NetworkPredefinedPorts network) ? network : NetworkPredefinedPorts.MainNet) { }

private KnownNetworks(NetworkPredefinedPorts network) {
Network = network;
TextualRepresentation = Enum.GetName(Network).Required().ToLowerInvariant();
DefaultPort = (ushort)Network;
}
public ushort DefaultPort { get; }
public NetworkPredefinedPorts Network { get; }
public string TextualRepresentation { get; }
public override string ToString() => TextualRepresentation;
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@ namespace InterlockLedger.Rest.Client;

public enum NetworkPredefinedPorts : ushort
{
TestNet_Apollo = 32020,
TestNet_Janus = 32022,
TestNet_Minerva = 32024,
TestNet_Neptune = 32026,
TestNet_Saturn = 32028,
TestNet_Jupiter = 32030,
Apollo = 32020,
Janus = 32022,
Minerva = 32024,
Neptune = 32026,
Saturn = 32028,
Jupiter = 32030,
MainNet = 32032,
MetaNet = 32036,
Paperless = 29720,
// CustomNets
TilliT = 32063,
GoldReefCity = 2190,
}
}
2 changes: 1 addition & 1 deletion InterlockLedger.Rest.Client/V14_2_2/RestNodeV14_2_2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ namespace InterlockLedger.Rest.Client.V14_2_2;

public class RestNodeV14_2_2 : RestAbstractNode<RestChainV14_2_2>, INodeWithDocumentRegistry
{
public RestNodeV14_2_2(ConfigurationOptions options) : this(options.ClientCertificateFilePath.Required(), options.ClientCertificatePassword.Required(), options.Port, options.Host.Required()) { }
public RestNodeV14_2_2(ConnectionString options) : this(options.ClientCertificateFilePath.Required(), options.ClientCertificatePassword.Required(), options.Port, options.Host.Required()) { }
public RestNodeV14_2_2(X509Certificate2 x509Certificate, NetworkPredefinedPorts networkId, string address)
: base(x509Certificate, networkId, address) { }

Expand Down

0 comments on commit 11dc90b

Please sign in to comment.