ZeroTier intergration

This commit is contained in:
Sardelka
2022-08-12 20:40:50 +08:00
parent 495e5dc6b0
commit 8d450813e1
6 changed files with 119 additions and 61 deletions

View File

@ -6,6 +6,7 @@ using System.Drawing;
using System.Net;
using System.Threading;
using RageCoop.Core;
using GTA.UI;
namespace RageCoop.Client.Menus
{
@ -81,7 +82,15 @@ namespace RageCoop.Client.Menus
try
{
Menu.Visible = false;
if (server.ZeroTier)
{
address=$"{server.ZeroTierAddress}:{server.Port}";
Main.QueueAction(() => { Notification.Show($"~y~Joining ZeroTier network... {address}"); });
if (ZeroTierHelper.Join(server.ZeroTierNetWorkID)==null)
{
throw new Exception("Failed to obtain ZeroTier network IP");
}
}
Networking.ToggleConnection(address);
#if !NON_INTERACTIVE
CoopMenu.ServerIpItem.AltTitle = address;
@ -93,7 +102,7 @@ namespace RageCoop.Client.Menus
}
catch (Exception ex)
{
GTA.UI.Notification.Show($"~r~{ex.Message}");
Notification.Show($"~r~{ex.Message}");
}
};
Menu.Add(tmpItem);

View File

@ -5,7 +5,7 @@ using System.Collections.Generic;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using GTA.UI;
namespace RageCoop.Client
{
internal static partial class Networking
@ -34,7 +34,7 @@ namespace RageCoop.Client
else if (IsConnecting) {
_publicKeyReceived.Set();
IsConnecting = false;
GTA.UI.Notification.Show("Connection has been canceled");
Notification.Show("Connection has been canceled");
}
else
{
@ -84,10 +84,10 @@ namespace RageCoop.Client
try { ProcessMessage(m); }
catch (Exception ex) { Main.Logger.Error(ex); }
};
Main.QueueAction(() => { GTA.UI.Notification.Show($"~y~Trying to connect..."); });
Main.QueueAction(() => { Notification.Show($"~y~Trying to connect..."); });
Menus.CoopMenu._serverConnectItem.Enabled=false;
Security.Regen();
if (!GetServerPublicKey(address))
if (!GetServerPublicKey(ip[0],int.Parse(ip[1])))
{
Menus.CoopMenu._serverConnectItem.Enabled=true;
throw new TimeoutException("Failed to retrive server's public key");
@ -112,7 +112,7 @@ namespace RageCoop.Client
catch (Exception ex)
{
Main.Logger.Error("Cannot connect to server: ", ex);
Main.QueueAction(() => GTA.UI.Notification.Show("Cannot connect to server: "+ex.Message));
Main.QueueAction(() => Notification.Show("Cannot connect to server: "+ex.Message));
}
IsConnecting=false;
});
@ -147,13 +147,12 @@ namespace RageCoop.Client
#endregion // -- PLAYER --
#region -- GET --
private static bool GetServerPublicKey(string address, int timeout = 10000)
private static bool GetServerPublicKey(string host,int port, int timeout = 10000)
{
Security.ServerRSA=null;
var msg = Peer.CreateMessage();
new Packets.PublicKeyRequest().Pack(msg);
var adds = address.Split(':');
Peer.SendUnconnectedMessage(msg, adds[0], int.Parse(adds[1]));
Peer.SendUnconnectedMessage(msg, host, port);
return _publicKeyReceived.WaitOne(timeout) && Security.ServerRSA!=null;
}

View File

