Skip to content

Commit

Permalink
feat: Added ruffles transport
Browse files Browse the repository at this point in the history
  • Loading branch information
TwoTenPvP committed May 23, 2019
1 parent 1b19a7b commit 340da41
Show file tree
Hide file tree
Showing 8 changed files with 333 additions and 45 deletions.
3 changes: 2 additions & 1 deletion .releaserc
Expand Up @@ -8,7 +8,8 @@
"@semantic-release/release-notes-generator",
["@semantic-release/github", {
"assets": [
{"path": "MLAPI/bin/Release/net35/MLAPI.dll"},
{"path": "MLAPI/bin/Release/net35/MLAPI.dll"},
{"path": "MLAPI/bin/Release/net35/Ruffles.dll"},
{"path": "*.unitypackage"}
]
}]
Expand Down
32 changes: 4 additions & 28 deletions MLAPI.EnetTransport/EnetTransport.cs
Expand Up @@ -21,7 +21,7 @@ public struct EnetChannel
public ushort Port = 7777;
public string Address = "127.0.0.1";
public int MaxClients = 100;
public List<TransportChannel> Channels = new List<TransportChannel>();
public List<EnetChannel> Channels = new List<EnetChannel>();
public int MessageBufferSize = 1024 * 5;


Expand Down Expand Up @@ -227,7 +227,7 @@ public override void Init()
{
Id = i,
Name = MLAPI_CHANNELS[i].Name,
Flags = ChannelTypeToPacketFlag(MLAPI_CHANNELS[i].Type)
Flags = MLAPIChannelTypeToPacketFlag(MLAPI_CHANNELS[i].Type)
});
}

Expand All @@ -242,37 +242,25 @@ public override void Init()
{
Id = id,
Name = Channels[i].Name,
Flags = ChannelTypeToPacketFlag(Channels[i].Type)
Flags = Channels[i].Flags
});
}

messageBuffer = new byte[MessageBufferSize];
}

