From ff5c05c1b41196589b1bf847a4973ef812e1ddfc Mon Sep 17 00:00:00 2001 From: rubidium Date: Sat, 19 Sep 2015 16:49:46 +0000 Subject: (svn r27400) -Fix [FS#6368] (r26449): when a dedicated server was paused with no clients the tick length was increased significantly, making any assumptions about the tick length used further down in the code are not true anymore. One of such assumptions was that one should readvertise every 15 minutes worth of original ticks, but due to the lengthening this timeframe would be more like 45-60 minutes. Now we'll take the operating system's millisecond counter instead --- src/network/network_udp.cpp | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'src/network/network_udp.cpp') diff --git a/src/network/network_udp.cpp b/src/network/network_udp.cpp index 731d51ca0..1cccbf644 100644 --- a/src/network/network_udp.cpp +++ b/src/network/network_udp.cpp @@ -42,9 +42,9 @@ static ThreadMutex *_network_udp_mutex = ThreadMutex::New(); /** Session key to register ourselves to the master server */ static uint64 _session_key = 0; -static const uint ADVERTISE_NORMAL_INTERVAL = 30000; ///< interval between advertising in ticks (15 minutes) -static const uint ADVERTISE_RETRY_INTERVAL = 300; ///< re-advertise when no response after this many ticks (9 seconds) -static const uint ADVERTISE_RETRY_TIMES = 3; ///< give up re-advertising after this much failed retries +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 uint32 ADVERTISE_RETRY_TIMES = 3; ///< give up re-advertising after this much failed retries NetworkUDPSocketHandler *_udp_client_socket = NULL; ///< udp client socket NetworkUDPSocketHandler *_udp_server_socket = NULL; ///< udp server socket @@ -616,25 +616,37 @@ static void NetworkUDPAdvertiseThread(void *pntr) */ 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. + /* Check if we should send an advertise */ if (!_networking || !_network_server || !_network_udp_server || !_settings_client.network.server_advertise) return; - if (_network_need_advertise) { + 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. */ _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 ((_network_last_advertise_frame + ADVERTISE_NORMAL_INTERVAL) > _frame_counter) return; + if (_realtime_tick <= _next_advertisement) return; _network_advertise_retries = ADVERTISE_RETRY_TIMES; + } else { + /* An actual retry. */ + if (_realtime_tick <= _next_retry) return; } - - if ((_network_last_advertise_frame + ADVERTISE_RETRY_INTERVAL) > _frame_counter) return; } _network_advertise_retries--; - _network_last_advertise_frame = _frame_counter; + _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; if (!ThreadObject::New(NetworkUDPAdvertiseThread, NULL)) { NetworkUDPAdvertiseThread(NULL); -- cgit v1.2.3-70-g09d2