Use TryGet* approach in SystemNetExtensions.
MODIFY
WalletWasabi.Tests/UnitTests/Userfacing/ParserTests.cs
WalletWasabi.Tests/UnitTests/Userfacing/ParserTests.cs
@@ -129,14 +129,13 @@ namespace WalletWasabi.Tests.UnitTests
private static void AssertEndPointParserOutputs(bool isSuccess, EndPoint endPoint, string expectedHost, int expectedPort)
{
Assert.True(isSuccess);
- var actualPort = endPoint.GetPortOrDefault();
- Assert.Equal(expectedPort, actualPort);
- var actualHost = endPoint.GetHostOrDefault();
- if (expectedHost == "localhost")
- {
- expectedHost = "127.0.0.1";
- }
+ Assert.True(endPoint.TryGetHostAndPort(out string? actualHost, out int? actualPort));
+
+ expectedHost = (expectedHost == "localhost") ? "127.0.0.1" : expectedHost;
+
Assert.Equal(expectedHost, actualHost);
+ Assert.Equal(expectedPort, actualPort);
+
Assert.Equal($"{actualHost}:{actualPort}", endPoint.ToString(expectedPort));
}

MODIFY
WalletWasabi/BitcoinCore/CoreNode.cs
WalletWasabi/BitcoinCore/CoreNode.cs
@@ -64,7 +64,7 @@ namespace WalletWasabi.BitcoinCore
string rpcUser = configTranslator.TryGetRpcUser();
string rpcPassword = configTranslator.TryGetRpcPassword();
string rpcCookieFilePath = configTranslator.TryGetRpcCookieFile();
- string rpcHost = configTranslator.TryGetRpcBind();
+ string? rpcHost = configTranslator.TryGetRpcBind();
int? rpcPort = configTranslator.TryGetRpcPort();
WhiteBind whiteBind = configTranslator.TryGetWhiteBind();
@@ -82,8 +82,17 @@ namespace WalletWasabi.BitcoinCore
}
coreNode.P2pEndPoint = whiteBind?.EndPoint ?? coreNodeParams.P2pEndPointStrategy.EndPoint;
- rpcHost ??= coreNodeParams.RpcEndPointStrategy.EndPoint.GetHostOrDefault();
- rpcPort ??= coreNodeParams.RpcEndPointStrategy.EndPoint.GetPortOrDefault();
+
+ if (rpcHost is null)
+ {
+ coreNodeParams.RpcEndPointStrategy.EndPoint.TryGetHost(out rpcHost);
+ }
+
+ if (rpcPort is null)
+ {
+ coreNodeParams.RpcEndPointStrategy.EndPoint.TryGetPort(out rpcPort);
+ }
+
EndPointParser.TryParse($"{rpcHost}:{rpcPort}", coreNode.Network.RPCPort, out EndPoint rpce);
coreNode.RpcEndPoint = rpce;
@@ -109,14 +118,20 @@ namespace WalletWasabi.BitcoinCore
var configPrefix = NetworkTranslator.GetConfigPrefix(coreNode.Network);
var whiteBindPermissionsPart = !string.IsNullOrWhiteSpace(whiteBind?.Permissions) ? $"{whiteBind?.Permissions}@" : "";
+
+ if (!coreNode.RpcEndPoint.TryGetHost(out string? rpcBindParameter) || !coreNode.RpcEndPoint.TryGetPort(out int? rpcPortParameter))
+ {
+ throw new ArgumentException("Endpoint type is not supported.", nameof(coreNode.RpcEndPoint));
+ }
+
var desiredConfigLines = new List<string>()
{
$"{configPrefix}.server = 1",
$"{configPrefix}.listen = 1",
$"{configPrefix}.whitebind = {whiteBindPermissionsPart}{coreNode.P2pEndPoint.ToString(coreNode.Network.DefaultPort)}",
- $"{configPrefix}.rpcbind = {coreNode.RpcEndPoint.GetHostOrDefault()}",
+ $"{configPrefix}.rpcbind = {rpcBindParameter}",
$"{configPrefix}.rpcallowip = {IPAddress.Loopback}",
- $"{configPrefix}.rpcport = {coreNode.RpcEndPoint.GetPortOrDefault()}"
+ $"{configPrefix}.rpcport = {rpcPortParameter}"
};
if (!cookieAuth)