@ -6,10 +6,12 @@ using System.Threading.Tasks;
using GTA.Math;
using System.Security.Cryptography;
using System.Net;
using System.Net.Http;
using System.Net.Sockets;
using System.IO;
using System.Runtime.CompilerServices;
using Lidgren.Network;
using Newtonsoft.Json;
[assembly: InternalsVisibleTo("RageCoop.Server")]
[assembly: InternalsVisibleTo("RageCoop.Client")]
@ -152,7 +154,7 @@ namespace RageCoop.Core
return endPoint.Address;
}
}
private static IPAddress GetIPfromHost(string p)
public static IPAddress GetIPfromHost(string p)
{
var hosts = Dns.GetHostAddresses(p);
@ -161,7 +163,34 @@ namespace RageCoop.Core
return hosts[0];
}
public static IpInfo GetIPInfo()
{
// TLS only
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
var httpClient = new HttpClient();
HttpResponseMessage response = httpClient.GetAsync("https://ipinfo.io/json").GetAwaiter().GetResult();
if (response.StatusCode != HttpStatusCode.OK)
{
throw new Exception($"IPv4 request failed! [{(int)response.StatusCode}/{response.ReasonPhrase}]");
}
string content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
return JsonConvert.DeserializeObject<IpInfo>(content);
}
}
internal struct IpInfo
{
[JsonProperty("ip")]
public string Address { get; set; }
[JsonProperty("country")]
public string Country { get; set; }
}
internal static class Extensions
{

View File

@ -12,7 +12,7 @@ namespace RageCoop.Core
public string Address { get; set; }
[JsonProperty("port")]
public int Port { get; set; }
public string Port { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
@ -21,10 +21,10 @@ namespace RageCoop.Core
public string Version { get; set; }
[JsonProperty("players")]
public int Players { get; set; }
public string Players { get; set; }
[JsonProperty("maxPlayers")]
public int MaxPlayers { get; set; }
public string MaxPlayers { get; set; }
[JsonProperty("country")]
public string Country { get; set; }
@ -40,5 +40,19 @@ namespace RageCoop.Core
[JsonProperty("language")]
public string Language { get; set; }
[JsonProperty("useP2P")]
public bool P2P { get; set; }
[JsonProperty("useZT")]
public bool ZeroTier { get; set; }
[JsonProperty("ztID")]
public string ZeroTierNetWorkID { get; set; }
[JsonProperty("ztAddress")]
public string ZeroTierAddress { get; set; }
}
}

View File

