From 70e862e92f522f5af458aba533cf16679f20dd09 Mon Sep 17 00:00:00 2001 From: Regalis Date: Thu, 1 Jun 2017 22:07:01 +0300 Subject: [PATCH] - both clients and server limit the number of chat messages written per packet - added an error message if MTU is exceeded - if the server disconnects a client while reading a message from them, the rest of the message is ignored --- Subsurface/Source/Networking/GameClient.cs | 29 ++++++++++++-------- Subsurface/Source/Networking/GameServer.cs | 31 +++++++++++++++++----- 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/Subsurface/Source/Networking/GameClient.cs b/Subsurface/Source/Networking/GameClient.cs index 5d123786a..0f35ba280 100644 --- a/Subsurface/Source/Networking/GameClient.cs +++ b/Subsurface/Source/Networking/GameClient.cs @@ -958,12 +958,17 @@ namespace Barotrauma.Networking outmsg.Write(ChatMessage.LastID); chatMsgQueue.RemoveAll(cMsg => !NetIdUtils.IdMoreRecent(cMsg.NetStateID, lastSentChatMsgID)); - - foreach (ChatMessage cMsg in chatMsgQueue) + for (int i = 0; i < chatMsgQueue.Count && i < ChatMessage.MaxMessagesPerPacket; i++) { - cMsg.ClientWrite(outmsg); + chatMsgQueue[i].ClientWrite(outmsg); } outmsg.Write((byte)ClientNetObject.END_OF_MESSAGE); + + if (outmsg.LengthBytes > client.Configuration.MaximumTransmissionUnit) + { + DebugConsole.ThrowError("Maximum packet size exceeded (" + outmsg.LengthBytes + " > " + client.Configuration.MaximumTransmissionUnit); + } + client.SendMessage(outmsg, NetDeliveryMethod.Unreliable); } @@ -978,20 +983,22 @@ namespace Barotrauma.Networking outmsg.Write(entityEventManager.LastReceivedID); chatMsgQueue.RemoveAll(cMsg => !NetIdUtils.IdMoreRecent(cMsg.NetStateID, lastSentChatMsgID)); - - foreach (ChatMessage cMsg in chatMsgQueue) + for (int i = 0; i < chatMsgQueue.Count && i < ChatMessage.MaxMessagesPerPacket; i++) { - cMsg.ClientWrite(outmsg); - } - - if (Character.Controlled != null) - { - Character.Controlled.ClientWrite(outmsg); + chatMsgQueue[i].ClientWrite(outmsg); } + + Character.Controlled?.ClientWrite(outmsg); entityEventManager.Write(outmsg, client.ServerConnection); outmsg.Write((byte)ClientNetObject.END_OF_MESSAGE); + + if (outmsg.LengthBytes > client.Configuration.MaximumTransmissionUnit) + { + DebugConsole.ThrowError("Maximum packet size exceeded (" + outmsg.LengthBytes + " > " + client.Configuration.MaximumTransmissionUnit); + } + client.SendMessage(outmsg, NetDeliveryMethod.Unreliable); } diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index d84098147..bb57df447 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -652,8 +652,10 @@ namespace Barotrauma.Networking break; default: return; - //break; } + + //don't read further messages if the client has been disconnected (kicked due to spam for example) + if (!connectedClients.Contains(c)) break; } } @@ -752,6 +754,9 @@ namespace Barotrauma.Networking default: return; } + + //don't read further messages if the client has been disconnected (kicked due to spam for example) + if (!connectedClients.Contains(c)) break; } } @@ -846,9 +851,8 @@ namespace Barotrauma.Networking outmsg.Write(c.lastSentEntityEventID); c.chatMsgQueue.RemoveAll(cMsg => !NetIdUtils.IdMoreRecent(cMsg.NetStateID, c.lastRecvChatMsgID)); - - int maxChatMsgsPerPacket = 50; - for (int i = 0; i < c.chatMsgQueue.Count && i < maxChatMsgsPerPacket; i++) + + for (int i = 0; i < c.chatMsgQueue.Count && i < ChatMessage.MaxMessagesPerPacket; i++) { c.chatMsgQueue[i].ServerWrite(outmsg, c); } @@ -897,6 +901,12 @@ namespace Barotrauma.Networking entityEventManager.Write(c, outmsg); outmsg.Write((byte)ServerNetObject.END_OF_MESSAGE); + + if (outmsg.LengthBytes > config.MaximumTransmissionUnit) + { + DebugConsole.ThrowError("Maximum packet size exceeded (" + outmsg.LengthBytes + " > " + config.MaximumTransmissionUnit); + } + server.SendMessage(outmsg, c.Connection, NetDeliveryMethod.Unreliable); } @@ -959,12 +969,19 @@ namespace Barotrauma.Networking outmsg.Write(c.lastSentChatMsgID); //send this to client so they know which chat messages weren't received by the server c.chatMsgQueue.RemoveAll(cMsg => !NetIdUtils.IdMoreRecent(cMsg.NetStateID, c.lastRecvChatMsgID)); - foreach (ChatMessage cMsg in c.chatMsgQueue) + + for (int i = 0; i < c.chatMsgQueue.Count && i < ChatMessage.MaxMessagesPerPacket; i++) { - cMsg.ServerWrite(outmsg, c); - } + c.chatMsgQueue[i].ServerWrite(outmsg, c); + } outmsg.Write((byte)ServerNetObject.END_OF_MESSAGE); + + if (outmsg.LengthBytes > config.MaximumTransmissionUnit) + { + DebugConsole.ThrowError("Maximum packet size exceeded (" + outmsg.LengthBytes + " > " + config.MaximumTransmissionUnit); + } + server.SendMessage(outmsg, c.Connection, NetDeliveryMethod.Unreliable); }