MODIFY
WalletWasabi/Extensions/SystemNetExtensions.cs
WalletWasabi/Extensions/SystemNetExtensions.cs
+using System.Diagnostics.CodeAnalysis;
+
namespace System.Net
{
public static class SystemNetExtensions
{
- public static int? GetPortOrDefault(this EndPoint me)
+ /// <summary>
+ /// Tries to get port from <paramref name="endPoint"/> which must be either <see cref="DnsEndPoint"/> or <see cref="IPEndPoint"/>.
+ /// </summary>
+ /// <returns><c>true</c> when port can be returned for <paramref name="endPoint"/>, <c>false</c> otherwise.</returns>
+ public static bool TryGetPort(this EndPoint endPoint, [NotNullWhen(true)] out int? port)
{
- int port;
- if (me is DnsEndPoint dnsEndPoint)
+ if (endPoint is DnsEndPoint dnsEndPoint)
{
port = dnsEndPoint.Port;
+ return true;
}
- else if (me is IPEndPoint ipEndPoint)
+ else if (endPoint is IPEndPoint ipEndPoint)
{
port = ipEndPoint.Port;
+ return true;
}
else
{
- return null;
+ port = null;
+ return false;
}
-
- return port;
}
- public static string GetHostOrDefault(this EndPoint me)
+ /// <summary>
+ /// Tries to get host from <paramref name="endPoint"/> which must be either <see cref="DnsEndPoint"/> or <see cref="IPEndPoint"/>.
+ /// </summary>
+ /// <returns><c>true</c> when host can be returned for <paramref name="endPoint"/>, <c>false</c> otherwise.</returns>
+ public static bool TryGetHost(this EndPoint endPoint, [NotNullWhen(true)] out string? host)
{
- string host;
- if (me is DnsEndPoint dnsEndPoint)
+ if (endPoint is DnsEndPoint dnsEndPoint)
{
host = dnsEndPoint.Host;
+ return true;
}
- else if (me is IPEndPoint ipEndPoint)
+ else if (endPoint is IPEndPoint ipEndPoint)
{
host = ipEndPoint.Address.ToString();
+ return true;
}
else
{
- return null;
+ host = null;
+ return false;
+ }
}
- return host;
+ /// <summary>
+ /// Tries to get host and port from <paramref name="endPoint"/> which must be either <see cref="DnsEndPoint"/> or <see cref="IPEndPoint"/>.
+ /// </summary>
+ /// <returns><c>true</c> when host and port can be returned for <paramref name="endPoint"/>, <c>false</c> otherwise.</returns>
+ public static bool TryGetHostAndPort(this EndPoint endPoint, [NotNullWhen(true)] out string? host, [NotNullWhen(true)] out int? port)
+ {
+ if (endPoint is DnsEndPoint dnsEndPoint)
+ {
+ host = dnsEndPoint.Host;
+ port = dnsEndPoint.Port;
+ return true;
+ }
+ else if (endPoint is IPEndPoint ipEndPoint)
+ {
+ host = ipEndPoint.Address.ToString();
+ port = ipEndPoint.Port;
+ return true;
+ }
+ else
+ {
+ host = null;
+ port = null;
+ return false;
+ }
}
}
}

MODIFY
WalletWasabi/Tor/Socks5/TorSocks5Client.cs
WalletWasabi/Tor/Socks5/TorSocks5Client.cs
@@ -60,8 +60,11 @@ namespace WalletWasabi.Tor.Socks5
using (await AsyncLock.LockAsync().ConfigureAwait(false))
{
- string host = TorSocks5EndPoint.GetHostOrDefault();
- int? port = TorSocks5EndPoint.GetPortOrDefault();
+ if (!TorSocks5EndPoint.TryGetHostAndPort(out string? host, out int? port))
+ {
+ throw new ArgumentException("Endpoint type is not supported.", nameof(TorSocks5EndPoint));
+ }
+
try
{
await TcpClient.ConnectAsync(host, port.Value).ConfigureAwait(false);
@@ -185,8 +188,12 @@ namespace WalletWasabi.Tor.Socks5
internal async Task ConnectToDestinationAsync(EndPoint destination, bool isRecursiveCall = false)
{
- Guard.NotNull(nameof(destination), destination);
- await ConnectToDestinationAsync(destination.GetHostOrDefault(), destination.GetPortOrDefault().Value, isRecursiveCall: isRecursiveCall).ConfigureAwait(false);
+ if (!destination.TryGetHostAndPort(out string? host, out int? port))
+ {
+ throw new ArgumentException("Endpoint type is not supported.", nameof(destination));
+ }
+
+ await ConnectToDestinationAsync(host, port.Value, isRecursiveCall: isRecursiveCall).ConfigureAwait(false);
}
/// <param name="host">IPv4 or domain</param>

Use TryGet* approach in SystemNetExtensions.