LRM Server-Side NAT Punchtrough code
This commit is contained in:
parent
cd309b2a93
commit
45f82b812d
6 changed files with 264 additions and 82 deletions
51
ServerProject-DONT-IMPORT-INTO-UNITY/BiDictionary.cs
Normal file
51
ServerProject-DONT-IMPORT-INTO-UNITY/BiDictionary.cs
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
//
|
||||||
|
// Source: https://stackoverflow.com/questions/255341/getting-multiple-keys-of-specified-value-of-a-generic-dictionary#255630
|
||||||
|
//
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace LightReflectiveMirror
|
||||||
|
{
|
||||||
|
class BiDictionary<TFirst, TSecond>
|
||||||
|
{
|
||||||
|
IDictionary<TFirst, TSecond> firstToSecond = new Dictionary<TFirst, TSecond>();
|
||||||
|
IDictionary<TSecond, TFirst> secondToFirst = new Dictionary<TSecond, TFirst>();
|
||||||
|
|
||||||
|
public void Add(TFirst first, TSecond second)
|
||||||
|
{
|
||||||
|
if (firstToSecond.ContainsKey(first) ||
|
||||||
|
secondToFirst.ContainsKey(second))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Duplicate first or second");
|
||||||
|
}
|
||||||
|
firstToSecond.Add(first, second);
|
||||||
|
secondToFirst.Add(second, first);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetByFirst(TFirst first, out TSecond second)
|
||||||
|
{
|
||||||
|
return firstToSecond.TryGetValue(first, out second);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Remove(TFirst first)
|
||||||
|
{
|
||||||
|
secondToFirst.Remove(firstToSecond[first]);
|
||||||
|
firstToSecond.Remove(first);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetBySecond(TSecond second, out TFirst first)
|
||||||
|
{
|
||||||
|
return secondToFirst.TryGetValue(second, out first);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TSecond GetByFirst(TFirst first)
|
||||||
|
{
|
||||||
|
return firstToSecond[first];
|
||||||
|
}
|
||||||
|
|
||||||
|
public TFirst GetBySecond(TSecond second)
|
||||||
|
{
|
||||||
|
return secondToFirst[second];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,8 +11,10 @@ namespace LightReflectiveMirror
|
||||||
public string AuthenticationKey = "Secret Auth Key";
|
public string AuthenticationKey = "Secret Auth Key";
|
||||||
public int UpdateLoopTime = 10;
|
public int UpdateLoopTime = 10;
|
||||||
public int UpdateHeartbeatInterval = 100;
|
public int UpdateHeartbeatInterval = 100;
|
||||||
public bool UseEndpoint = false;
|
public bool UseEndpoint = true;
|
||||||
public ushort EndpointPort = 6969;
|
public ushort EndpointPort = 8080;
|
||||||
public bool EndpointServerList = false;
|
public bool EndpointServerList = true;
|
||||||
|
public bool EnableNATPunchtroughServer = true;
|
||||||
|
public ushort NATPunchtroughPort = 7776;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
using Grapevine;
|
using Grapevine;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
@ -49,26 +52,29 @@ namespace LightReflectiveMirror.Endpoints
|
||||||
|
|
||||||
public class EndpointServer
|
public class EndpointServer
|
||||||
{
|
{
|
||||||
public bool Start(ushort port = 6969)
|
public bool Start(ushort port = 8080)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var server = RestServerBuilder.UseDefaults().Build();
|
var config = new ConfigurationBuilder()
|
||||||
server.Prefixes.Remove($"http://localhost:{1234}/");
|
.SetBasePath(System.IO.Directory.GetCurrentDirectory())
|
||||||
server.Prefixes.Add($"http://*:{port}/");
|
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
server.Router.Options.SendExceptionMessages = false;
|
.Build();
|
||||||
|
|
||||||
server.AfterStarting += (s) =>
|
Action<IServiceCollection> configServices = (services) =>
|
||||||
{
|
{
|
||||||
string startup = @"
|
services.AddLogging(configure => configure.AddConsole());
|
||||||
********************************************************************************
|
services.Configure<LoggerFilterOptions>(options => options.MinLevel = LogLevel.None);
|
||||||
* Endpoint Server listening on "+$"{string.Join(", ", server.Prefixes)}" + @"
|
|
||||||
* Be sure to Port Forward! :^)
|
|
||||||
********************************************************************************
|
|
||||||
";
|
|
||||||
Console.WriteLine(startup);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Action<IRestServer> configServer = (server) =>
|
||||||
|
{
|
||||||
|
server.Prefixes.Add($"http://*:{port}/");
|
||||||
|
};
|
||||||
|
|
||||||
|
var server = new RestServerBuilder(new ServiceCollection(), config, configServices, configServer).Build();
|
||||||
|
server.Router.Options.SendExceptionMessages = false;
|
||||||
|
|
||||||
server.Start();
|
server.Start();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,10 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using LightReflectiveMirror.Endpoints;
|
using LightReflectiveMirror.Endpoints;
|
||||||
using Mirror;
|
using Mirror;
|
||||||
|
|
@ -25,8 +28,15 @@ namespace LightReflectiveMirror
|
||||||
private DateTime _startupTime;
|
private DateTime _startupTime;
|
||||||
|
|
||||||
private List<int> _currentConnections = new List<int>();
|
private List<int> _currentConnections = new List<int>();
|
||||||
|
public Dictionary<int, IPEndPoint> NATConnections = new Dictionary<int, IPEndPoint>();
|
||||||
|
private BiDictionary<int, string> _pendingNATPunches = new BiDictionary<int, string>();
|
||||||
private int _currentHeartbeatTimer = 0;
|
private int _currentHeartbeatTimer = 0;
|
||||||
|
|
||||||
|
private byte[] _NATRequest = new byte[500];
|
||||||
|
private int _NATRequestPosition = 0;
|
||||||
|
|
||||||
|
private UdpClient _punchServer;
|
||||||
|
|
||||||
private const string CONFIG_PATH = "config.json";
|
private const string CONFIG_PATH = "config.json";
|
||||||
|
|
||||||
public static void Main(string[] args) => new Program().MainAsync().GetAwaiter().GetResult();
|
public static void Main(string[] args) => new Program().MainAsync().GetAwaiter().GetResult();
|
||||||
|
|
@ -52,33 +62,34 @@ namespace LightReflectiveMirror
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
conf = JsonConvert.DeserializeObject<Config>(File.ReadAllText(CONFIG_PATH));
|
conf = JsonConvert.DeserializeObject<Config>(File.ReadAllText(CONFIG_PATH));
|
||||||
|
WriteLogMessage("Loading Assembly... ", ConsoleColor.White, true);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var asm = Assembly.LoadFile(Directory.GetCurrentDirectory() + @"\" + conf.TransportDLL);
|
var asm = Assembly.LoadFile(Directory.GetCurrentDirectory() + @"\" + conf.TransportDLL);
|
||||||
WriteLogMessage($"Loaded Assembly: {asm.FullName}", ConsoleColor.Green);
|
WriteLogMessage($"OK", ConsoleColor.Green);
|
||||||
|
|
||||||
|
WriteLogMessage("\nLoading Transport Class... ", ConsoleColor.White, true);
|
||||||
|
|
||||||
transport = asm.CreateInstance(conf.TransportClass) as Transport;
|
transport = asm.CreateInstance(conf.TransportClass) as Transport;
|
||||||
|
|
||||||
if (transport != null)
|
if (transport != null)
|
||||||
{
|
{
|
||||||
var transportClass = asm.GetType(conf.TransportClass);
|
var transportClass = asm.GetType(conf.TransportClass);
|
||||||
|
WriteLogMessage("OK", ConsoleColor.Green);
|
||||||
|
|
||||||
WriteLogMessage($"Loaded Transport: {transportClass.Name}! Loading Methods...", ConsoleColor.Green);
|
WriteLogMessage("\nLoading Transport Methods... ", ConsoleColor.White, true);
|
||||||
CheckMethods(transportClass);
|
CheckMethods(transportClass);
|
||||||
|
WriteLogMessage("OK", ConsoleColor.Green);
|
||||||
|
|
||||||
|
WriteLogMessage("\nInvoking Transport Methods...");
|
||||||
|
|
||||||
if (_awakeMethod != null)
|
if (_awakeMethod != null)
|
||||||
{
|
|
||||||
_awakeMethod.Invoke(transport, null);
|
_awakeMethod.Invoke(transport, null);
|
||||||
WriteLogMessage("Called Awake on transport.", ConsoleColor.Yellow);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_startMethod != null)
|
if (_startMethod != null)
|
||||||
{
|
_startMethod.Invoke(transport, null);
|
||||||
_awakeMethod.Invoke(transport, null);
|
|
||||||
WriteLogMessage("Called Start on transport.", ConsoleColor.Yellow);
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteLogMessage("Starting Transport...", ConsoleColor.Green);
|
WriteLogMessage("\nStarting Transport... ", ConsoleColor.White, true);
|
||||||
|
|
||||||
transport.OnServerError = (clientID, error) =>
|
transport.OnServerError = (clientID, error) =>
|
||||||
{
|
{
|
||||||
|
|
@ -90,6 +101,16 @@ namespace LightReflectiveMirror
|
||||||
WriteLogMessage($"Transport Connected, Client: {clientID}", ConsoleColor.Cyan);
|
WriteLogMessage($"Transport Connected, Client: {clientID}", ConsoleColor.Cyan);
|
||||||
_currentConnections.Add(clientID);
|
_currentConnections.Add(clientID);
|
||||||
_relay.ClientConnected(clientID);
|
_relay.ClientConnected(clientID);
|
||||||
|
|
||||||
|
if (conf.EnableNATPunchtroughServer)
|
||||||
|
{
|
||||||
|
string natID = Guid.NewGuid().ToString();
|
||||||
|
_pendingNATPunches.Add(clientID, natID);
|
||||||
|
_NATRequestPosition = 0;
|
||||||
|
_NATRequest.WriteByte(ref _NATRequestPosition, (byte)OpCodes.RequestNATConnection);
|
||||||
|
_NATRequest.WriteString(ref _NATRequestPosition, natID);
|
||||||
|
transport.ServerSend(clientID, 0, new ArraySegment<byte>(_NATRequest, 0, _NATRequestPosition));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_relay = new RelayHandler(transport.GetMaxPacketSize(0));
|
_relay = new RelayHandler(transport.GetMaxPacketSize(0));
|
||||||
|
|
@ -99,32 +120,71 @@ namespace LightReflectiveMirror
|
||||||
{
|
{
|
||||||
_currentConnections.Remove(clientID);
|
_currentConnections.Remove(clientID);
|
||||||
_relay.HandleDisconnect(clientID);
|
_relay.HandleDisconnect(clientID);
|
||||||
|
|
||||||
|
if(NATConnections.ContainsKey(clientID))
|
||||||
|
NATConnections.Remove(clientID);
|
||||||
|
|
||||||
|
if(_pendingNATPunches.TryGetByFirst(clientID, out _))
|
||||||
|
_pendingNATPunches.Remove(clientID);
|
||||||
};
|
};
|
||||||
|
|
||||||
transport.ServerStart();
|
transport.ServerStart();
|
||||||
|
|
||||||
WriteLogMessage("Transport Started!", ConsoleColor.Green);
|
WriteLogMessage("OK", ConsoleColor.Green);
|
||||||
|
|
||||||
if (conf.UseEndpoint)
|
if (conf.UseEndpoint)
|
||||||
{
|
{
|
||||||
|
WriteLogMessage("\nStarting Endpoint Service... ", ConsoleColor.White, true);
|
||||||
var endpoint = new EndpointServer();
|
var endpoint = new EndpointServer();
|
||||||
|
|
||||||
if (endpoint.Start(conf.EndpointPort))
|
if (endpoint.Start(conf.EndpointPort))
|
||||||
WriteLogMessage("Endpoint Service Started!", ConsoleColor.Green);
|
{
|
||||||
|
WriteLogMessage("OK", ConsoleColor.Green);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
WriteLogMessage("Endpoint failure, please run as administrator.", ConsoleColor.Red);
|
{
|
||||||
|
WriteLogMessage("FAILED\nPlease run as administrator or check if port is in use.", ConsoleColor.DarkRed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conf.EnableNATPunchtroughServer)
|
||||||
|
{
|
||||||
|
WriteLogMessage("\nStarting NatPunchthrough Socket... ", ConsoleColor.White, true);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_punchServer = new UdpClient(conf.NATPunchtroughPort);
|
||||||
|
|
||||||
|
WriteLogMessage("OK\n", ConsoleColor.Green, true);
|
||||||
|
|
||||||
|
WriteLogMessage("\nStarting NatPunchthrough Thread... ", ConsoleColor.White, true);
|
||||||
|
var natThread = new Thread(new ThreadStart(RunNATPunchLoop));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
natThread.Start();
|
||||||
|
}catch(Exception err)
|
||||||
|
{
|
||||||
|
WriteLogMessage("FAILED\n" + err, ConsoleColor.DarkRed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception error)
|
||||||
|
{
|
||||||
|
WriteLogMessage("FAILED\nCheck if port is in use.", ConsoleColor.DarkRed, true);
|
||||||
|
Console.WriteLine(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WriteLogMessage("Transport Class not found! Please make sure to include namespaces.", ConsoleColor.Red);
|
WriteLogMessage("FAILED\nClass not found, make sure to included namespaces!", ConsoleColor.DarkRed);
|
||||||
Console.ReadKey();
|
Console.ReadKey();
|
||||||
Environment.Exit(0);
|
Environment.Exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
WriteLogMessage("Exception: " + e, ConsoleColor.Red);
|
WriteLogMessage("FAILED\nException: " + e, ConsoleColor.DarkRed);
|
||||||
Console.ReadKey();
|
Console.ReadKey();
|
||||||
Environment.Exit(0);
|
Environment.Exit(0);
|
||||||
}
|
}
|
||||||
|
|
@ -151,10 +211,55 @@ namespace LightReflectiveMirror
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteLogMessage(string message, ConsoleColor color = ConsoleColor.White)
|
void RunNATPunchLoop()
|
||||||
|
{
|
||||||
|
WriteLogMessage("OK\n", ConsoleColor.Green);
|
||||||
|
IPEndPoint remoteEndpoint = new IPEndPoint(IPAddress.Any, conf.NATPunchtroughPort);
|
||||||
|
|
||||||
|
// Stock Data server sends to everyone:
|
||||||
|
var serverResponse = new byte[1] { 1 };
|
||||||
|
|
||||||
|
byte[] readData;
|
||||||
|
bool isConnectionEstablishment;
|
||||||
|
int pos;
|
||||||
|
string connectionID;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
readData = _punchServer.Receive(ref remoteEndpoint);
|
||||||
|
pos = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
isConnectionEstablishment = readData.ReadBool(ref pos);
|
||||||
|
|
||||||
|
if (isConnectionEstablishment)
|
||||||
|
{
|
||||||
|
connectionID = readData.ReadString(ref pos);
|
||||||
|
|
||||||
|
if (_pendingNATPunches.TryGetBySecond(connectionID, out pos))
|
||||||
|
{
|
||||||
|
NATConnections.Add(pos, new IPEndPoint(remoteEndpoint.Address, remoteEndpoint.Port));
|
||||||
|
_pendingNATPunches.Remove(pos);
|
||||||
|
Console.WriteLine("Client Successfully Established Puncher Connection. " + remoteEndpoint.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_punchServer.Send(serverResponse, 1, remoteEndpoint);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignore, packet got fucked up or something.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteLogMessage(string message, ConsoleColor color = ConsoleColor.White, bool oneLine = false)
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = color;
|
Console.ForegroundColor = color;
|
||||||
Console.WriteLine(message);
|
if (oneLine)
|
||||||
|
Console.Write(message);
|
||||||
|
else
|
||||||
|
Console.WriteLine(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckMethods(Type type)
|
void CheckMethods(Type type)
|
||||||
|
|
@ -163,11 +268,6 @@ namespace LightReflectiveMirror
|
||||||
_startMethod = type.GetMethod("Start", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
_startMethod = type.GetMethod("Start", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||||
_updateMethod = type.GetMethod("Update", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
_updateMethod = type.GetMethod("Update", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||||
_lateUpdateMethod = type.GetMethod("LateUpdate", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
_lateUpdateMethod = type.GetMethod("LateUpdate", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||||
|
|
||||||
if (_awakeMethod != null) WriteLogMessage("'Awake' Loaded!", ConsoleColor.Yellow);
|
|
||||||
if (_startMethod != null) WriteLogMessage("'Start' Loaded!", ConsoleColor.Yellow);
|
|
||||||
if (_updateMethod != null) WriteLogMessage("'Update' Loaded!", ConsoleColor.Yellow);
|
|
||||||
if (_lateUpdateMethod != null) WriteLogMessage("'LateUpdate' Loaded!", ConsoleColor.Yellow);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteTitle()
|
void WriteTitle()
|
||||||
|
|
@ -184,8 +284,8 @@ namespace LightReflectiveMirror
|
||||||
";
|
";
|
||||||
|
|
||||||
string load = $"Chimp Event Listener Initializing... OK" +
|
string load = $"Chimp Event Listener Initializing... OK" +
|
||||||
"\nHarambe Memorial Initializing... OK" +
|
"\nHarambe Memorial Initializing... OK" +
|
||||||
"\nBananas initializing... OK\n";
|
"\nBananas initializing... OK\n";
|
||||||
|
|
||||||
WriteLogMessage(t, ConsoleColor.Green);
|
WriteLogMessage(t, ConsoleColor.Green);
|
||||||
WriteLogMessage(load, ConsoleColor.Cyan);
|
WriteLogMessage(load, ConsoleColor.Cyan);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace LightReflectiveMirror
|
namespace LightReflectiveMirror
|
||||||
|
|
@ -57,7 +58,7 @@ namespace LightReflectiveMirror
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
{
|
{
|
||||||
case OpCodes.CreateRoom:
|
case OpCodes.CreateRoom:
|
||||||
CreateRoom(clientId, data.ReadInt(ref pos), data.ReadString(ref pos), data.ReadBool(ref pos), data.ReadString(ref pos));
|
CreateRoom(clientId, data.ReadInt(ref pos), data.ReadString(ref pos), data.ReadBool(ref pos), data.ReadString(ref pos), data.ReadBool(ref pos), data.ReadString(ref pos), data.ReadBool(ref pos), data.ReadInt(ref pos));
|
||||||
break;
|
break;
|
||||||
case OpCodes.RequestID:
|
case OpCodes.RequestID:
|
||||||
SendClientID(clientId);
|
SendClientID(clientId);
|
||||||
|
|
@ -66,7 +67,7 @@ namespace LightReflectiveMirror
|
||||||
LeaveRoom(clientId);
|
LeaveRoom(clientId);
|
||||||
break;
|
break;
|
||||||
case OpCodes.JoinServer:
|
case OpCodes.JoinServer:
|
||||||
JoinRoom(clientId, data.ReadInt(ref pos));
|
JoinRoom(clientId, data.ReadInt(ref pos), data.ReadBool(ref pos), data.ReadString(ref pos));
|
||||||
break;
|
break;
|
||||||
case OpCodes.KickPlayer:
|
case OpCodes.KickPlayer:
|
||||||
LeaveRoom(data.ReadInt(ref pos), clientId);
|
LeaveRoom(data.ReadInt(ref pos), clientId);
|
||||||
|
|
@ -74,9 +75,6 @@ namespace LightReflectiveMirror
|
||||||
case OpCodes.SendData:
|
case OpCodes.SendData:
|
||||||
ProcessData(clientId, data.ReadBytes(ref pos), channel, data.ReadInt(ref pos));
|
ProcessData(clientId, data.ReadBytes(ref pos), channel, data.ReadInt(ref pos));
|
||||||
break;
|
break;
|
||||||
case OpCodes.RequestServers:
|
|
||||||
SendServerList(clientId);
|
|
||||||
break;
|
|
||||||
case OpCodes.UpdateRoomData:
|
case OpCodes.UpdateRoomData:
|
||||||
var plyRoom = GetRoomForPlayer(clientId);
|
var plyRoom = GetRoomForPlayer(clientId);
|
||||||
|
|
||||||
|
|
@ -110,28 +108,6 @@ namespace LightReflectiveMirror
|
||||||
|
|
||||||
public void HandleDisconnect(int clientId) => LeaveRoom(clientId);
|
public void HandleDisconnect(int clientId) => LeaveRoom(clientId);
|
||||||
|
|
||||||
void SendServerList(int clientId)
|
|
||||||
{
|
|
||||||
int pos = 0;
|
|
||||||
var buffer = _sendBuffers.Rent(500);
|
|
||||||
buffer.WriteByte(ref pos, (byte)OpCodes.ServerListReponse);
|
|
||||||
for(int i = 0; i < rooms.Count; i++)
|
|
||||||
{
|
|
||||||
if (rooms[i].isPublic)
|
|
||||||
{
|
|
||||||
buffer.WriteBool(ref pos, true);
|
|
||||||
buffer.WriteString(ref pos, rooms[i].serverName);
|
|
||||||
buffer.WriteString(ref pos, rooms[i].serverData);
|
|
||||||
buffer.WriteInt(ref pos, rooms[i].serverId);
|
|
||||||
buffer.WriteInt(ref pos, rooms[i].maxPlayers);
|
|
||||||
buffer.WriteInt(ref pos, rooms[i].clients.Count + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buffer.WriteBool(ref pos, false);
|
|
||||||
Program.transport.ServerSend(clientId, 0, new ArraySegment<byte>(buffer, 0, pos));
|
|
||||||
_sendBuffers.Return(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProcessData(int clientId, byte[] clientData, int channel, int sendTo = -1)
|
void ProcessData(int clientId, byte[] clientData, int channel, int sendTo = -1)
|
||||||
{
|
{
|
||||||
Room playersRoom = GetRoomForPlayer(clientId);
|
Room playersRoom = GetRoomForPlayer(clientId);
|
||||||
|
|
@ -184,7 +160,7 @@ namespace LightReflectiveMirror
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JoinRoom(int clientId, int serverId)
|
void JoinRoom(int clientId, int serverId, bool canDirectConnect, string localIP)
|
||||||
{
|
{
|
||||||
LeaveRoom(clientId);
|
LeaveRoom(clientId);
|
||||||
|
|
||||||
|
|
@ -197,15 +173,44 @@ namespace LightReflectiveMirror
|
||||||
rooms[i].clients.Add(clientId);
|
rooms[i].clients.Add(clientId);
|
||||||
|
|
||||||
int sendJoinPos = 0;
|
int sendJoinPos = 0;
|
||||||
byte[] sendJoinBuffer = _sendBuffers.Rent(5);
|
byte[] sendJoinBuffer = _sendBuffers.Rent(500);
|
||||||
|
|
||||||
sendJoinBuffer.WriteByte(ref sendJoinPos, (byte)OpCodes.ServerJoined);
|
if (canDirectConnect && Program.instance.NATConnections.ContainsKey(clientId))
|
||||||
sendJoinBuffer.WriteInt(ref sendJoinPos, clientId);
|
{
|
||||||
|
sendJoinBuffer.WriteByte(ref sendJoinPos, (byte)OpCodes.DirectConnectIP);
|
||||||
|
|
||||||
Program.transport.ServerSend(clientId, 0, new ArraySegment<byte>(sendJoinBuffer, 0, sendJoinPos));
|
if (Program.instance.NATConnections[clientId].Address.Equals(rooms[i].hostIP.Address))
|
||||||
Program.transport.ServerSend(rooms[i].hostId, 0, new ArraySegment<byte>(sendJoinBuffer, 0, sendJoinPos));
|
sendJoinBuffer.WriteString(ref sendJoinPos, rooms[i].hostLocalIP == localIP ? "127.0.0.1" : rooms[i].hostLocalIP);
|
||||||
_sendBuffers.Return(sendJoinBuffer);
|
else
|
||||||
return;
|
sendJoinBuffer.WriteString(ref sendJoinPos, rooms[i].hostIP.Address.ToString());
|
||||||
|
|
||||||
|
sendJoinBuffer.WriteInt(ref sendJoinPos, rooms[i].useNATPunch ? rooms[i].hostIP.Port : rooms[i].port);
|
||||||
|
|
||||||
|
Program.transport.ServerSend(clientId, 0, new ArraySegment<byte>(sendJoinBuffer, 0, sendJoinPos));
|
||||||
|
|
||||||
|
sendJoinPos = 0;
|
||||||
|
sendJoinBuffer.WriteByte(ref sendJoinPos, (byte)OpCodes.DirectConnectIP);
|
||||||
|
Console.WriteLine(Program.instance.NATConnections[clientId].Address.ToString());
|
||||||
|
sendJoinBuffer.WriteString(ref sendJoinPos, Program.instance.NATConnections[clientId].Address.ToString());
|
||||||
|
sendJoinBuffer.WriteInt(ref sendJoinPos, Program.instance.NATConnections[clientId].Port);
|
||||||
|
|
||||||
|
Program.transport.ServerSend(rooms[i].hostId, 0, new ArraySegment<byte>(sendJoinBuffer, 0, sendJoinPos));
|
||||||
|
|
||||||
|
_sendBuffers.Return(sendJoinBuffer);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
sendJoinBuffer.WriteByte(ref sendJoinPos, (byte)OpCodes.ServerJoined);
|
||||||
|
sendJoinBuffer.WriteInt(ref sendJoinPos, clientId);
|
||||||
|
|
||||||
|
Program.transport.ServerSend(clientId, 0, new ArraySegment<byte>(sendJoinBuffer, 0, sendJoinPos));
|
||||||
|
Program.transport.ServerSend(rooms[i].hostId, 0, new ArraySegment<byte>(sendJoinBuffer, 0, sendJoinPos));
|
||||||
|
_sendBuffers.Return(sendJoinBuffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -220,10 +225,13 @@ namespace LightReflectiveMirror
|
||||||
_sendBuffers.Return(sendBuffer);
|
_sendBuffers.Return(sendBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateRoom(int clientId, int maxPlayers, string serverName, bool isPublic, string serverData)
|
void CreateRoom(int clientId, int maxPlayers, string serverName, bool isPublic, string serverData, bool useDirectConnect, string hostLocalIP, bool useNatPunch, int port)
|
||||||
{
|
{
|
||||||
LeaveRoom(clientId);
|
LeaveRoom(clientId);
|
||||||
|
|
||||||
|
IPEndPoint hostIP = null;
|
||||||
|
Program.instance.NATConnections.TryGetValue(clientId, out hostIP);
|
||||||
|
|
||||||
Room room = new Room
|
Room room = new Room
|
||||||
{
|
{
|
||||||
hostId = clientId,
|
hostId = clientId,
|
||||||
|
|
@ -232,8 +240,12 @@ namespace LightReflectiveMirror
|
||||||
isPublic = isPublic,
|
isPublic = isPublic,
|
||||||
serverData = serverData,
|
serverData = serverData,
|
||||||
clients = new List<int>(),
|
clients = new List<int>(),
|
||||||
|
serverId = GetRandomServerID(),
|
||||||
serverId = GetRandomServerID()
|
hostIP = hostIP,
|
||||||
|
hostLocalIP = hostLocalIP,
|
||||||
|
supportsDirectConnect = hostIP == null ? false : useDirectConnect,
|
||||||
|
port = port,
|
||||||
|
useNATPunch = useNatPunch
|
||||||
};
|
};
|
||||||
|
|
||||||
rooms.Add(room);
|
rooms.Add(room);
|
||||||
|
|
@ -322,6 +334,7 @@ namespace LightReflectiveMirror
|
||||||
public enum OpCodes
|
public enum OpCodes
|
||||||
{
|
{
|
||||||
Default = 0, RequestID = 1, JoinServer = 2, SendData = 3, GetID = 4, ServerJoined = 5, GetData = 6, CreateRoom = 7, ServerLeft = 8, PlayerDisconnected = 9, RoomCreated = 10,
|
Default = 0, RequestID = 1, JoinServer = 2, SendData = 3, GetID = 4, ServerJoined = 5, GetData = 6, CreateRoom = 7, ServerLeft = 8, PlayerDisconnected = 9, RoomCreated = 10,
|
||||||
LeaveRoom = 11, KickPlayer = 12, AuthenticationRequest = 13, AuthenticationResponse = 14, RequestServers = 15, ServerListReponse = 16, Authenticated = 17, UpdateRoomData = 18, ServerConnectionData = 19
|
LeaveRoom = 11, KickPlayer = 12, AuthenticationRequest = 13, AuthenticationResponse = 14, Authenticated = 17, UpdateRoomData = 18, ServerConnectionData = 19, RequestNATConnection = 20,
|
||||||
|
DirectConnectIP = 21
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
using System;
|
using Newtonsoft.Json;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Net;
|
||||||
|
|
||||||
namespace LightReflectiveMirror
|
namespace LightReflectiveMirror
|
||||||
{
|
{
|
||||||
[Serializable]
|
[JsonObject(MemberSerialization.OptOut)]
|
||||||
public class Room
|
public class Room
|
||||||
{
|
{
|
||||||
public int serverId;
|
public int serverId;
|
||||||
|
|
@ -14,5 +14,15 @@ namespace LightReflectiveMirror
|
||||||
public bool isPublic;
|
public bool isPublic;
|
||||||
public int maxPlayers;
|
public int maxPlayers;
|
||||||
public List<int> clients;
|
public List<int> clients;
|
||||||
|
[JsonIgnore]
|
||||||
|
public bool supportsDirectConnect = false;
|
||||||
|
[JsonIgnore]
|
||||||
|
public IPEndPoint hostIP;
|
||||||
|
[JsonIgnore]
|
||||||
|
public string hostLocalIP;
|
||||||
|
[JsonIgnore]
|
||||||
|
public bool useNATPunch = false;
|
||||||
|
[JsonIgnore]
|
||||||
|
public int port;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue