Send order queue length in ping responses.

This commit is contained in:
Paul Chote
2021-09-25 15:31:04 +01:00
committed by abcdefg30
parent 2d08f2bbfd
commit defaf92752
6 changed files with 30 additions and 17 deletions

View File

@@ -304,12 +304,11 @@ namespace OpenRA.Network
orderManager.ReceiveDisconnect(disconnect.ClientId, disconnect.Frame); orderManager.ReceiveDisconnect(disconnect.ClientId, disconnect.Frame);
else if (OrderIO.TryParseSync(p.Data, out var sync)) else if (OrderIO.TryParseSync(p.Data, out var sync))
orderManager.ReceiveSync(sync); orderManager.ReceiveSync(sync);
else if (OrderIO.TryParsePing(p.FromClient, p.Data, out var ping)) else if (OrderIO.TryParsePingRequest(p, out var timestamp))
{ {
// The Ping packet is sent back directly without changes
// Note that processing this here, rather than in NetworkConnectionReceive, // Note that processing this here, rather than in NetworkConnectionReceive,
// so that poor world tick performance can be reflected in the latency measurement // so that poor world tick performance can be reflected in the latency measurement
Send(ping); Send(OrderIO.SerializePingResponse(timestamp, (byte)orderManager.OrderQueueLength));
record = false; record = false;
} }
else if (OrderIO.TryParseAck(p, out var ackFrame, out var ackCount)) else if (OrderIO.TryParseAck(p, out var ackFrame, out var ackCount))

View File

@@ -93,6 +93,16 @@ namespace OpenRA.Network
return ms.GetBuffer(); return ms.GetBuffer();
} }
public static byte[] SerializePingResponse(long timestamp, byte queueLength)
{
var ms = new MemoryStream(14);
ms.WriteArray(BitConverter.GetBytes(0));
ms.WriteByte((byte)OrderType.Ping);
ms.WriteArray(BitConverter.GetBytes(timestamp));
ms.WriteByte(queueLength);
return ms.GetBuffer();
}
public static bool TryParseDisconnect((int FromClient, byte[] Data) packet, out (int Frame, int ClientId) disconnect) public static bool TryParseDisconnect((int FromClient, byte[] Data) packet, out (int Frame, int ClientId) disconnect)
{ {
// Valid Disconnect packets are only ever generated by the server // Valid Disconnect packets are only ever generated by the server
@@ -123,24 +133,24 @@ namespace OpenRA.Network
return true; return true;
} }
public static bool TryParsePing(int fromClient, byte[] packet, out byte[] ping) public static bool TryParsePingRequest((int FromClient, byte[] Data) packet, out long timestamp)
{ {
// Valid Ping packets are only ever generated by the server // Valid Ping requests are only ever generated by the server
if (fromClient != 0 || packet.Length != 13 || packet[4] != (byte)OrderType.Ping) if (packet.FromClient != 0 || packet.Data.Length != 13 || packet.Data[4] != (byte)OrderType.Ping)
{ {
ping = null; timestamp = 0;
return false; return false;
} }
// Valid Ping packets always have frame 0 // Valid Ping packets always have frame 0
var frame = BitConverter.ToInt32(packet, 0); var frame = BitConverter.ToInt32(packet.Data, 0);
if (frame != 0) if (frame != 0)
{ {
ping = null; timestamp = 0;
return false; return false;
} }
ping = packet; timestamp = BitConverter.ToInt64(packet.Data, 5);
return true; return true;
} }

View File

@@ -29,6 +29,7 @@ namespace OpenRA.Network
public Session LobbyInfo = new Session(); public Session LobbyInfo = new Session();
public Session.Client LocalClient => LobbyInfo.ClientWithIndex(Connection.LocalClientId); public Session.Client LocalClient => LobbyInfo.ClientWithIndex(Connection.LocalClientId);
public World World; public World World;
public int OrderQueueLength => pendingOrders.Count > 0 ? pendingOrders.Min(q => q.Value.Count) : 0;
public string ServerError = null; public string ServerError = null;
public bool AuthenticationFailed = false; public bool AuthenticationFailed = false;

View File

@@ -128,13 +128,13 @@ namespace OpenRA.Server
{ {
// Ping packets are sent and processed internally within this thread to reduce // Ping packets are sent and processed internally within this thread to reduce
// server-introduced latencies from polling loops // server-introduced latencies from polling loops
if (expectLength == 9 && bytes[0] == (byte)OrderType.Ping) if (expectLength == 10 && bytes[0] == (byte)OrderType.Ping)
{ {
if (pingHistory.Count == MaxPingSamples) if (pingHistory.Count == MaxPingSamples)
pingHistory.Dequeue(); pingHistory.Dequeue();
pingHistory.Enqueue((int)(Game.RunTime - BitConverter.ToInt64(bytes, 1))); pingHistory.Enqueue((int)(Game.RunTime - BitConverter.ToInt64(bytes, 1)));
server.OnConnectionPing(this, pingHistory.ToArray()); server.OnConnectionPing(this, pingHistory.ToArray(), bytes[9]);
} }
else else
server.OnConnectionPacket(this, frame, bytes); server.OnConnectionPacket(this, frame, bytes);

View File

@@ -41,6 +41,7 @@ namespace OpenRA.Server
// - byte containing the number of sent order packets to apply // - byte containing the number of sent order packets to apply
// - 0x20: Ping // - 0x20: Ping
// - Int64 containing the server timestamp when the ping was generated // - Int64 containing the server timestamp when the ping was generated
// - [client -> server only] byte containing the number of frames ready to simulate
// //
// A connection handshake begins when a client opens a connection to the server: // A connection handshake begins when a client opens a connection to the server:
// - Server sends: // - Server sends:

View File

@@ -323,9 +323,9 @@ namespace OpenRA.Server
events.Add(new ConnectionPacketEvent(conn, frame, data)); events.Add(new ConnectionPacketEvent(conn, frame, data));
} }
internal void OnConnectionPing(Connection conn, int[] pingHistory) internal void OnConnectionPing(Connection conn, int[] pingHistory, byte queueLength)
{ {
events.Add(new ConnectionPingEvent(conn, pingHistory)); events.Add(new ConnectionPingEvent(conn, pingHistory, queueLength));
} }
internal void OnConnectionDisconnect(Connection conn) internal void OnConnectionDisconnect(Connection conn)
@@ -1021,7 +1021,7 @@ namespace OpenRA.Server
} }
} }
public void ReceivePing(Connection conn, int[] pingHistory) public void ReceivePing(Connection conn, int[] pingHistory, byte queueLength)
{ {
// Levels set relative to the default order lag of 3 net ticks (360ms) // Levels set relative to the default order lag of 3 net ticks (360ms)
// TODO: Adjust this once dynamic lag is implemented // TODO: Adjust this once dynamic lag is implemented
@@ -1367,16 +1367,18 @@ namespace OpenRA.Server
{ {
readonly Connection connection; readonly Connection connection;
readonly int[] pingHistory; readonly int[] pingHistory;
readonly byte queueLength;
public ConnectionPingEvent(Connection connection, int[] pingHistory) public ConnectionPingEvent(Connection connection, int[] pingHistory, byte queueLength)
{ {
this.connection = connection; this.connection = connection;
this.pingHistory = pingHistory; this.pingHistory = pingHistory;
this.queueLength = queueLength;
} }
void IServerEvent.Invoke(Server server) void IServerEvent.Invoke(Server server)
{ {
server.ReceivePing(connection, pingHistory); server.ReceivePing(connection, pingHistory, queueLength);
} }
} }