Added the files for the MLAPI Relay Server

- This version of the server is modified from the other open sourced one
  on GitHub as we ignore the port when attempting to connect.
  Program.cs is modified as such
This commit is contained in:
2022-02-17 14:13:58 -06:00
parent 011ba5cba1
commit 9aa31d9cd7
285 changed files with 14612 additions and 0 deletions

View File

@@ -0,0 +1,158 @@
using System;
using System.Collections.Generic;
using System.Net;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Ruffles.Channeling;
using Ruffles.Configuration;
using Ruffles.Connections;
using Ruffles.Core;
namespace MLAPI.Relay.Transports
{
public class RufflesTransport : Transport
{
private RuffleSocket socket;
private readonly Dictionary<ulong, IPEndPoint> endpoints = new Dictionary<ulong, IPEndPoint>();
private NetworkEvent? pendingRecycleEvent = null;
private Connection pendingRecycleConnection = null;
public override void Disconnect(ulong connectionId)
{
socket.Disconnect(connectionId, true);
}
public override object GetConfig()
{
return new RufflesConfig()
{
DefaultChannelType = ChannelType.ReliableSequenced,
SocketConfig = new SocketConfig(),
UseDelay = true
};
}
public override IPEndPoint GetEndPoint(ulong connectionId)
{
if (endpoints.ContainsKey(connectionId))
{
return endpoints[connectionId];
}
// TODO: Handle better
return null;
}
public override NetEventType Poll(out ulong connectionId, out byte channelId, out ArraySegment<byte> payload)
{
if (pendingRecycleEvent != null)
{
pendingRecycleEvent.Value.Recycle();
pendingRecycleEvent = null;
}
if (pendingRecycleConnection != null)
{
pendingRecycleConnection.Recycle();
pendingRecycleConnection = null;
}
socket.RunInternalLoop();
NetworkEvent @event = socket.Poll();
channelId = @event.ChannelId;
switch (@event.Type)
{
case NetworkEventType.Connect:
{
connectionId = @event.Connection.Id;
payload = new ArraySegment<byte>();
endpoints.Add(connectionId, (IPEndPoint)@event.Connection.EndPoint);
return NetEventType.Connect;
}
case NetworkEventType.Timeout:
case NetworkEventType.Disconnect:
{
connectionId = @event.Connection.Id;
payload = new ArraySegment<byte>();
// Will be recycled next iteration
pendingRecycleConnection = @event.Connection;
endpoints.Remove(connectionId);
return NetEventType.Disconnect;
}
case NetworkEventType.Data:
{
connectionId = @event.Connection.Id;
payload = @event.Data;
pendingRecycleEvent = @event;
return NetEventType.Data;
}
default:
{
payload = new ArraySegment<byte>();
channelId = 0;
connectionId = 0;
return NetEventType.Nothing;
}
}
}
public override void Send(ArraySegment<byte> payload, byte channelId, ulong connectionId)
{
socket.Send(payload, connectionId, channelId, false);
}
public override void Start(object config)
{
RufflesConfig rufflesConfig = null;
if (config is RufflesConfig) rufflesConfig = (RufflesConfig)config;
else if (config is JObject) rufflesConfig = ((JObject)config).ToObject<RufflesConfig>();
rufflesConfig.SocketConfig.DualListenPort = Program.Config.ListenPort;
ChannelType[] channelTypes = rufflesConfig.SocketConfig.ChannelTypes;
ChannelType[] newChannelTypes = new ChannelType[channelTypes.Length + 1];
// Copy old channels
for (int i = 0; i < channelTypes.Length; i++)
{
newChannelTypes[i] = channelTypes[i];
}
// Set the default channel
newChannelTypes[newChannelTypes.Length - 1] = rufflesConfig.DefaultChannelType;
// Set the default channel byte
Program.DEFAULT_CHANNEL_BYTE = (byte)(newChannelTypes.Length - 1);
// Change to the new array
rufflesConfig.SocketConfig.ChannelTypes = newChannelTypes;
// Start the socket
socket = new RuffleSocket((SocketConfig)config);
}
public class RufflesConfig
{
public SocketConfig SocketConfig { get; set; } = new SocketConfig();
[JsonConverter(typeof(StringEnumConverter))]
public ChannelType DefaultChannelType { get; set; } = ChannelType.ReliableSequenced;
public bool UseDelay { get; set; } = true;
}
}
}

View File

@@ -0,0 +1,38 @@
using System;
using System.Net;
namespace MLAPI.Relay.Transports
{
public abstract class Transport
{
public abstract void Send(ArraySegment<byte> payload, byte channelId, ulong connectionId);
public abstract void Disconnect(ulong connectionId);
public abstract NetEventType Poll(out ulong connectionId, out byte channelId, out ArraySegment<byte> payload);
public abstract IPEndPoint GetEndPoint(ulong connectionId);
public abstract void Start(object config);
public abstract object GetConfig();
public virtual RelayConfig BeforeSerializeConfig(RelayConfig config)
{
return config;
}
public virtual string ProcessSerializedJson(string json)
{
return json;
}
public virtual RelayConfig AfterDeserializedConfig(RelayConfig config)
{
return config;
}
}
public enum NetEventType
{
Connect,
Disconnect,
Data,
Nothing
}
}

