Added first version of MessagePassthrough

This commit is contained in:
Albin Corén 2018-01-10 13:26:20 +01:00
parent 1f14ded9cf
commit a2090443d4
5 changed files with 131 additions and 18 deletions

View File

@ -11,6 +11,8 @@ namespace MLAPI
public ushort ProtocolVersion = 0;
public SortedDictionary<string, QosType> Channels = new SortedDictionary<string, QosType>();
public List<string> MessageTypes = new List<string>();
public List<string> PassthroughMessageTypes = new List<string>();
internal HashSet<ushort> RegisteredPassthroughMessageTypes = new HashSet<ushort>();
public int MessageBufferSize = 65535;
public int MaxMessagesPerFrame = 150;
public int MaxConnections = 100;
@ -26,6 +28,7 @@ namespace MLAPI
//Should only be used for dedicated servers and will require the servers RSA keypair being hard coded into clients in order to exchange a AES key
//TODO
public bool EncryptMessages = false;
public bool AllowPassthroughMessages = true;
//Cached config hash
private byte[] ConfigHash = null;
@ -44,13 +47,20 @@ namespace MLAPI
writer.Write(pair.Key);
writer.Write((int)pair.Value);
}
MessageTypes.Sort();
PassthroughMessageTypes.Sort();
for (int i = 0; i < MessageTypes.Count; i++)
{
writer.Write(MessageTypes[i]);
}
for (int i = 0; i < PassthroughMessageTypes.Count; i++)
{
writer.Write(PassthroughMessageTypes[i]);
}
writer.Write(HandleObjectSpawning);
writer.Write(CompressMessages);
writer.Write(EncryptMessages);
writer.Write(AllowPassthroughMessages);
}
using(SHA256Managed sha256 = new SHA256Managed())
{

View File

@ -126,9 +126,9 @@ namespace MLAPI
protected void SendToLocalClient(string messageType, string channelName, byte[] data)
{
if (!isServer)
if (!isServer && (!NetworkingManager.singleton.NetworkConfig.AllowPassthroughMessages || !NetworkingManager.singleton.NetworkConfig.PassthroughMessageTypes.Contains(messageType)))
{
Debug.LogWarning("MLAPI: Sending messages from client to other clients is not yet supported");
Debug.LogWarning("MLAPI: Invalid Passthrough send. Ensure AllowPassthroughMessages are turned on and that the MessageType " + messageType + " is registered as a passthroughMessageType");
return;
}
NetworkingManager.singleton.Send(ownerClientId, messageType, channelName, data);
@ -136,9 +136,9 @@ namespace MLAPI
protected void SendToLocalClientTarget(string messageType, string channelName, byte[] data)
{
if (!isServer)
if (!isServer && (!NetworkingManager.singleton.NetworkConfig.AllowPassthroughMessages || !NetworkingManager.singleton.NetworkConfig.PassthroughMessageTypes.Contains(messageType)))
{
Debug.LogWarning("MLAPI: Sending messages from client to other clients is not yet supported");
Debug.LogWarning("MLAPI: Invalid Passthrough send. Ensure AllowPassthroughMessages are turned on and that the MessageType " + messageType + " is registered as a passthroughMessageType");
return;
}
NetworkingManager.singleton.Send(ownerClientId, messageType, channelName, data, networkId);
@ -166,9 +166,9 @@ namespace MLAPI
protected void SendToClient(int clientId, string messageType, string channelName, byte[] data)
{
if (!isServer)
if (!isServer && (!NetworkingManager.singleton.NetworkConfig.AllowPassthroughMessages || !NetworkingManager.singleton.NetworkConfig.PassthroughMessageTypes.Contains(messageType)))
{
Debug.LogWarning("MLAPI: Sending messages from client to other clients is not yet supported");
Debug.LogWarning("MLAPI: Invalid Passthrough send. Ensure AllowPassthroughMessages are turned on and that the MessageType " + messageType + " is registered as a passthroughMessageType");
return;
}
NetworkingManager.singleton.Send(clientId, messageType, channelName, data);
@ -176,9 +176,9 @@ namespace MLAPI
protected void SendToClientTarget(int clientId, string messageType, string channelName, byte[] data)
{
if (!isServer)
if (!isServer && (!NetworkingManager.singleton.NetworkConfig.AllowPassthroughMessages || !NetworkingManager.singleton.NetworkConfig.PassthroughMessageTypes.Contains(messageType)))
{
Debug.LogWarning("MLAPI: Sending messages from client to other clients is not yet supported");
Debug.LogWarning("MLAPI: Invalid Passthrough send. Ensure AllowPassthroughMessages are turned on and that the MessageType " + messageType + " is registered as a passthroughMessageType");
return;
}
NetworkingManager.singleton.Send(clientId, messageType, channelName, data, networkId);

View File

@ -67,8 +67,17 @@ namespace MLAPI
MessageManager.messageHandlerCounter = new Dictionary<ushort, int>();
MessageManager.releasedMessageHandlerCounters = new Dictionary<ushort, Stack<int>>();
MessageManager.targetedMessages = new Dictionary<ushort, Dictionary<uint, List<int>>>();
MessageManager.reverseChannels = new Dictionary<int, string>();
MessageManager.reverseMessageTypes = new Dictionary<ushort, string>();
SpawnManager.spawnedObjects = new Dictionary<uint, NetworkedObject>();
SpawnManager.releasedNetworkObjectIds = new Stack<uint>();
if(NetworkConfig.AllowPassthroughMessages)
{
for (int i = 0; i < NetworkConfig.PassthroughMessageTypes.Count; i++)
{
NetworkConfig.RegisteredPassthroughMessageTypes.Add(MessageManager.messageTypes[NetworkConfig.PassthroughMessageTypes[i]]);
}
}
if (NetworkConfig.HandleObjectSpawning)
{
NetworkedObject[] sceneObjects = FindObjectsOfType<NetworkedObject>();
@ -104,11 +113,13 @@ namespace MLAPI
int channelId = cConfig.AddChannel(pair.Value);
MessageManager.channels.Add(pair.Key, channelId);
channelNames.Add(pair.Key);
MessageManager.reverseChannels.Add(channelId, pair.Key);
}
//0-32 are reserved for MLAPI messages
ushort messageId = 32;
for (ushort i = 0; i < NetworkConfig.MessageTypes.Count; i++)
{
MessageManager.reverseMessageTypes.Add(messageId, NetworkConfig.MessageTypes[i]);
MessageManager.messageTypes.Add(NetworkConfig.MessageTypes[i], messageId);
messageId++;
}
@ -289,7 +300,7 @@ namespace MLAPI
}
break;
case NetworkEventType.DataEvent:
HandleIncomingData(clientId, messageBuffer);
HandleIncomingData(clientId, messageBuffer, channelId);
break;
case NetworkEventType.DisconnectEvent:
if(isServer)
@ -319,7 +330,7 @@ namespace MLAPI
}
}
private void HandleIncomingData(int connectonId, byte[] data)
private void HandleIncomingData(int clientId, byte[] data, int channelId)
{
using(MemoryStream readStream = new MemoryStream(data))
{
@ -330,6 +341,16 @@ namespace MLAPI
uint targetNetworkId = 0;
if(targeted)
targetNetworkId = reader.ReadUInt32();
bool isPassthrough = reader.ReadBoolean();
int passthroughOrigin = 0;
int passthroughTarget = 0;
if (isPassthrough && isServer)
passthroughTarget = reader.ReadInt32();
else if (isPassthrough && !isServer)
passthroughOrigin = reader.ReadInt32();
//Client tried to send a network message that was not the connection request before he was accepted.
if (isServer && pendingClients.Contains(clientId) && messageType != 0)
@ -338,8 +359,30 @@ namespace MLAPI
return;
}
ushort bytesToRead = reader.ReadUInt16();
byte[] incommingData = reader.ReadBytes(bytesToRead);
if (isServer && isPassthrough && !NetworkConfig.RegisteredPassthroughMessageTypes.Contains(messageType))
{
Debug.LogWarning("MLAPI: Client " + clientId + " tried to send a passthrough message for a messageType not registered as passthrough");
return;
}
else if(isClient && isPassthrough && !NetworkConfig.RegisteredPassthroughMessageTypes.Contains(messageType))
{
Debug.LogWarning("MLAPI: Server tried to send a passthrough message for a messageType not registered as passthrough");
return;
}
else if(isServer && NetworkConfig.AllowPassthroughMessages && connectedClients.ContainsKey(passthroughTarget))
{
uint? netIdTarget = null;
if (targeted)
netIdTarget = targetNetworkId;
PassthroughSend(passthroughTarget, clientId, messageType, channelId, incommingData, netIdTarget);
return;
}
if (messageType >= 32)
{
//Custom message, invoke all message handlers
@ -348,14 +391,20 @@ namespace MLAPI
List<int> handlerIds = MessageManager.targetedMessages[messageType][targetNetworkId];
for (int i = 0; i < handlerIds.Count; i++)
{
MessageManager.messageCallbacks[messageType][handlerIds[i]](clientId, incommingData);
if (isPassthrough)
MessageManager.messageCallbacks[messageType][handlerIds[i]](passthroughOrigin, incommingData);
else
MessageManager.messageCallbacks[messageType][handlerIds[i]](clientId, incommingData);
}
}
else
{
foreach (KeyValuePair<int, Action<int, byte[]>> pair in MessageManager.messageCallbacks[messageType])
{
pair.Value(clientId, incommingData);
if (isPassthrough)
pair.Value(passthroughOrigin, incommingData);
else
pair.Value(clientId, incommingData);
}
}
}
@ -500,6 +549,40 @@ namespace MLAPI
}
}
internal void PassthroughSend(int targetId, int sourceId, ushort messageType, int channelId, byte[] data, uint? networkId = null)
{
if (isHost && targetId == -1)
{
//Host trying to send data to it's own client
if (networkId == null)
MessageManager.InvokeMessageHandlers(MessageManager.reverseMessageTypes[messageType], data, sourceId);
else
MessageManager.InvokeTargetedMessageHandler(MessageManager.reverseMessageTypes[messageType], data, sourceId, networkId.Value);
return;
}
int sizeOfStream = 10;
if (networkId != null)
sizeOfStream += 4;
sizeOfStream += data.Length;
using (MemoryStream stream = new MemoryStream(sizeOfStream))
{
using (BinaryWriter writer = new BinaryWriter(stream))
{
writer.Write(messageType);
writer.Write(networkId != null);
if (networkId != null)
writer.Write(networkId.Value);
writer.Write(true);
writer.Write(sourceId);
writer.Write((ushort)data.Length);
writer.Write(data);
}
NetworkTransport.Send(hostId, targetId, channelId, stream.GetBuffer(), sizeOfStream, out error);
}
}
internal void Send(int clientId, string messageType, string channelName, byte[] data, uint? networkId = null)
{
if(isHost && clientId == -1)
@ -516,10 +599,19 @@ namespace MLAPI
//Client trying to send data to host
clientId = serverClientId;
}
//2 bytes for messageType, 2 bytes for buffer length and one byte for target bool
int sizeOfStream = 5;
bool isPassthrough = (!isServer && clientId != serverClientId && NetworkConfig.AllowPassthroughMessages);
if (isPassthrough && !NetworkConfig.RegisteredPassthroughMessageTypes.Contains(MessageManager.messageTypes[messageType]))
{
Debug.LogWarning("MLAPI: The The MessageType " + messageType + " is not registered as an allowed passthrough message type.");
return;
}
int sizeOfStream = 6;
if (networkId != null)
sizeOfStream += 4;
if (isPassthrough)
sizeOfStream += 4;
sizeOfStream += data.Length;
using (MemoryStream stream = new MemoryStream(sizeOfStream))
@ -530,17 +622,21 @@ namespace MLAPI
writer.Write(networkId != null);
if (networkId != null)
writer.Write(networkId.Value);
writer.Write(isPassthrough);
if (isPassthrough)
writer.Write(clientId);
writer.Write((ushort)data.Length);
writer.Write(data);
}
if (isPassthrough)
clientId = serverClientId;
NetworkTransport.Send(hostId, clientId, MessageManager.channels[channelName], stream.GetBuffer(), sizeOfStream, out error);
}
}
internal void Send(int[] clientIds, string messageType, string channelName, byte[] data, uint? networkId = null)
{
//2 bytes for messageType, 2 bytes for buffer length and one byte for target bool
int sizeOfStream = 5;
int sizeOfStream = 6;
if (networkId != null)
sizeOfStream += 4;
sizeOfStream += data.Length;
@ -553,6 +649,7 @@ namespace MLAPI
writer.Write(networkId != null);
if (networkId != null)
writer.Write(networkId.Value);
writer.Write(false);
writer.Write((ushort)data.Length);
writer.Write(data);
}
@ -581,7 +678,7 @@ namespace MLAPI
internal void Send(List<int> clientIds, string messageType, string channelName, byte[] data, uint? networkId = null)
{
//2 bytes for messageType, 2 bytes for buffer length and one byte for target bool
int sizeOfStream = 5;
int sizeOfStream = 6;
if (networkId != null)
sizeOfStream += 4;
sizeOfStream += data.Length;
@ -594,6 +691,7 @@ namespace MLAPI
writer.Write(networkId != null);
if (networkId != null)
writer.Write(networkId.Value);
writer.Write(false);
writer.Write((ushort)data.Length);
writer.Write(data);
}
@ -622,7 +720,7 @@ namespace MLAPI
internal void Send(string messageType, string channelName, byte[] data, uint? networkId = null)
{
//2 bytes for messageType, 2 bytes for buffer length and one byte for target bool
int sizeOfStream = 5;
int sizeOfStream = 6;
if (networkId != null)
sizeOfStream += 4;
sizeOfStream += data.Length;
@ -635,6 +733,7 @@ namespace MLAPI
writer.Write(networkId != null);
if (networkId != null)
writer.Write(networkId.Value);
writer.Write(false);
writer.Write((ushort)data.Length);
writer.Write(data);
}
@ -677,6 +776,7 @@ namespace MLAPI
writer.Write(networkId != null);
if (networkId != null)
writer.Write(networkId.Value);
writer.Write(false);
writer.Write((ushort)data.Length);
writer.Write(data);
}

View File

@ -7,7 +7,9 @@ namespace MLAPI.NetworkingManagerComponents
internal static class MessageManager
{
internal static Dictionary<string, int> channels;
internal static Dictionary<int, string> reverseChannels;
internal static Dictionary<string, ushort> messageTypes;
internal static Dictionary<ushort, string> reverseMessageTypes;
internal static Dictionary<ushort, Dictionary<int, Action<int, byte[]>>> messageCallbacks;
internal static Dictionary<ushort, int> messageHandlerCounter;
internal static Dictionary<ushort, Stack<int>> releasedMessageHandlerCounters;

View File

@ -25,6 +25,7 @@ It's licenced under the MIT licence :D
* ProtocolVersion to allow making different versions not talk to each other. (done)
* NetworkedBehaviours does not have to be on the root, it's simply just a class that implements the send methods etc. (done)
* Multiple messages processed every frame with the ability to specify a maximum to prevent freezes in the normal game logic (done)
* Passthrough messages (check the wiki for details)
That's all I can think of right now. But there is more to come, especially if people show intrest in the project.