public PacketFlags ChannelTypeToPacketFlag(ChannelType type)
public PacketFlags MLAPIChannelTypeToPacketFlag(ChannelType type)
{
switch (type)
{
case ChannelType.Unreliable:
{
return PacketFlags.Unsequenced | PacketFlags.UnreliableFragment;
}
case ChannelType.UnreliableFragmented:
{
return PacketFlags.Unsequenced | PacketFlags.UnreliableFragment;
}
case ChannelType.UnreliableSequenced:
{
return PacketFlags.UnreliableFragment;
}
case ChannelType.Reliable:
{
return PacketFlags.Reliable | PacketFlags.Unsequenced;
}
case ChannelType.ReliableFragmented:
{
return PacketFlags.Reliable | PacketFlags.Unsequenced;
}
case ChannelType.ReliableSequenced:
{
return PacketFlags.Reliable;
Expand All @@ -281,18 +269,6 @@ public PacketFlags ChannelTypeToPacketFlag(ChannelType type)
{
return PacketFlags.None;
}
case ChannelType.ReliableStateUpdate:
{
return PacketFlags.Reliable;
}
case ChannelType.AllCostDelivery:
{
return PacketFlags.Reliable;
}
case ChannelType.UnreliableFragmentedSequenced:
{
return PacketFlags.UnreliableFragment;
}
case ChannelType.ReliableFragmentedSequenced:
{
return PacketFlags.Reliable;
Expand Down
3 changes: 3 additions & 0 deletions MLAPI/MLAPI.csproj
Expand Up @@ -20,4 +20,7 @@
<Private>false</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Ruffles" Version="1.0.5" />
</ItemGroup>
</Project>
21 changes: 21 additions & 0 deletions MLAPI/Transports/Ruffles/RufflesChannel.cs
@@ -0,0 +1,21 @@
using System;

namespace MLAPI.Transports.Ruffles
{
/// <summary>
/// A transport channel used by the MLAPI
/// </summary>
[Serializable]
public class RufflesChannel
{
/// <summary>
/// The name of the channel
/// </summary>
public string Name;

/// <summary>
/// The type of channel
/// </summary>
public global::Ruffles.Channeling.ChannelType Type;
}
}
245 changes: 245 additions & 0 deletions MLAPI/Transports/Ruffles/RufflesTransport.cs
@@ -0,0 +1,245 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System;
using System.Collections.Generic;
using Ruffles.Core;
using Ruffles.Configuration;
using System.Net;

namespace MLAPI.Transports.Ruffles
{
public class RufflesTransport : Transport
{
// Inspector / settings
public int MessageBufferSize = 1024 * 5;
public int MaxConnections = 100;
public string ConnectAddress = "127.0.0.1";
public int ConnectPort = 7777;
public int ServerListenPort = 7777;
public List<RufflesChannel> Channels = new List<RufflesChannel>();

// Runtime / state
private byte[] messageBuffer;
private WeakReference temporaryBufferReference;
private bool isConnector = false;

// Lookup / translation
private readonly Dictionary<ulong, global::Ruffles.Connections.Connection> connections = new Dictionary<ulong, global::Ruffles.Connections.Connection>();
private readonly Dictionary<string, byte> channelNameToId = new Dictionary<string, byte>();
private readonly Dictionary<byte, string> channelIdToName = new Dictionary<byte, string>();
private global::Ruffles.Connections.Connection serverConnection;

// Ruffles
private RuffleSocket socket;

public override ulong ServerClientId => GetMLAPIClientId(0, true);

public override void Send(ulong clientId, ArraySegment<byte> data, string channelName, bool skipQueue)
{
GetRufflesConnectionDetails(clientId, out ulong connectionId);

byte channelId = channelNameToId[channelName];

socket.Send(data, connectionId, channelId, skipQueue);
}

public override void FlushSendQueue(ulong clientId)
{

}

public override NetEventType PollEvent(out ulong clientId, out string channelName, out ArraySegment<byte> payload)
{
socket.RunInternalLoop();
NetworkEvent @event = socket.Poll();

if (@event.Type != NetworkEventType.Nothing)
{
clientId = GetMLAPIClientId(@event.Connection.Id, false);
}
else
{
clientId = 0;
}

byte[] dataBuffer = messageBuffer;

if (@event.Type == NetworkEventType.Data)
{
if (@event.Data.Count > messageBuffer.Length)
{
if (temporaryBufferReference != null && temporaryBufferReference.IsAlive && ((byte[])temporaryBufferReference.Target).Length >= @event.Data.Count)
{
dataBuffer = (byte[])temporaryBufferReference.Target;
}
else
{
dataBuffer = new byte[@event.Data.Count];
temporaryBufferReference = new WeakReference(dataBuffer);
}
}

Buffer.BlockCopy(@event.Data.Array, @event.Data.Offset, dataBuffer, 0, @event.Data.Count);
payload = new ArraySegment<byte>(dataBuffer, 0, @event.Data.Count);
}
else
{
payload = new ArraySegment<byte>();
}

// TODO: FIX, ruffles needs to give us the channel
channelName = channelIdToName[0];

// Translate NetworkEventType to NetEventType
switch (@event.Type)
{
case NetworkEventType.Data:
return NetEventType.Data;
case NetworkEventType.Connect:
{
connections.Add(@event.Connection.Id, @event.Connection);

// Set the server connectionId
if (isConnector)
{
serverConnection = @event.Connection;
}

return NetEventType.Connect;
}
case NetworkEventType.Timeout:
case NetworkEventType.Disconnect:
{
if (@event.Connection == serverConnection)
serverConnection = null;

connections.Remove(@event.Connection.Id);

@event.Connection.Recycle();

return NetEventType.Disconnect;
}
case NetworkEventType.Nothing:
return NetEventType.Nothing;
}

return NetEventType.Nothing;
}

public override void StartClient()
{
SocketConfig config = GetConfig();
// The OS will grab a port
config.DualListenPort = 0;
socket = new RuffleSocket(config);

isConnector = true;
socket.Connect(new IPEndPoint(IPAddress.Parse(ConnectAddress), ConnectPort));
}

public override void StartServer()
{
SocketConfig config = GetConfig();
config.DualListenPort = (ushort)ServerListenPort;

socket = new RuffleSocket(config);
}

public override void DisconnectRemoteClient(ulong clientId)
{
GetRufflesConnectionDetails(clientId, out ulong connectionId);
socket.Disconnect(connections[connectionId], true);
}

public override void DisconnectLocalClient()
{
socket.Disconnect(serverConnection, true);
}

public override ulong GetCurrentRtt(ulong clientId)
{
GetRufflesConnectionDetails(clientId, out ulong connectionId);
return (ulong)connections[connectionId].Roundtrip;
}

public override void Shutdown()
{
channelIdToName.Clear();
channelNameToId.Clear();
connections.Clear();
}

public override void Init()
{
messageBuffer = new byte[MessageBufferSize];
}

public ulong GetMLAPIClientId(ulong connectionId, bool isServer)
{
if (isServer)
{
return 0;
}
else
{
return (ulong)connectionId + 1;
}
}

public void GetRufflesConnectionDetails(ulong clientId, out ulong connectionId)
{
if (clientId == 0)
{
connectionId = serverConnection.Id;
}
else
{
connectionId = (ushort)(clientId - 1);
}
}

private SocketConfig GetConfig()
{
SocketConfig config = new SocketConfig();

int channelCount = MLAPI_CHANNELS.Length + Channels.Count;
config.ChannelTypes = new global::Ruffles.Channeling.ChannelType[channelCount];

for (byte i = 0; i < MLAPI_CHANNELS.Length; i++)
{
config.ChannelTypes[i] = ConvertChannelType(MLAPI_CHANNELS[i].Type);
channelIdToName.Add(i, MLAPI_CHANNELS[i].Name);
channelNameToId.Add(MLAPI_CHANNELS[i].Name, i);
}

for (byte i = (byte)MLAPI_CHANNELS.Length; i < Channels.Count + MLAPI_CHANNELS.Length; i++)
{
config.ChannelTypes[i] = Channels[i].Type;
channelIdToName.Add(i, Channels[i].Name);
channelNameToId.Add(Channels[i].Name, i);
}

return config;
}

private global::Ruffles.Channeling.ChannelType ConvertChannelType(ChannelType type)
{
switch (type)
{
case ChannelType.Reliable:
return global::Ruffles.Channeling.ChannelType.Reliable;
case ChannelType.ReliableFragmentedSequenced:
return global::Ruffles.Channeling.ChannelType.ReliableSequenced;
case ChannelType.ReliableSequenced:
return global::Ruffles.Channeling.ChannelType.ReliableSequenced;
case ChannelType.StateUpdate:
return global::Ruffles.Channeling.ChannelType.Unreliable;
case ChannelType.Unreliable:
return global::Ruffles.Channeling.ChannelType.Unreliable;
}

return global::Ruffles.Channeling.ChannelType.Reliable;
}
}
}
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member

22 changes: 22 additions & 0 deletions MLAPI/Transports/UNET/UnetChannel.cs
@@ -0,0 +1,22 @@
using System;
using UnityEngine.Networking;

namespace MLAPI.Transports
{
/// <summary>
/// A transport channel used by the MLAPI
/// </summary>
[Serializable]
public class UnetChannel
{
/// <summary>
/// The name of the channel
/// </summary>
public string Name;

/// <summary>
/// The type of channel
/// </summary>
public QosType Type;
}
}

0 comments on commit 340da41

Please sign in to comment.