ZeroTier intergration
This commit is contained in:
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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")
|
||||
{
|
||||
|
Reference in New Issue
Block a user