2009-08-21 20:21:05 +00:00
/*
* This file is part of OpenTTD .
* OpenTTD is free software ; you can redistribute it and / or modify it under the terms of the GNU General Public License as published by the Free Software Foundation , version 2.
* OpenTTD is distributed in the hope that it will be useful , but WITHOUT ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
* See the GNU General Public License for more details . You should have received a copy of the GNU General Public License along with OpenTTD . If not , see < http : //www.gnu.org/licenses/>.
*/
2007-02-23 08:37:33 +00:00
/**
* @ file network_gamelist . cpp This file handles the GameList
* Also , it handles the request to a server for data about the server
*/
2007-01-02 17:34:03 +00:00
# include "../stdafx.h"
# include "../debug.h"
2011-02-08 20:51:30 +00:00
# include "../window_func.h"
2008-05-30 18:20:26 +00:00
# include "network_internal.h"
2007-02-01 21:04:40 +00:00
# include "network_udp.h"
2007-02-02 21:32:58 +00:00
# include "network_gamelist.h"
2019-03-17 10:05:38 +00:00
# include <atomic>
2007-02-02 21:32:58 +00:00
2014-04-23 20:13:33 +00:00
# include "../safeguards.h"
2019-04-10 21:07:06 +00:00
NetworkGameList * _network_game_list = nullptr ;
2007-02-01 21:04:40 +00:00
2011-05-02 16:14:23 +00:00
/** The games to insert when the GUI thread has time for us. */
2019-04-10 21:07:06 +00:00
static std : : atomic < NetworkGameList * > _network_game_delayed_insertion_list ( nullptr ) ;
2009-01-20 03:44:43 +00:00
2010-08-01 19:22:34 +00:00
/**
* Add a new item to the linked gamelist , but do it delayed in the next tick
2009-01-20 03:44:43 +00:00
* or so to prevent race conditions .
* @ param item the item to add . Will be freed once added .
*/
void NetworkGameListAddItemDelayed ( NetworkGameList * item )
{
2019-03-17 10:05:38 +00:00
item - > next = _network_game_delayed_insertion_list . load ( std : : memory_order_relaxed ) ;
while ( ! _network_game_delayed_insertion_list . compare_exchange_weak ( item - > next , item , std : : memory_order_acq_rel ) ) { }
2009-01-20 03:44:43 +00:00
}
/** Perform the delayed (thread safe) insertion into the game list */
static void NetworkGameListHandleDelayedInsert ( )
{
2019-03-17 10:05:38 +00:00
while ( true ) {
NetworkGameList * ins_item = _network_game_delayed_insertion_list . load ( std : : memory_order_relaxed ) ;
2019-04-10 21:07:06 +00:00
while ( ins_item ! = nullptr & & ! _network_game_delayed_insertion_list . compare_exchange_weak ( ins_item , ins_item - > next , std : : memory_order_acq_rel ) ) { }
if ( ins_item = = nullptr ) break ; // No item left.
2009-01-20 03:44:43 +00:00
2021-05-05 21:21:14 +00:00
NetworkGameList * item = NetworkGameListAddItem ( ins_item - > connection_string ) ;
2009-01-20 03:44:43 +00:00
2019-04-10 21:07:06 +00:00
if ( item ! = nullptr ) {
2021-05-06 14:19:00 +00:00
if ( item - > info . server_name . empty ( ) ) {
2010-01-06 20:49:24 +00:00
ClearGRFConfigList ( & item - > info . grfconfig ) ;
2021-05-06 14:19:00 +00:00
item - > info = { } ;
item - > info . server_name = ins_item - > info . server_name ;
2009-01-20 03:44:43 +00:00
item - > online = false ;
}
2009-04-03 12:49:58 +00:00
item - > manually | = ins_item - > manually ;
2009-07-29 16:45:51 +00:00
if ( item - > manually ) NetworkRebuildHostList ( ) ;
2012-03-25 19:46:59 +00:00
UpdateNetworkGameWindow ( ) ;
2009-01-20 03:44:43 +00:00
}
2021-05-04 17:30:25 +00:00
delete ins_item ;
2009-01-20 03:44:43 +00:00
}
}
2010-08-01 19:22:34 +00:00
/**
* Add a new item to the linked gamelist . If the IP and Port match
2006-01-26 13:01:53 +00:00
* return the existing item instead of adding it again
2009-04-03 11:02:41 +00:00
* @ param address the address of the to - be added item
2010-08-01 19:44:49 +00:00
* @ return a point to the newly added or already existing item
*/
2021-05-05 21:21:14 +00:00
NetworkGameList * NetworkGameListAddItem ( const std : : string & connection_string )
2004-12-04 17:54:56 +00:00
{
2006-01-25 19:03:50 +00:00
NetworkGameList * item , * prev_item ;
2004-12-04 17:54:56 +00:00
2021-05-05 21:21:14 +00:00
/* Parse the connection string to ensure the default port is there. */
const std : : string resolved_connection_string = ParseConnectionString ( connection_string , NETWORK_DEFAULT_PORT ) . GetAddressAsString ( false ) ;
2019-04-10 21:07:06 +00:00
prev_item = nullptr ;
for ( item = _network_game_list ; item ! = nullptr ; item = item - > next ) {
2021-05-05 21:21:14 +00:00
if ( item - > connection_string = = resolved_connection_string ) return item ;
2006-01-25 19:03:50 +00:00
prev_item = item ;
2004-12-04 17:54:56 +00:00
}
2021-05-04 17:30:25 +00:00
item = new NetworkGameList ( resolved_connection_string ) ;
2006-01-25 19:03:50 +00:00
2019-04-10 21:07:06 +00:00
if ( prev_item = = nullptr ) {
2006-06-27 21:25:53 +00:00
_network_game_list = item ;
} else {
prev_item - > next = item ;
}
2004-12-04 17:54:56 +00:00
2012-03-25 19:46:59 +00:00
UpdateNetworkGameWindow ( ) ;
2004-12-04 17:54:56 +00:00
return item ;
}
2010-08-01 19:22:34 +00:00
/**
* Remove an item from the gamelist linked list
2010-08-01 19:44:49 +00:00
* @ param remove pointer to the item to be removed
*/
2004-12-20 22:14:39 +00:00
void NetworkGameListRemoveItem ( NetworkGameList * remove )
{
2019-04-10 21:07:06 +00:00
NetworkGameList * prev_item = nullptr ;
for ( NetworkGameList * item = _network_game_list ; item ! = nullptr ; item = item - > next ) {
2006-01-25 19:03:50 +00:00
if ( remove = = item ) {
2019-04-10 21:07:06 +00:00
if ( prev_item = = nullptr ) {
2006-06-27 21:25:53 +00:00
_network_game_list = remove - > next ;
} else {
prev_item - > next = remove - > next ;
}
2004-12-20 22:14:39 +00:00
2006-12-18 12:26:55 +00:00
/* Remove GRFConfig information */
2006-12-20 21:17:33 +00:00
ClearGRFConfigList ( & remove - > info . grfconfig ) ;
2021-05-04 17:30:25 +00:00
delete remove ;
2006-12-20 21:17:33 +00:00
2009-07-29 16:45:51 +00:00
NetworkRebuildHostList ( ) ;
2012-03-25 19:46:59 +00:00
UpdateNetworkGameWindow ( ) ;
2004-12-20 22:14:39 +00:00
return ;
}
2006-01-25 19:03:50 +00:00
prev_item = item ;
2004-12-20 22:14:39 +00:00
}
}
2010-05-13 10:14:29 +00:00
static const uint MAX_GAME_LIST_REQUERY_COUNT = 10 ; ///< How often do we requery in number of times per server?
static const uint REQUERY_EVERY_X_GAMELOOPS = 60 ; ///< How often do we requery in time?
static const uint REFRESH_GAMEINFO_X_REQUERIES = 50 ; ///< Refresh the game info itself after REFRESH_GAMEINFO_X_REQUERIES * REQUERY_EVERY_X_GAMELOOPS game loops
2007-02-01 21:04:40 +00:00
/** Requeries the (game) servers we have not gotten a reply from */
2007-03-07 11:47:46 +00:00
void NetworkGameListRequery ( )
2007-02-01 21:04:40 +00:00
{
2009-01-20 03:44:43 +00:00
NetworkGameListHandleDelayedInsert ( ) ;
2007-02-01 21:04:40 +00:00
static uint8 requery_cnt = 0 ;
2007-07-26 09:53:58 +00:00
if ( + + requery_cnt < REQUERY_EVERY_X_GAMELOOPS ) return ;
2007-02-01 21:04:40 +00:00
requery_cnt = 0 ;
2019-04-10 21:07:06 +00:00
for ( NetworkGameList * item = _network_game_list ; item ! = nullptr ; item = item - > next ) {
2007-07-26 09:53:58 +00:00
item - > retries + + ;
if ( item - > retries < REFRESH_GAMEINFO_X_REQUERIES & & ( item - > online | | item - > retries > = MAX_GAME_LIST_REQUERY_COUNT ) ) continue ;
2007-02-01 21:04:40 +00:00
/* item gets mostly zeroed by NetworkUDPQueryServer */
uint8 retries = item - > retries ;
2021-05-05 21:21:14 +00:00
NetworkUDPQueryServer ( item - > connection_string ) ;
2007-07-26 09:53:58 +00:00
item - > retries = ( retries > = REFRESH_GAMEINFO_X_REQUERIES ) ? 0 : retries ;
2007-02-01 21:04:40 +00:00
}
}
2009-09-17 21:14:16 +00:00
/**
* Rebuild the GRFConfig ' s of the servers in the game list as we did
* a rescan and might have found new NewGRFs .
*/
void NetworkAfterNewGRFScan ( )
{
2019-04-10 21:07:06 +00:00
for ( NetworkGameList * item = _network_game_list ; item ! = nullptr ; item = item - > next ) {
2012-12-01 13:12:39 +00:00
/* Reset compatibility state */
2009-09-17 21:14:16 +00:00
item - > info . compatible = item - > info . version_compatible ;
2019-04-10 21:07:06 +00:00
for ( GRFConfig * c = item - > info . grfconfig ; c ! = nullptr ; c = c - > next ) {
2009-09-17 21:14:16 +00:00
assert ( HasBit ( c - > flags , GCF_COPY ) ) ;
2010-10-17 12:12:13 +00:00
const GRFConfig * f = FindGRFConfig ( c - > ident . grfid , FGCM_EXACT , c - > ident . md5sum ) ;
2019-04-10 21:07:06 +00:00
if ( f = = nullptr ) {
2009-09-17 21:14:16 +00:00
/* Don't know the GRF, so mark game incompatible and the (possibly)
* already resolved name for this GRF ( another server has sent the
2012-12-01 13:12:39 +00:00
* name of the GRF already . */
2011-03-03 18:47:46 +00:00
c - > name = FindUnknownGRFName ( c - > ident . grfid , c - > ident . md5sum , true ) ;
2009-09-17 21:14:16 +00:00
c - > status = GCS_NOT_FOUND ;
2012-12-01 13:12:39 +00:00
/* If we miss a file, we're obviously incompatible. */
2009-09-17 21:14:16 +00:00
item - > info . compatible = false ;
} else {
2011-03-03 18:47:46 +00:00
c - > filename = f - > filename ;
c - > name = f - > name ;
c - > info = f - > info ;
c - > status = GCS_UNKNOWN ;
2009-09-17 21:14:16 +00:00
}
}
}
2011-02-08 20:51:30 +00:00
InvalidateWindowClassesData ( WC_NETWORK_WINDOW ) ;
2009-09-17 21:14:16 +00:00
}