Get rid of unnecessary allocations in receiving packets.

This reduces pressure on the GC for when many players are connected.
This commit is contained in:
UnknownShadow200 2017-07-28 12:01:10 +10:00
parent 2e1ce9f8f5
commit e0875e0924
4 changed files with 36 additions and 30 deletions

View File

@ -33,7 +33,6 @@ namespace MCGalaxy.Commands.Eco {
Item item = Economy.GetItem(parts[0]);
if (item == null) { Help(p); return; }
if (!item.Enabled) {
Player.Message(p, "%cThe {0} item is not currently buyable.", item.Name); return;
}

View File

@ -22,7 +22,7 @@ namespace MCGalaxy.Events.PlayerEvents {
public delegate void OnPlayerChat(Player p, string message);
/// <summary> Called whenever a player chats on the server. </summary>
/// <remarks> You must cancel this event to prevent the message being sent to the user. </remarks>
/// <remarks> You must cancel this event to prevent the message being sent to the user (and others). </remarks>
public sealed class OnPlayerChatEvent : IEvent<OnPlayerChat> {
public static void Call(Player p, string message) {

View File

@ -22,8 +22,10 @@ namespace MCGalaxy.Network {
public sealed class TcpSocket : INetworkSocket {
readonly Player player;
readonly Socket socket;
byte[] unprocessed = new byte[0];
byte[] unprocessed = new byte[352];
byte[] recvBuffer = new byte[256];
int unprocessedLen;
public TcpSocket(Player p, Socket s) {
player = p; socket = s;
@ -48,19 +50,25 @@ namespace MCGalaxy.Network {
if (p.disconnected) return;
try {
int length = s.socket.EndReceive(result);
if (length == 0) { p.Disconnect(); return; }
int recvLen = s.socket.EndReceive(result);
if (recvLen == 0) { p.Disconnect(); return; }
byte[] allData = new byte[s.unprocessed.Length + length];
Buffer.BlockCopy(s.unprocessed, 0, allData, 0, s.unprocessed.Length);
Buffer.BlockCopy(s.recvBuffer, 0, allData, s.unprocessed.Length, length);
s.unprocessed = p.ProcessReceived(allData);
// Packets may not always be fully received in a Receive call
// As such, we may need to retain a little bit of partial packet data
Buffer.BlockCopy(s.recvBuffer, 0, s.unprocessed, s.unprocessedLen, recvLen);
s.unprocessedLen += recvLen;
int processedLen = p.ProcessReceived(s.unprocessed, s.unprocessedLen);
if (p.nonPlayerClient && s.unprocessed.Length == 0) {
s.Close();
p.disconnected = true;
return;
// Disconnect invalid clients
if (p.nonPlayerClient && processedLen == -1) { s.Close(); p.disconnected = true; }
if (processedLen == -1) return;
// move remaining partial packet data back to start of unprocessed buffer
for (int i = processedLen; i < s.unprocessedLen; i++) {
s.unprocessed[i - processedLen] = s.unprocessed[i];
}
s.unprocessedLen -= processedLen;
if (!p.disconnected) s.ReceiveNextAsync();
} catch (SocketException) {
p.Disconnect();

View File

@ -185,28 +185,27 @@ namespace MCGalaxy {
return block == Block.Air || (block >= Block.Water && block <= Block.StillLava);
}
internal byte[] ProcessReceived(byte[] buffer) {
internal int ProcessReceived(byte[] buffer, int bufferLen) {
int processedLen = 0;
try {
int size = PacketSize(buffer);
if (size == -2) return new byte[1]; // WoM get request
if (size == -1) return new byte[0]; // invalid packet
if (buffer.Length < size) return buffer;
HandlePacket(buffer, 0);
if (buffer.Length == size) return new byte[0];
byte[] remaining = new byte[buffer.Length - size];
Buffer.BlockCopy(buffer, size, remaining, 0, remaining.Length);
return ProcessReceived(remaining);
while (processedLen < bufferLen) {
int packetLen = PacketSize(buffer[processedLen]);
if (packetLen == -1) return -1;
// Partial packet data received
if (processedLen + packetLen > bufferLen) return processedLen;
HandlePacket(buffer, processedLen);
processedLen += packetLen;
}
} catch (Exception ex) {
Logger.LogError(ex);
}
return buffer;
return processedLen;
}
int PacketSize(byte[] buffer) {
switch (buffer[0]) {
case (byte)'G': return -2; //For wom
int PacketSize(byte opcode) {
switch (opcode) {
case (byte)'G': return -1; // HTTP GET, ignore it
case Opcode.Handshake: return 131;
case Opcode.SetBlockClient:
if (!loggedIn) goto default;
@ -226,7 +225,7 @@ namespace MCGalaxy {
default:
if (!nonPlayerClient) {
string msg = "Unhandled message id \"" + buffer[0] + "\"!";
string msg = "Unhandled message id \"" + opcode + "\"!";
Leave(msg, msg, true);
}
return -1;