Rework master server ping rate-limit logic.
Pings are now delayed instead of dropped to avoid data loss.
This commit is contained in:
@@ -11,9 +11,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using BeaconLib;
|
using BeaconLib;
|
||||||
using OpenRA.Network;
|
using OpenRA.Network;
|
||||||
@@ -24,8 +22,12 @@ namespace OpenRA.Mods.Common.Server
|
|||||||
{
|
{
|
||||||
public class MasterServerPinger : ServerTrait, ITick, INotifyServerStart, INotifySyncLobbyInfo, IStartGame, IEndGame
|
public class MasterServerPinger : ServerTrait, ITick, INotifyServerStart, INotifySyncLobbyInfo, IStartGame, IEndGame
|
||||||
{
|
{
|
||||||
// 3 minutes. Server has a 5 minute TTL for games, so give ourselves a bit of leeway.
|
// 3 minutes (in milliseconds). Server has a 5 minute TTL for games, so give ourselves a bit of leeway.
|
||||||
const int MasterPingInterval = 60 * 3;
|
const int MasterPingInterval = 60 * 3 * 1000;
|
||||||
|
|
||||||
|
// 1 second (in milliseconds) minimum delay between pings
|
||||||
|
const int RateLimitInterval = 1000;
|
||||||
|
|
||||||
static readonly Beacon LanGameBeacon;
|
static readonly Beacon LanGameBeacon;
|
||||||
static readonly Dictionary<int, string> MasterServerErrors = new Dictionary<int, string>()
|
static readonly Dictionary<int, string> MasterServerErrors = new Dictionary<int, string>()
|
||||||
{
|
{
|
||||||
@@ -34,6 +36,7 @@ namespace OpenRA.Mods.Common.Server
|
|||||||
};
|
};
|
||||||
|
|
||||||
long lastPing = 0;
|
long lastPing = 0;
|
||||||
|
long lastChanged = 0;
|
||||||
bool isInitialPing = true;
|
bool isInitialPing = true;
|
||||||
|
|
||||||
volatile bool isBusy;
|
volatile bool isBusy;
|
||||||
@@ -53,9 +56,25 @@ namespace OpenRA.Mods.Common.Server
|
|||||||
|
|
||||||
public void Tick(S server)
|
public void Tick(S server)
|
||||||
{
|
{
|
||||||
if ((Game.RunTime - lastPing > MasterPingInterval * 1000) || isInitialPing)
|
// Force an update if the last one was too long ago so the advertisement doesn't time out
|
||||||
PublishGame(server);
|
if (Game.RunTime - lastChanged > MasterPingInterval)
|
||||||
else
|
lastChanged = Game.RunTime;
|
||||||
|
|
||||||
|
// Update the master server and LAN clients if something has changed
|
||||||
|
// Note that isBusy is set while the master server ping is running on a
|
||||||
|
// background thread, and limits LAN pings as well as master server pings for simplicity.
|
||||||
|
if (!isBusy && ((lastChanged > lastPing && Game.RunTime - lastPing > RateLimitInterval) || isInitialPing))
|
||||||
|
{
|
||||||
|
var gs = new GameServer(server);
|
||||||
|
if (server.Settings.AdvertiseOnline)
|
||||||
|
UpdateMasterServer(server, gs.ToPOSTData(false));
|
||||||
|
|
||||||
|
if (LanGameBeacon != null)
|
||||||
|
LanGameBeacon.BeaconData = gs.ToPOSTData(true);
|
||||||
|
|
||||||
|
lastPing = Game.RunTime;
|
||||||
|
}
|
||||||
|
|
||||||
lock (masterServerMessages)
|
lock (masterServerMessages)
|
||||||
while (masterServerMessages.Count > 0)
|
while (masterServerMessages.Count > 0)
|
||||||
server.SendMessage(masterServerMessages.Dequeue());
|
server.SendMessage(masterServerMessages.Dequeue());
|
||||||
@@ -69,12 +88,12 @@ namespace OpenRA.Mods.Common.Server
|
|||||||
|
|
||||||
public void LobbyInfoSynced(S server)
|
public void LobbyInfoSynced(S server)
|
||||||
{
|
{
|
||||||
PublishGame(server);
|
lastChanged = Game.RunTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GameStarted(S server)
|
public void GameStarted(S server)
|
||||||
{
|
{
|
||||||
PublishGame(server);
|
lastChanged = Game.RunTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GameEnded(S server)
|
public void GameEnded(S server)
|
||||||
@@ -82,24 +101,11 @@ namespace OpenRA.Mods.Common.Server
|
|||||||
if (LanGameBeacon != null)
|
if (LanGameBeacon != null)
|
||||||
LanGameBeacon.Stop();
|
LanGameBeacon.Stop();
|
||||||
|
|
||||||
PublishGame(server);
|
lastChanged = Game.RunTime;
|
||||||
}
|
|
||||||
|
|
||||||
void PublishGame(S server)
|
|
||||||
{
|
|
||||||
// Cache the server info on the main thread to ensure data consistency
|
|
||||||
var gs = new GameServer(server);
|
|
||||||
|
|
||||||
if (!isBusy && server.Settings.AdvertiseOnline)
|
|
||||||
UpdateMasterServer(server, gs.ToPOSTData(false));
|
|
||||||
|
|
||||||
if (LanGameBeacon != null)
|
|
||||||
LanGameBeacon.BeaconData = gs.ToPOSTData(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateMasterServer(S server, string postData)
|
void UpdateMasterServer(S server, string postData)
|
||||||
{
|
{
|
||||||
lastPing = Game.RunTime;
|
|
||||||
isBusy = true;
|
isBusy = true;
|
||||||
|
|
||||||
Action a = () =>
|
Action a = () =>
|
||||||
|
|||||||
Reference in New Issue
Block a user