1
0
Fork 0

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

pull/8752/head
Patric Stout 2021-02-25 20:30:16 +01:00 committed by Patric Stout
parent dc7ba33b51
commit 53c28a8ec9
10 changed files with 39 additions and 49 deletions

View File

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

View File

@ -16,6 +16,7 @@
#include "tcp.h" #include "tcp.h"
#include "../network_type.h" #include "../network_type.h"
#include "../../core/pool_type.hpp" #include "../../core/pool_type.hpp"
#include <chrono>
/** /**
* Enum with all types of TCP packets. * Enum with all types of TCP packets.
@ -518,7 +519,7 @@ public:
uint32 last_frame; ///< Last frame we have executed uint32 last_frame; ///< Last frame we have executed
uint32 last_frame_server; ///< Last frame the server has executed uint32 last_frame_server; ///< Last frame the server has executed
CommandQueue incoming_queue; ///< The command-queue awaiting handling 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; NetworkRecvStatus CloseConnection(bool error = true) override;

View File

@ -37,7 +37,7 @@ NetworkAdminSocketPool _networkadminsocket_pool("NetworkAdminSocket");
INSTANTIATE_POOL_METHODS(NetworkAdminSocket) INSTANTIATE_POOL_METHODS(NetworkAdminSocket)
/** The timeout for authorisation of the client. */ /** 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. */ /** Frequencies, which may be registered for a certain update type. */
@ -64,7 +64,7 @@ ServerNetworkAdminSocketHandler::ServerNetworkAdminSocketHandler(SOCKET s) : Net
{ {
_network_admins_connected++; _network_admins_connected++;
this->status = ADMIN_STATUS_INACTIVE; 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() /* static */ void ServerNetworkAdminSocketHandler::Send()
{ {
for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::Iterate()) { for (ServerNetworkAdminSocketHandler *as : ServerNetworkAdminSocketHandler::Iterate()) {
if (as->status == ADMIN_STATUS_INACTIVE && as->realtime_connect + ADMIN_AUTHORISATION_TIMEOUT < _realtime_tick) { 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", ADMIN_AUTHORISATION_TIMEOUT / 1000); 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); as->CloseConnection(true);
continue; continue;
} }

View File

@ -37,7 +37,7 @@ protected:
NetworkRecvStatus SendPong(uint32 d1); NetworkRecvStatus SendPong(uint32 d1);
public: public:
AdminUpdateFrequency update_frequency[ADMIN_UPDATE_END]; ///< Admin requested update intervals. 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. NetworkAddress address; ///< Address of the admin.
ServerNetworkAdminSocketHandler(SOCKET s); ServerNetworkAdminSocketHandler(SOCKET s);

View File

@ -40,7 +40,7 @@ static const uint NETWORK_CHAT_LINE_SPACING = 3;
struct ChatMessage { struct ChatMessage {
char message[DRAW_STRING_BUFFER]; ///< The action message. char message[DRAW_STRING_BUFFER]; ///< The action message.
TextColour colour; ///< The colour of the 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 */ /* used for chat window */
@ -97,7 +97,7 @@ void CDECL NetworkAddChatMessage(TextColour colour, uint duration, const char *m
ChatMessage *cmsg = &_chatmsg_list[msg_count++]; ChatMessage *cmsg = &_chatmsg_list[msg_count++];
strecpy(cmsg->message, buf, lastof(cmsg->message)); strecpy(cmsg->message, buf, lastof(cmsg->message));
cmsg->colour = (colour & TC_IS_PALETTE_COLOUR) ? colour : TC_WHITE; 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; _chatmessage_dirty = true;
} }
@ -180,7 +180,7 @@ void NetworkChatMessageLoop()
if (cmsg->message[0] == '\0') continue; if (cmsg->message[0] == '\0') continue;
/* Message has expired, remove from the list */ /* 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 */ /* 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)); if (i != MAX_CHAT_MESSAGES - 1) memmove(cmsg, cmsg + 1, sizeof(*cmsg) * (MAX_CHAT_MESSAGES - i - 1));

View File

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

View File

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

View File

@ -74,7 +74,7 @@ protected:
FILE *curFile; ///< Currently downloaded file FILE *curFile; ///< Currently downloaded file
ContentInfo *curInfo; ///< Information about the currently downloaded file ContentInfo *curInfo; ///< Information about the currently downloaded file
bool isConnecting; ///< Whether we're connecting 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; friend class NetworkContentConnecter;
@ -100,7 +100,7 @@ protected:
void DownloadSelectedContentFallback(const ContentIDList &content); void DownloadSelectedContentFallback(const ContentIDList &content);
public: public:
/** The idle timeout; when to close the connection because it's idle. */ /** 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();
~ClientNetworkContentSocketHandler(); ~ClientNetworkContentSocketHandler();

View File

@ -1816,7 +1816,7 @@ void NetworkServer_Tick(bool send_frame)
case NetworkClientSocket::STATUS_ACTIVE: case NetworkClientSocket::STATUS_ACTIVE:
if (lag > _settings_client.network.max_lag_time) { if (lag > _settings_client.network.max_lag_time) {
/* Client did still not report in within the specified limit. */ /* 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. */ /* 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" : "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. */ /* No packet was received in the last three game days; sounds like a lost connection. */
@ -1827,11 +1827,11 @@ void NetworkServer_Tick(bool send_frame)
} }
/* Report once per time we detect the lag, and only when we /* 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 * did not receive a packet, then the client is not just
* slow, but the connection is likely severed. Mentioning * slow, but the connection is likely severed. Mentioning
* frame_freq is not useful in this case. */ * 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); 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; cs->lag_test = 1;
} }

View File

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