/*
* Copyright (c) 2023 Proton AG
*
* This file is part of ProtonVPN.
*
* ProtonVPN is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonVPN is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonVPN. If not, see .
*/
using System;
using System.Collections.Generic;
using ProtonVPN.Common.Core.Extensions;
using ProtonVPN.Common.Core.Networking;
using ProtonVPN.Common.Legacy.Helpers;
using ProtonVPN.Crypto.Contracts;
namespace ProtonVPN.Common.Legacy.Vpn;
public struct VpnHost
{
public string Name { get; }
public string Ip { get; }
public string Label { get; }
public PublicKey X25519PublicKey { get; }
public string Signature { get; }
public bool IsIpv6Supported { get; }
public Dictionary RelayIpByProtocol { get; }
public VpnHost(
string name,
string ip,
string label,
PublicKey x25519PublicKey,
string signature,
bool isIpv6Supported,
Dictionary relayIpByProtocol)
{
AssertHostNameIsValid(name);
AssertIpAddressIsValid(ip);
if (relayIpByProtocol is not null)
{
foreach (KeyValuePair protocolIpPair in relayIpByProtocol)
{
AssertIpAddressIsValid(protocolIpPair.Value);
}
}
Name = name;
Ip = ip;
Label = label;
X25519PublicKey = x25519PublicKey;
Signature = signature;
IsIpv6Supported = isIpv6Supported;
RelayIpByProtocol = relayIpByProtocol;
}
public bool IsEmpty() => string.IsNullOrEmpty(Name) && string.IsNullOrEmpty(Ip);
public string GetIp(VpnProtocol protocol)
{
return RelayIpByProtocol is not null && RelayIpByProtocol.TryGetValue(protocol, out string relayIp)
? relayIp
: Ip;
}
private static void AssertHostNameIsValid(string hostName)
{
Ensure.NotEmpty(hostName, nameof(hostName));
UriHostNameType hostNameType = Uri.CheckHostName(hostName);
if (hostNameType != UriHostNameType.Dns && hostNameType != UriHostNameType.IPv4)
{
throw new ArgumentException($"Invalid argument {nameof(hostName)} value: {hostName}");
}
}
private static void AssertIpAddressIsValid(string ip)
{
if (!string.IsNullOrEmpty(ip) && !ip.IsValidIpAddressFormat())
{
throw new ArgumentException($"Invalid argument {nameof(ip)} value: {ip}");
}
}
public static bool operator ==(VpnHost h1, VpnHost h2)
{
return h1.Equals(h2);
}
public override bool Equals(object o)
{
if (o == null)
{
return false;
}
VpnHost vpnHost = (VpnHost)o;
return Ip == vpnHost.Ip &&
(Label == vpnHost.Label || string.IsNullOrEmpty(Label) && string.IsNullOrEmpty(vpnHost.Label));
}
public override int GetHashCode()
{
return Tuple.Create(Ip, Label).GetHashCode();
}
public static bool operator !=(VpnHost h1, VpnHost h2)
{
return !h1.Equals(h2);
}
}