View File

@@ -0,0 +1,161 @@
using System;
using System.Collections.Generic;
using System.Net;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using UnetServerDll;
namespace MLAPI.Relay.Transports
{
public class UnetTransport : Transport
{
private int hostId;
private NetLibraryManager unetManager;
public override void Disconnect(ulong connectionId)
{
unetManager.Disconnect(hostId, (int)connectionId, out byte error);
}
public override object GetConfig()
{
return new UnetConfig()
{
ConnectionConfig = new ConnectionConfig(),
GlobalConfig = new GlobalConfig()
};
}
public override IPEndPoint GetEndPoint(ulong connectionId)
{
unetManager.GetConnectionInfo(hostId, (int)connectionId, out string address, out int port, out byte error);
if ((NetworkError)error == NetworkError.Ok)
{
return new IPEndPoint(IPAddress.Parse(address).MapToIPv6(), port);
}
return null;
}
public override NetEventType Poll(out ulong connectionId, out byte channelId, out ArraySegment<byte> payload)
{
NetworkEventType eventType = unetManager.ReceiveFromHost(hostId, out int _connectionId, out int _channelId, Program.MESSAGE_BUFFER, Program.MESSAGE_BUFFER.Length, out int receivedSize, out byte error);
// Cast to correct types (this is fine because in UNET, under the hood, connectionIds are ushort and channelIds are byte. They are just exposed in C# as int)
connectionId = (ulong)_connectionId;
channelId = (byte)_channelId;
// Wrap buffer
payload = new ArraySegment<byte>(Program.MESSAGE_BUFFER, 0, receivedSize);
if ((NetworkError)error == NetworkError.Timeout)
{
eventType = NetworkEventType.DisconnectEvent;
}
switch (eventType)
{
case NetworkEventType.DataEvent:
{
return NetEventType.Data;
}
case NetworkEventType.ConnectEvent:
{
return NetEventType.Connect;
}
case NetworkEventType.DisconnectEvent:
{
return NetEventType.Disconnect;
}
default:
{
return NetEventType.Nothing;
}
}
}
public override void Send(ArraySegment<byte> payload, byte channelId, ulong connectionId)
{
if (payload.Offset > 0)
{
// UNET cannot handle offsets!
// TODO: Copy
throw new Exception("UNET cannot handle offsets!");
}
unetManager.Send(hostId, (int)connectionId, channelId, payload.Array, payload.Count, out byte error);
}
public override void Start(object config)
{
UnetConfig unetConfig = null;
if (config is UnetConfig) unetConfig = (UnetConfig)config;
else if (config is JObject) unetConfig = ((JObject)config).ToObject<UnetConfig>();
for (int i = 0; i < unetConfig.Channels.Count; i++)
{
unetConfig.ConnectionConfig.AddChannel(unetConfig.Channels[i]);
}
Program.DEFAULT_CHANNEL_BYTE = unetConfig.ConnectionConfig.AddChannel(QosType.ReliableSequenced);
unetManager = new NetLibraryManager(unetConfig.GlobalConfig);
hostId = unetManager.AddHost(new HostTopology(unetConfig.ConnectionConfig, unetConfig.MaxConnections), Program.Config.ListenPort, null);
}
public override RelayConfig BeforeSerializeConfig(RelayConfig config)
{
UnetConfig unetConfig = null;
if (config.TransportConfig is UnetConfig) unetConfig = (UnetConfig)config.TransportConfig;
else if (config.TransportConfig is JObject) unetConfig = ((JObject)config.TransportConfig).ToObject<UnetConfig>();
unetConfig.Channels.Clear();
for (int i = 0; i < unetConfig.ConnectionConfig.Channels.Count; i++)
{
unetConfig.Channels.Add(unetConfig.ConnectionConfig.Channels[i].QOS);
}
unetConfig.ConnectionConfig.Channels.Clear();
return config;
}
public override RelayConfig AfterDeserializedConfig(RelayConfig config)
{
UnetConfig unetConfig = null;
if (config.TransportConfig is UnetConfig) unetConfig = (UnetConfig)config.TransportConfig;
else if (config.TransportConfig is JObject) unetConfig = ((JObject)config.TransportConfig).ToObject<UnetConfig>();
unetConfig.ConnectionConfig.Channels.Clear();
for (int i = 0; i < unetConfig.Channels.Count; i++)
{
unetConfig.ConnectionConfig.AddChannel(unetConfig.Channels[i]);
}
return config;
}
public override string ProcessSerializedJson(string json)
{
return json.Replace(",\n \"ChannelCount\": 0,\n \"SharedOrderChannelCount\": 0,\n \"Channels\": []", "");
}
public class UnetConfig
{
public ushort MaxConnections { get; set; } = 100;
public ConnectionConfig ConnectionConfig { get; set; } = new ConnectionConfig();
public GlobalConfig GlobalConfig { get; set; } = new GlobalConfig();
[JsonProperty(ItemConverterType = typeof(StringEnumConverter))]
public List<QosType> Channels = new List<QosType>();
}
}
}