@ -54,7 +54,7 @@ namespace RageCoop.Core
throw new Exception("ZeroTier not ready: "+status);
}
}
public static ZeroTierNetwork Join(string networkId, bool waitIpAssign=true)
public static ZeroTierNetwork Join(string networkId, int timeout=10000)
{
var p = Run("join "+networkId);
var o = p.StandardOutput.ReadToEnd();
@ -62,10 +62,12 @@ namespace RageCoop.Core
{
throw new Exception(o+p.StandardError.ReadToEnd());
}
if (!waitIpAssign) { return ListNetworks()[networkId]; }
while (true)
if (timeout==0) { return Networks[networkId]; }
int i = 0;
while (i<=timeout)
{
if(ListNetworks().TryGetValue(networkId,out var n))
i+=100;
if(Networks.TryGetValue(networkId,out var n))
{
if (n.Addresses.Count!=0 && (!n.Addresses.Where(x=>x=="-").Any()))
{
@ -89,22 +91,24 @@ namespace RageCoop.Core
throw new Exception(o+p.StandardError.ReadToEnd());
}
}
public static Dictionary<string, ZeroTierNetwork> ListNetworks()
public static Dictionary<string, ZeroTierNetwork> Networks
{
Dictionary<string, ZeroTierNetwork> networks=new Dictionary<string, ZeroTierNetwork>();
var p = Run("listnetworks");
var lines=Regex.Split(p.StandardOutput.ReadToEnd(),"\n").Skip(1);
get {
Dictionary<string, ZeroTierNetwork> networks = new Dictionary<string, ZeroTierNetwork>();
var p = Run("listnetworks");
var lines = Regex.Split(p.StandardOutput.ReadToEnd(), "\n").Skip(1);
foreach (var line in lines)
{
var l=line.Replace("\r","");
if (!string.IsNullOrWhiteSpace(l))
foreach (var line in lines)
{
var n = new ZeroTierNetwork(l);
networks.Add(n.ID,n);
var l = line.Replace("\r", "");
if (!string.IsNullOrWhiteSpace(l))
{
var n = new ZeroTierNetwork(l);
networks.Add(n.ID, n);
}
}
return networks;
}
return networks;
}
private static Process Run(string args)
{
@ -116,6 +120,7 @@ namespace RageCoop.Core
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow=true,
};
p.Start();
p.WaitForExit();

View File

@ -20,14 +20,6 @@ using RageCoop.Core.Scripting;
namespace RageCoop.Server
{
internal struct IpInfo
{
[JsonProperty("ip")]
public string Address { get; set; }
[JsonProperty("country")]
public string Country { get; set; }
}
/// <summary>
/// The instantiable RageCoop server class
@ -121,18 +113,10 @@ namespace RageCoop.Server
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
HttpClient httpClient = new();
IpInfo info;
try
{
HttpResponseMessage response = await httpClient.GetAsync("https://ipinfo.io/json");
if (response.StatusCode != HttpStatusCode.OK)
{
throw new Exception($"IPv4 request failed! [{(int)response.StatusCode}/{response.ReasonPhrase}]");
}
string content = await response.Content.ReadAsStringAsync();
info = JsonConvert.DeserializeObject<IpInfo>(content);
info = CoreUtils.GetIPInfo();
Logger?.Info($"Your public IP is {info.Address}, announcing to master server...");
}
catch (Exception ex)
@ -142,24 +126,29 @@ namespace RageCoop.Server
}
while (!_stopping)
{
var serverInfo = new ServerInfo
{
Address = info.Address,
Port=Settings.Port,
Country=info.Country,
Name=Settings.Name,
Version=_compatibleVersion.Replace("_", "."),
Players=MainNetServer.ConnectionsCount,
MaxPlayers=Settings.MaxPlayers,
Description=Settings.Description,
Website=Settings.Website,
GameMode=Settings.GameMode,
Language=Settings.Language,
};
string msg = JsonConvert.SerializeObject(serverInfo);
HttpResponseMessage response = null;
try
{
var serverInfo = new ServerInfo
{
Address = info.Address,
Port=Settings.Port.ToString(),
Country=info.Country,
Name=Settings.Name,
Version=_compatibleVersion.Replace("_", "."),
Players=MainNetServer.ConnectionsCount.ToString(),
MaxPlayers=Settings.MaxPlayers.ToString(),
Description=Settings.Description,
Website=Settings.Website,
GameMode=Settings.GameMode,
Language=Settings.Language,
P2P=Settings.UseP2P,
ZeroTier=Settings.UseZeroTier,
ZeroTierNetWorkID=Settings.UseZeroTier ? Settings.ZeroTierNetworkID : "",
ZeroTierAddress=Settings.UseZeroTier ? ZeroTierHelper.Networks[Settings.ZeroTierNetworkID].Addresses.Where(x => !x.Contains(":")).First() : "0.0.0.0",
};
string msg = JsonConvert.SerializeObject(serverInfo);
var realUrl = Util.GetFinalRedirect(Settings.MasterServer);
response = await httpClient.PostAsync(realUrl, new StringContent(msg, Encoding.UTF8, "application/json"));
}
@ -227,6 +216,19 @@ namespace RageCoop.Server
Logger?.Info($"Compatible RAGECOOP versions: {_compatibleVersion.Replace('_', '.')}.x");
Logger?.Info("================");
if (Settings.UseZeroTier)
{
Logger?.Info($"Joining ZeroTier network: "+Settings.ZeroTierNetworkID);
if (ZeroTierHelper.Join(Settings.ZeroTierNetworkID)==null)
{
throw new Exception("Failed to obtain ZeroTier network IP");
}
}
else if (Settings.UseP2P)
{
Logger?.Warning("ZeroTier is not enabled, P2P connection may not work as expected.");
}
// 623c92c287cc392406e7aaaac1c0f3b0 = RAGECOOP
NetPeerConfiguration config = new("623c92c287cc392406e7aaaac1c0f3b0")
{