2005-07-24 14:12:37 +00:00
/* $Id$ */
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
*/
2006-10-12 14:13:39 +00:00
# ifdef ENABLE_NETWORK
2007-01-02 17:34:03 +00:00
# include "../stdafx.h"
# include "../debug.h"
2009-09-01 10:07:22 +00:00
# include "../thread/thread.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"
NetworkGameList * _network_game_list = NULL ;
2007-02-01 21:04:40 +00:00
2009-11-09 09:59:35 +00:00
static ThreadMutex * _network_game_list_mutex = ThreadMutex : : New ( ) ;
static NetworkGameList * _network_game_delayed_insertion_list = NULL ;
2009-01-20 03:44:43 +00:00
/** Add a new item to the linked gamelist, but do it delayed in the next tick
* or so to prevent race conditions .
* @ param item the item to add . Will be freed once added .
*/
void NetworkGameListAddItemDelayed ( NetworkGameList * item )
{
_network_game_list_mutex - > BeginCritical ( ) ;
item - > next = _network_game_delayed_insertion_list ;
_network_game_delayed_insertion_list = item ;
_network_game_list_mutex - > EndCritical ( ) ;
}
/** Perform the delayed (thread safe) insertion into the game list */
static void NetworkGameListHandleDelayedInsert ( )
{
_network_game_list_mutex - > BeginCritical ( ) ;
while ( _network_game_delayed_insertion_list ! = NULL ) {
NetworkGameList * ins_item = _network_game_delayed_insertion_list ;
_network_game_delayed_insertion_list = ins_item - > next ;
2009-04-02 20:17:46 +00:00
NetworkGameList * item = NetworkGameListAddItem ( ins_item - > address ) ;
2009-01-20 03:44:43 +00:00
if ( item ! = NULL ) {
if ( StrEmpty ( item - > info . server_name ) ) {
2010-01-06 20:49:24 +00:00
ClearGRFConfigList ( & item - > info . grfconfig ) ;
2009-01-20 03:44:43 +00:00
memset ( & item - > info , 0 , sizeof ( item - > info ) ) ;
strecpy ( item - > info . server_name , ins_item - > info . server_name , lastof ( item - > info . server_name ) ) ;
strecpy ( item - > info . hostname , ins_item - > info . hostname , lastof ( item - > info . hostname ) ) ;
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 ( ) ;
2009-01-20 03:44:43 +00:00
UpdateNetworkGameWindow ( false ) ;
}
free ( ins_item ) ;
}
_network_game_list_mutex - > EndCritical ( ) ;
}
2006-01-26 13:01:53 +00:00
/** Add a new item to the linked gamelist. If the IP and Port match
* 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
2006-01-26 13:01:53 +00:00
* @ param port the port the server is running on
* @ return a point to the newly added or already existing item */
2009-04-02 20:17:46 +00:00
NetworkGameList * NetworkGameListAddItem ( NetworkAddress address )
2004-12-04 17:54:56 +00:00
{
2009-04-08 21:16:24 +00:00
const char * hostname = address . GetHostname ( ) ;
/* Do not query the 'any' address. */
if ( StrEmpty ( hostname ) | |
strcmp ( hostname , " 0.0.0.0 " ) = = 0 | |
strcmp ( hostname , " :: " ) = = 0 ) {
return NULL ;
}
2008-04-14 20:31:21 +00:00
2006-01-25 19:03:50 +00:00
NetworkGameList * item , * prev_item ;
2004-12-04 17:54:56 +00:00
2006-01-25 19:03:50 +00:00
prev_item = NULL ;
for ( item = _network_game_list ; item ! = NULL ; item = item - > next ) {
2009-04-02 20:17:46 +00:00
if ( item - > address = = address ) return item ;
2006-01-25 19:03:50 +00:00
prev_item = item ;
2004-12-04 17:54:56 +00:00
}
2009-01-20 03:44:43 +00:00
item = CallocT < NetworkGameList > ( 1 ) ;
2004-12-04 17:54:56 +00:00
item - > next = NULL ;
2009-04-02 20:17:46 +00:00
item - > address = address ;
2006-01-25 19:03:50 +00:00
2006-06-27 21:25:53 +00:00
if ( prev_item = = NULL ) {
_network_game_list = item ;
} else {
prev_item - > next = item ;
}
2006-12-26 17:36:18 +00:00
DEBUG ( net , 4 , " [gamelist] added server to list " ) ;
2004-12-04 17:54:56 +00:00
UpdateNetworkGameWindow ( false ) ;
return item ;
}
2006-01-26 13:01:53 +00:00
/** Remove an item from the gamelist linked list
* @ param remove pointer to the item to be removed */
2004-12-20 22:14:39 +00:00
void NetworkGameListRemoveItem ( NetworkGameList * remove )
{
2009-04-09 01:16:15 +00:00
NetworkGameList * prev_item = NULL ;
for ( NetworkGameList * item = _network_game_list ; item ! = NULL ; item = item - > next ) {
2006-01-25 19:03:50 +00:00
if ( remove = = item ) {
2006-06-27 21:25:53 +00:00
if ( prev_item = = NULL ) {
_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 ) ;
2004-12-20 22:14:39 +00:00
free ( remove ) ;
2006-12-20 21:17:33 +00:00
remove = NULL ;
2006-12-26 17:36:18 +00:00
DEBUG ( net , 4 , " [gamelist] removed server from list " ) ;
2009-07-29 16:45:51 +00:00
NetworkRebuildHostList ( ) ;
2006-01-25 19:03:50 +00:00
UpdateNetworkGameWindow ( false ) ;
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 ;
2009-01-20 01:32:06 +00:00
for ( NetworkGameList * item = _network_game_list ; item ! = NULL ; 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 ;
2009-04-02 20:17:46 +00:00
NetworkUDPQueryServer ( NetworkAddress ( item - > address ) ) ;
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 ( )
{
for ( NetworkGameList * item = _network_game_list ; item ! = NULL ; item = item - > next ) {
/* Reset compatability state */
item - > info . compatible = item - > info . version_compatible ;
for ( GRFConfig * c = item - > info . grfconfig ; c ! = NULL ; c = c - > next ) {
assert ( HasBit ( c - > flags , GCF_COPY ) ) ;
2010-02-25 20:05:31 +00:00
const GRFConfig * f = FindGRFConfig ( c - > ident . grfid , c - > ident . md5sum ) ;
2009-09-17 21:14:16 +00:00
if ( f = = NULL ) {
/* Don't know the GRF, so mark game incompatible and the (possibly)
* already resolved name for this GRF ( another server has sent the
* name of the GRF already */
2010-02-25 20:05:31 +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 ;
/* If we miss a file, we're obviously incompatible */
item - > info . compatible = false ;
} else {
c - > filename = f - > filename ;
c - > name = f - > name ;
c - > info = f - > info ;
c - > status = GCS_UNKNOWN ;
}
}
}
}
2004-12-04 17:54:56 +00:00
# endif /* ENABLE_NETWORK */