Codechange: [Network] replace _realtime_tick with std::chrono

(cherry picked from commit 53c28a8ec9)
pull/221/head
Patric Stout 3 years ago committed by Jonathan G Rennison
parent 729df75d3e
commit d4f208d9c1

@ -25,9 +25,10 @@
* @param s The socket to connect with.
*/
NetworkGameSocketHandler::NetworkGameSocketHandler(SOCKET s) : info(nullptr), client_id(INVALID_CLIENT_ID),
last_frame(_frame_counter), last_frame_server(_frame_counter), last_packet(_realtime_tick)
last_frame(_frame_counter), last_frame_server(_frame_counter)
{
this->sock = s;
this->last_packet = std::chrono::steady_clock::now();
}
/**
@ -65,7 +66,7 @@ NetworkRecvStatus NetworkGameSocketHandler::HandlePacket(Packet *p)
{
PacketGameType type = (PacketGameType)p->Recv_uint8();
this->last_packet = _realtime_tick;
this->last_packet = std::chrono::steady_clock::now();
switch (this->HasClientQuit() ? PACKET_END : type) {
case PACKET_SERVER_FULL: return this->Receive_SERVER_FULL(p);

@ -17,6 +17,7 @@
#include "../network_type.h"
#include "../../core/pool_type.hpp"
#include <memory>
#include <chrono>
/**
* Enum with all types of TCP packets.
@ -544,7 +545,7 @@ public:
uint32 last_frame; ///< Last frame we have executed
uint32 last_frame_server; ///< Last frame the server has executed
CommandQueue incoming_queue; ///< The command-queue awaiting handling
uint last_packet; ///< Time we received the last frame.
std::chrono::steady_clock::time_point last_packet; ///< Time we received the last frame.
NetworkRecvStatus CloseConnection(bool error = true) override;

@ -37,7 +37,7 @@ NetworkAdminSocketPool _networkadminsocket_pool("NetworkAdminSocket");
INSTANTIATE_POOL_METHODS(NetworkAdminSocket)
/** The timeout for authorisation of the client. */
static const int ADMIN_AUTHORISATION_TIMEOUT = 10000;
static const std::chrono::seconds ADMIN_AUTHORISATION_TIMEOUT(10);
/** Frequencies, which may be registered for a certain update type. */
@ -64,7 +64,7 @@ ServerNetworkAdminSocketHandler::ServerNetworkAdminSocketHandler(SOCKET s) : Net
{
_network_admins_connected++;
this->status = ADMIN_STATUS_INACTIVE;
this->realtime_connect = _realtime_tick;
this->connect_time = std::chrono::steady_clock::now();
}
/**
@ -95,8 +95,8 @@ ServerNetworkAdminSocketHandler::~ServerNetworkAdminSocketHandler()
/* static */ void ServerNetworkAdminSocketHandler::Send()
{
for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::Iterate()) {
if (as->status == ADMIN_STATUS_INACTIVE && as->realtime_connect + ADMIN_AUTHORISATION_TIMEOUT < _realtime_tick) {
DEBUG(net, 1, "[admin] Admin did not send its authorisation within %d seconds", ADMIN_AUTHORISATION_TIMEOUT / 1000);
if (as->status == ADMIN_STATUS_INACTIVE && std::chrono::steady_clock::now() > as->connect_time + ADMIN_AUTHORISATION_TIMEOUT) {
DEBUG(net, 1, "[admin] Admin did not send its authorisation within %d seconds", (uint32)std::chrono::duration_cast<std::chrono::seconds>(ADMIN_AUTHORISATION_TIMEOUT).count());
as->CloseConnection(true);
continue;
}

@ -37,7 +37,7 @@ protected:
NetworkRecvStatus SendPong(uint32 d1);
public:
AdminUpdateFrequency update_frequency[ADMIN_UPDATE_END]; ///< Admin requested update intervals.
uint32 realtime_connect; ///< Time of connection.
std::chrono::steady_clock::time_point connect_time; ///< Time of connection.
NetworkAddress address; ///< Address of the admin.
ServerNetworkAdminSocketHandler(SOCKET s);

@ -40,7 +40,7 @@ static const uint NETWORK_CHAT_LINE_SPACING = 3;
struct ChatMessage {
char message[DRAW_STRING_BUFFER]; ///< The action message.
TextColour colour; ///< The colour of the message.
uint32 remove_time; ///< The time to remove the message.
std::chrono::steady_clock::time_point remove_time; ///< The time to remove the message.
};
/* used for chat window */
@ -97,7 +97,7 @@ void CDECL NetworkAddChatMessage(TextColour colour, uint duration, const char *m
ChatMessage *cmsg = &_chatmsg_list[msg_count++];
strecpy(cmsg->message, buf, lastof(cmsg->message));
cmsg->colour = (colour & TC_IS_PALETTE_COLOUR) ? colour : TC_WHITE;
cmsg->remove_time = _realtime_tick + duration * 1000;
cmsg->remove_time = std::chrono::steady_clock::now() + std::chrono::seconds(duration);
_chatmessage_dirty = true;
}
@ -180,7 +180,7 @@ void NetworkChatMessageLoop()
if (cmsg->message[0] == '\0') continue;
/* Message has expired, remove from the list */
if (cmsg->remove_time < _realtime_tick) {
if (std::chrono::steady_clock::now() > cmsg->remove_time) {
/* Move the remaining messages over the current message */
if (i != MAX_CHAT_MESSAGES - 1) memmove(cmsg, cmsg + 1, sizeof(*cmsg) * (MAX_CHAT_MESSAGES - i - 1));

@ -978,7 +978,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DONE(Packet
bool load_success = SafeLoad({}, SLO_LOAD, DFT_GAME_FILE, GM_NORMAL, NO_DIRECTORY, lf);
/* Long savegame loads shouldn't affect the lag calculation! */
this->last_packet = _realtime_tick;
this->last_packet = std::chrono::steady_clock::now();
if (!load_success) {
DeleteWindowById(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
@ -1312,27 +1312,23 @@ void ClientNetworkGameSocketHandler::CheckConnection()
/* Only once we're authorized we can expect a steady stream of packets. */
if (this->status < STATUS_AUTHORIZED) return;
/* It might... sometimes occur that the realtime ticker overflows. */
if (_realtime_tick < this->last_packet) this->last_packet = _realtime_tick;
/* Lag is in milliseconds; 5 seconds are roughly twice the
* server's "you're slow" threshold (1 game day). */
uint lag = (_realtime_tick - this->last_packet) / 1000;
if (lag < 5) return;
/* 5 seconds are roughly twice the server's "you're slow" threshold (1 game day). */
std::chrono::steady_clock::duration lag = std::chrono::steady_clock::now() - this->last_packet;
if (lag < std::chrono::seconds(5)) return;
/* 20 seconds are (way) more than 4 game days after which
* the server will forcefully disconnect you. */
if (lag > 20) {
if (lag > std::chrono::seconds(20)) {
this->NetworkGameSocketHandler::CloseConnection();
return;
}
/* Prevent showing the lag message every tick; just update it when needed. */
static uint last_lag = 0;
if (last_lag == lag) return;
static std::chrono::steady_clock::duration last_lag = {};
if (std::chrono::duration_cast<std::chrono::seconds>(last_lag) == std::chrono::duration_cast<std::chrono::seconds>(lag)) return;
last_lag = lag;
SetDParam(0, lag);
SetDParam(0, std::chrono::duration_cast<std::chrono::seconds>(lag).count());
ShowErrorMessage(STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION_CAPTION, STR_NETWORK_ERROR_CLIENT_GUI_LOST_CONNECTION, WL_INFO);
}

@ -718,9 +718,9 @@ ClientNetworkContentSocketHandler::ClientNetworkContentSocketHandler() :
http_response_index(-2),
curFile(nullptr),
curInfo(nullptr),
isConnecting(false),
lastActivity(_realtime_tick)
isConnecting(false)
{
this->lastActivity = std::chrono::steady_clock::now();
}
/** Clear up the mess ;) */
@ -750,7 +750,7 @@ public:
void OnConnect(SOCKET s) override
{
assert(_network_content_client.sock == INVALID_SOCKET);
_network_content_client.lastActivity = _realtime_tick;
_network_content_client.lastActivity = std::chrono::steady_clock::now();
_network_content_client.isConnecting = false;
_network_content_client.sock = s;
_network_content_client.Reopen();
@ -787,7 +787,7 @@ void ClientNetworkContentSocketHandler::SendReceive()
{
if (this->sock == INVALID_SOCKET || this->isConnecting) return;
if (this->lastActivity + IDLE_TIMEOUT < _realtime_tick) {
if (std::chrono::steady_clock::now() > this->lastActivity + IDLE_TIMEOUT) {
this->Close();
return;
}
@ -795,7 +795,7 @@ void ClientNetworkContentSocketHandler::SendReceive()
if (this->CanSendReceive()) {
if (this->ReceivePackets()) {
/* Only update activity once a packet is received, instead of every time we try it. */
this->lastActivity = _realtime_tick;
this->lastActivity = std::chrono::steady_clock::now();
}
}

@ -74,7 +74,7 @@ protected:
FILE *curFile; ///< Currently downloaded file
ContentInfo *curInfo; ///< Information about the currently downloaded file
bool isConnecting; ///< Whether we're connecting
uint32 lastActivity; ///< The last time there was network activity
std::chrono::steady_clock::time_point lastActivity; ///< The last time there was network activity
friend class NetworkContentConnecter;
@ -100,7 +100,7 @@ protected:
void DownloadSelectedContentFallback(const ContentIDList &content);
public:
/** The idle timeout; when to close the connection because it's idle. */
static const int IDLE_TIMEOUT = 60 * 1000;
static constexpr std::chrono::seconds IDLE_TIMEOUT = std::chrono::seconds(60);
ClientNetworkContentSocketHandler();
~ClientNetworkContentSocketHandler();

@ -1932,7 +1932,7 @@ void NetworkServer_Tick(bool send_frame)
case NetworkClientSocket::STATUS_ACTIVE:
if (lag > _settings_client.network.max_lag_time) {
/* Client did still not report in within the specified limit. */
IConsolePrintF(CC_ERROR, cs->last_packet + lag * MILLISECONDS_PER_TICK > _realtime_tick ?
IConsolePrintF(CC_ERROR, cs->last_packet + std::chrono::milliseconds(lag * MILLISECONDS_PER_TICK) > std::chrono::steady_clock::now() ?
/* A packet was received in the last three game days, so the client is likely lagging behind. */
"Client #%d is dropped because the client's game state is more than %d ticks behind" :
/* No packet was received in the last three game days; sounds like a lost connection. */
@ -1943,11 +1943,11 @@ void NetworkServer_Tick(bool send_frame)
}
/* Report once per time we detect the lag, and only when we
* received a packet in the last 2000 milliseconds. If we
* received a packet in the last 2 seconds. If we
* did not receive a packet, then the client is not just
* slow, but the connection is likely severed. Mentioning
* frame_freq is not useful in this case. */
if (lag > (uint)DAY_TICKS && cs->lag_test == 0 && cs->last_packet + 2000 > _realtime_tick) {
if (lag > (uint)DAY_TICKS && cs->lag_test == 0 && cs->last_packet + std::chrono::seconds(2) > std::chrono::steady_clock::now()) {
IConsolePrintF(CC_WARNING, "[%d] Client #%d is slow, try increasing [network.]frame_freq to a higher value!", _frame_counter, cs->client_id);
cs->lag_test = 1;
}

@ -47,8 +47,8 @@ static std::mutex _network_udp_mutex;
/** Session key to register ourselves to the master server */
static uint64 _session_key = 0;
static const uint32 ADVERTISE_NORMAL_INTERVAL = 15 * 60 * 1000; ///< interval between advertising in ms (15 minutes)
static const uint32 ADVERTISE_RETRY_INTERVAL = 10 * 1000; ///< re-advertise when no response after this many ms (10 seconds)
static const std::chrono::minutes ADVERTISE_NORMAL_INTERVAL(15); ///< interval between advertising.
static const std::chrono::seconds ADVERTISE_RETRY_INTERVAL(10); ///< re-advertise when no response after this amount of time.
static const uint32 ADVERTISE_RETRY_TIMES = 3; ///< give up re-advertising after this much failed retries
NetworkUDPSocketHandler *_udp_client_socket = nullptr; ///< udp client socket
@ -655,37 +655,29 @@ static void NetworkUDPAdvertiseThread()
*/
void NetworkUDPAdvertise()
{
static uint32 _last_advertisement = 0; ///< The time of the last advertisement (used to check for wrapping of time)
static uint32 _next_advertisement = 0; ///< The next time we should perform a normal advertisement.
static uint32 _next_retry = 0; ///< The next time we should perform a retry of an advertisement.
static std::chrono::steady_clock::time_point _last_advertisement = {}; ///< The last time we performed an advertisement.
/* Check if we should send an advertise */
if (!_networking || !_network_server || !_network_udp_server || !_settings_client.network.server_advertise) return;
if (_network_need_advertise || _realtime_tick < _last_advertisement) {
/* Forced advertisement, or a wrapping of time in which case we determine the advertisement/retry times again. */
if (_network_need_advertise) {
/* Forced advertisement. */
_network_need_advertise = false;
_network_advertise_retries = ADVERTISE_RETRY_TIMES;
} else {
/* Only send once every ADVERTISE_NORMAL_INTERVAL ticks */
if (_network_advertise_retries == 0) {
if (_realtime_tick <= _next_advertisement) return;
if (std::chrono::steady_clock::now() <= _last_advertisement + ADVERTISE_NORMAL_INTERVAL) return;
_network_advertise_retries = ADVERTISE_RETRY_TIMES;
} else {
/* An actual retry. */
if (_realtime_tick <= _next_retry) return;
if (std::chrono::steady_clock::now() <= _last_advertisement + ADVERTISE_RETRY_INTERVAL) return;
}
}
_network_advertise_retries--;
_last_advertisement = _realtime_tick;
_next_advertisement = _realtime_tick + ADVERTISE_NORMAL_INTERVAL;
_next_retry = _realtime_tick + ADVERTISE_RETRY_INTERVAL;
/* Make sure we do not have an overflow when checking these; when time wraps, we simply force an advertisement. */
if (_next_advertisement < _last_advertisement) _next_advertisement = UINT32_MAX;
if (_next_retry < _last_advertisement) _next_retry = UINT32_MAX;
_last_advertisement = std::chrono::steady_clock::now();
if (!StartNewThread(nullptr, "ottd:udp-advert", &NetworkUDPAdvertiseThread)) {
NetworkUDPAdvertiseThread();

Loading…
Cancel
Save