2005-07-24 16:12:37 +02:00
/* $Id$ */
2009-08-21 22:21:05 +02: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 09:37:33 +01: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 16:13:39 +02:00
# ifdef ENABLE_NETWORK
2007-01-02 18:34:03 +01:00
# include "../stdafx.h"
# include "../debug.h"
2009-09-01 12:07:22 +02:00
# include "../thread/thread.h"
2008-05-30 20:20:26 +02:00
# include "network_internal.h"
2007-02-01 22:04:40 +01:00
# include "network_udp.h"
2007-02-02 22:32:58 +01:00
# include "network_gamelist.h"
2010-07-31 11:33:39 +02:00
# include "../newgrf_text.h"
2007-02-02 22:32:58 +01:00
NetworkGameList * _network_game_list = NULL ;
2007-02-01 22:04:40 +01:00
2009-11-09 10:59:35 +01:00
static ThreadMutex * _network_game_list_mutex = ThreadMutex : : New ( ) ;
static NetworkGameList * _network_game_delayed_insertion_list = NULL ;
2009-01-20 04:44:43 +01: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 22:17:46 +02:00
NetworkGameList * item = NetworkGameListAddItem ( ins_item - > address ) ;
2009-01-20 04:44:43 +01:00
if ( item ! = NULL ) {
if ( StrEmpty ( item - > info . server_name ) ) {
2010-01-06 21:49:24 +01:00
ClearGRFConfigList ( & item - > info . grfconfig ) ;
2009-01-20 04:44:43 +01: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 14:49:58 +02:00
item - > manually | = ins_item - > manually ;
2009-07-29 18:45:51 +02:00
if ( item - > manually ) NetworkRebuildHostList ( ) ;
2009-01-20 04:44:43 +01:00
UpdateNetworkGameWindow ( false ) ;
}
free ( ins_item ) ;
}
_network_game_list_mutex - > EndCritical ( ) ;
}
2006-01-26 14:01:53 +01: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 13:02:41 +02:00
* @ param address the address of the to - be added item
2006-01-26 14:01:53 +01:00
* @ param port the port the server is running on
* @ return a point to the newly added or already existing item */
2009-04-02 22:17:46 +02:00
NetworkGameList * NetworkGameListAddItem ( NetworkAddress address )
2004-12-04 18:54:56 +01:00
{
2009-04-08 23:16:24 +02: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 22:31:21 +02:00
2006-01-25 20:03:50 +01:00
NetworkGameList * item , * prev_item ;
2004-12-04 18:54:56 +01:00
2006-01-25 20:03:50 +01:00
prev_item = NULL ;
for ( item = _network_game_list ; item ! = NULL ; item = item - > next ) {
2009-04-02 22:17:46 +02:00
if ( item - > address = = address ) return item ;
2006-01-25 20:03:50 +01:00
prev_item = item ;
2004-12-04 18:54:56 +01:00
}
2009-01-20 04:44:43 +01:00
item = CallocT < NetworkGameList > ( 1 ) ;
2004-12-04 18:54:56 +01:00
item - > next = NULL ;
2009-04-02 22:17:46 +02:00
item - > address = address ;
2006-01-25 20:03:50 +01:00
2006-06-27 23:25:53 +02:00
if ( prev_item = = NULL ) {
_network_game_list = item ;
} else {
prev_item - > next = item ;
}
2006-12-26 18:36:18 +01:00
DEBUG ( net , 4 , " [gamelist] added server to list " ) ;
2004-12-04 18:54:56 +01:00
UpdateNetworkGameWindow ( false ) ;
return item ;
}
2006-01-26 14:01:53 +01:00
/** Remove an item from the gamelist linked list
* @ param remove pointer to the item to be removed */
2004-12-20 23:14:39 +01:00
void NetworkGameListRemoveItem ( NetworkGameList * remove )
{
2009-04-09 03:16:15 +02:00
NetworkGameList * prev_item = NULL ;
for ( NetworkGameList * item = _network_game_list ; item ! = NULL ; item = item - > next ) {
2006-01-25 20:03:50 +01:00
if ( remove = = item ) {
2006-06-27 23:25:53 +02:00
if ( prev_item = = NULL ) {
_network_game_list = remove - > next ;
} else {
prev_item - > next = remove - > next ;
}
2004-12-20 23:14:39 +01:00
2006-12-18 13:26:55 +01:00
/* Remove GRFConfig information */
2006-12-20 22:17:33 +01:00
ClearGRFConfigList ( & remove - > info . grfconfig ) ;
2004-12-20 23:14:39 +01:00
free ( remove ) ;
2006-12-20 22:17:33 +01:00
remove = NULL ;
2006-12-26 18:36:18 +01:00
DEBUG ( net , 4 , " [gamelist] removed server from list " ) ;
2009-07-29 18:45:51 +02:00
NetworkRebuildHostList ( ) ;
2006-01-25 20:03:50 +01:00
UpdateNetworkGameWindow ( false ) ;
2004-12-20 23:14:39 +01:00
return ;
}
2006-01-25 20:03:50 +01:00
prev_item = item ;
2004-12-20 23:14:39 +01:00
}
}
2010-05-13 12:14:29 +02: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 22:04:40 +01:00
/** Requeries the (game) servers we have not gotten a reply from */
2007-03-07 12:47:46 +01:00
void NetworkGameListRequery ( )
2007-02-01 22:04:40 +01:00
{
2009-01-20 04:44:43 +01:00
NetworkGameListHandleDelayedInsert ( ) ;
2007-02-01 22:04:40 +01:00
static uint8 requery_cnt = 0 ;
2007-07-26 11:53:58 +02:00
if ( + + requery_cnt < REQUERY_EVERY_X_GAMELOOPS ) return ;
2007-02-01 22:04:40 +01:00
requery_cnt = 0 ;
2009-01-20 02:32:06 +01:00
for ( NetworkGameList * item = _network_game_list ; item ! = NULL ; item = item - > next ) {
2007-07-26 11:53:58 +02:00
item - > retries + + ;
if ( item - > retries < REFRESH_GAMEINFO_X_REQUERIES & & ( item - > online | | item - > retries > = MAX_GAME_LIST_REQUERY_COUNT ) ) continue ;
2007-02-01 22:04:40 +01:00
/* item gets mostly zeroed by NetworkUDPQueryServer */
uint8 retries = item - > retries ;
2009-04-02 22:17:46 +02:00
NetworkUDPQueryServer ( NetworkAddress ( item - > address ) ) ;
2007-07-26 11:53:58 +02:00
item - > retries = ( retries > = REFRESH_GAMEINFO_X_REQUERIES ) ? 0 : retries ;
2007-02-01 22:04:40 +01:00
}
}
2009-09-17 23:14:16 +02: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 21:05:31 +01:00
const GRFConfig * f = FindGRFConfig ( c - > ident . grfid , c - > ident . md5sum ) ;
2009-09-17 23:14:16 +02: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-07-31 11:33:39 +02:00
AddGRFTextToList ( & c - > name , FindUnknownGRFName ( c - > ident . grfid , c - > ident . md5sum , true ) ) ;
2009-09-17 23:14:16 +02: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 18:54:56 +01:00
# endif /* ENABLE_NETWORK */